Contract 0xb68f42c2c805b81dad78d2f07244917431c7f322

Contract Overview

Balance:
0 AVAX

AVAX Value:
$0.00

Token:
Txn Hash Method
Block
From
To
Value [Txn Fee]
0xb6da3dd50d3c84a16e88ac7839c6531cabf9b3c7f4faaa4e6e583456a6353c23Set Approval For...257233962023-02-02 5:04:042 hrs 41 mins ago0x2c812daf5b0297b935a287ad27340f2b37939f2c IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001235062203 26.712133478
0xe2d0ac3b10dd1ebd1cc0aa9d8547fea24476975545de47709f52b89d1b50c9afAdd Shirak257209792023-02-02 3:42:414 hrs 3 mins ago0x2ff445c7f72a85db44659adfb08140c59c4592a4 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.0011931625 26.5
0x1d7f5db7cb6691a1660c32c9681ee773fad72c3a3b303867d3b0848bbd7d6891Remove Shirak257206262023-02-02 3:30:494 hrs 15 mins ago0x7fdaa97f8896fd3ce42652255da289f16870a754 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001064668084 27.037129488
0xb8171e7a52c1f3e89f85c68aaf931525eed16496ef2cb5c5a1b31f2c33e1e6b2Claim Mech257198592023-02-02 3:05:024 hrs 41 mins ago0xba109916a5f1381845d6fc4a2758c1abd196ff93 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.00359021298 26.94
0x900dad59cdbdec1e707116bdb0fef6852363156cfd3c1b40196558195cc9d230Claim Mech257197162023-02-02 3:00:174 hrs 45 mins ago0x4ad9261d9c307872e995d2090212130ac50c0e5d IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.003992829732 26.55389635
0x21620f2ac7e1ed0110e38db2cdcb5a40cb9d26f84144c18a4a49dc76bb300f5aClaim Mech257194302023-02-02 2:50:494 hrs 55 mins ago0x4ad9261d9c307872e995d2090212130ac50c0e5d IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.002419973633 27.04938952
0xe3d9a2ba1d8a8dbf10bdf950457345afd560072b3fdf2e6ab64b79562aa12462Mint From Shirak257190332023-02-02 2:38:455 hrs 7 mins ago0x0bcde37655e78af6721c73e5b94a63fa2fc4069a IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.00180359 26.5
0xe052e21aef12e367a95471b0bb4b59143cb4d4ab059efafc8ad31a38092a9ddeMint From Shirak257190062023-02-02 2:37:515 hrs 8 mins ago0x0bcde37655e78af6721c73e5b94a63fa2fc4069a IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001804862 26.5
0x4c4ab6e551feb7cacf98863cde364dbc8c880692f0e84dd30ac0a16f3c05be54Add Shirak257188522023-02-02 2:32:565 hrs 13 mins ago0x39ffa0838b7b89e35dbf1ff2017001769b76dd37 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.0011922085 26.5
0x52c760df08d1e14401dee8322b6f4a125f66ddd105a6116a30e426c94438051dSafe Transfer Fr...257187092023-02-02 2:28:225 hrs 17 mins ago0x39ffa0838b7b89e35dbf1ff2017001769b76dd37 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001330088 26.5
0xb3331650ae02c5a39f8300b04467150e17ee2da4d8009267a9228f9fbb1d010dRemove Shirak257186652023-02-02 2:26:545 hrs 19 mins ago0x3aac2d9672cd0e080bf5e770fef9d2fc4e237865 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001196369 26.5
0x28734e3b815d8cbf501a7ce1bccf4515af65718c018c1f786be7dfce2ae3aa83Remove Shirak257186412023-02-02 2:26:065 hrs 19 mins ago0x3aac2d9672cd0e080bf5e770fef9d2fc4e237865 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001648565 26.5
0x4e3fdd863b7bb0d0218865461d97485656845acabecde85192bab1761556ad70Remove Shirak257186292023-02-02 2:25:425 hrs 20 mins ago0xe3840b7fd6bd307cf7d33482731c93d6bb7d106a IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001196369 26.5
0xc05731b7974ddc41be8bb7d80fdd1d10d2dd25f1e9d105655215d6b2fd8e0491Mint From Shirak257185832023-02-02 2:24:085 hrs 21 mins ago0xe3840b7fd6bd307cf7d33482731c93d6bb7d106a IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001804862 26.5
0x073e9954985269543993d110b437240a6e4ec77c68849f9f8fa93dd95765eb39Claim Mech257184242023-02-02 2:18:505 hrs 27 mins ago0x4ad9261d9c307872e995d2090212130ac50c0e5d IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.0023708225 26.5
0x9aa47266afb4bb7f9c9130c5f0fe2800b1ecbebbfa1b8a2ab231f528acf897d7Safe Transfer Fr...257173732023-02-02 1:44:156 hrs 1 min ago0xb6c5a50c28805abb41f79f7945bf3f9dfef4c8b0 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.00140369628
0x6045ee09486ed04f6a292365afe1c9b35ab30a46b9e1602edd0c91b904991f63Mint From Shirak257147562023-02-02 0:17:327 hrs 28 mins ago0x71004384c6dc48bc125cc639d9e3aed90f8fb335 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.000681008255 26.664379628
0xab620b806fb880e3c2a90a8da64adf8cd5c6933f1ba9bb261874c30f3e394d94Mint From Shirak257147472023-02-02 0:17:187 hrs 28 mins ago0x71004384c6dc48bc125cc639d9e3aed90f8fb335 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001400131344 27.44925
0xb54b656b974aed8d5a2b81be3bd134aecd3c72d26b050552cb3187c42d7f6935Add Shirak257105132023-02-01 21:56:559 hrs 49 mins ago0x90625ffe7a8759e218c3945fea8ac28fabbfa970 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.0011934805 26.5
0x4ca7aa3098ba556df95521f43030fb218613a03ace7aa0e396f46af48e486c81Set Approval For...257084562023-02-01 20:47:3510 hrs 58 mins ago0xab85dc3f89921a870c46c5f29f808de0f0db0827 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001225254 26.5
0x6af3e245f5d3d505166f540cae03b630d31fb8e9c7f2d35c516b6a4831f5fd10Claim Mech257074452023-02-01 20:13:5811 hrs 32 mins ago0x28a2ed4f01e6126357e8e8a15e7a29acaabaf84a IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.01353303 90
0xc09bc5f42216092d48cc7291ec58b10f490b37299d727b6b17cb1e4507c017e7Claim Mech257074292023-02-01 20:13:2411 hrs 32 mins ago0x28a2ed4f01e6126357e8e8a15e7a29acaabaf84a IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.01593621 90
0x6aff9b7aa30623af87a1b777c3404c7497de526741891aa674c330d2d9881be2Claim Mech257071492023-02-01 20:04:3911 hrs 41 mins ago0x7fb3993a2fbf49ee4b93dbc0a079f2622825e51b IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.002594208438 28.996908723
0x6c8f6b4e1596be3671e10382d90cb268ac420087603521932de8bff9b30b1a4aSet Approval For...257069982023-02-01 20:00:1311 hrs 45 mins ago0xf2171ae3a4f34bcb330bfd9db43b428fc43d49d3 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.001225254 26.5
0x1a24ead115f0b210767ac3665a095e5f18532dbe5b2cf561e91bbbf8ddabe432Remove Shirak257068082023-02-01 19:53:5311 hrs 52 mins ago0x25c7160789d8d16212bbd092b65133624ca826d9 IN  0xb68f42c2c805b81dad78d2f07244917431c7f3220 AVAX0.002060190193 45.646080417
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x823a9b5e1e3fa67f7b8bedb3dba08fbe83b32cb2bb2a5ee6bc9d196001932518254998272023-01-27 23:29:095 days 8 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x0b80bcd831094d35938890c8adbb39fb1dd9b2d94d8794cc7a1886a3c5b060ce254571522023-01-26 23:19:116 days 8 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x905e5140a8d38e381cbe864e9662afeca8c44e509cb3e1159a1ecbd40266fa83254552162023-01-26 22:13:256 days 9 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x5cf196fdcc8d6488d90374b3661a5d7e55186d1d4394057961d6c972d44c8496254457202023-01-26 16:50:556 days 14 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x81d47067bd4b6cb01614dcfda40ce7d85f4399104ba3a51976e042e74bfd21b5253986662023-01-25 14:17:317 days 17 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0xb4e8885f983039d3691a97d34eec5fce96d47e57ec676a1b38089bb29323880c252746812023-01-22 15:53:1110 days 15 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0xa1b86e744688ce9024a911f88d34fcd29b13ed9a42a0b93ed00bd15e2632f67d252387962023-01-21 19:35:0211 days 12 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x41b289684f24aadf8838588ecdd0b6282491cb971cdd208ff1d83f497fbce852252338432023-01-21 16:47:1811 days 14 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0xfe588f77853f0dcee4d4095244c3ab685e0e1063131412ae4739f84d819d4b55252150002023-01-21 5:59:2212 days 1 hr ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x1238d0a74dcfd845d1e44c98637a11307eb5b18c70157aabc874b7415ac2e989251996392023-01-20 21:15:3712 days 10 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0xa6373b0ce0be93c1ebe11321a8ea9d4ebe6c9bc6cb9bba09cdad944026eb179e251994572023-01-20 21:09:3412 days 10 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0xc404174912c16749ef2a62d31d0ec0e91fef5f03f83fab1b208341bf6b3528bc251987642023-01-20 20:46:3112 days 10 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0xaa9e7283703d59a8dca4d7d396f938e87495e4840fa8d0b2240686e3e981e5f1251965922023-01-20 19:34:5412 days 12 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x969a81cf8f52a194b3d65ba30b0d2ce8dce729751c1726127fbd0146fd8bfd9f251956822023-01-20 19:04:1312 days 12 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x04a419b556f832dced5cf5c2db5d4fcf2f955e5b7ba3351d69d5821470e3ee72251952562023-01-20 18:49:2612 days 12 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x4aab324898e841cc3cb586530addbd7b5ac6ee1faf241bfadaf151702c1c1462251907322023-01-20 16:17:0712 days 15 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x0172a206a334336582769d7a64ace78a4b6670cf6c8697d3465a9883ea24bba8251902512023-01-20 16:00:4312 days 15 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x0c76bda66ca8752a061333eb8821654dd121927c46723c72ab40be5032464380251888812023-01-20 15:14:0112 days 16 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x9fb0fed597485404ae8611b8fab82a2890444108f11f3b57ae3c5791dc3ddfdf251841472023-01-20 12:33:3512 days 19 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x2565437cb94ed96d6bd091a428d76823fac33fe3fec17235553b032ef3a72e77251839032023-01-20 12:25:2112 days 19 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x2e878c4f21e3cf979bae6b91790adeb6da7400d716ac5d9e0ad56ac9b1dc788c251838932023-01-20 12:25:0112 days 19 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0xc5c9132609ab7c6e0d1da54e3c6829decd7eb6f6edb0baf0f67f0f484e7b973b251798542023-01-20 10:06:2412 days 21 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x32e226dee95c30226e9fb39f7848e1fa571973d5349a56ecbd85fd40bea5cb82251781402023-01-20 9:08:2012 days 22 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0x170b92355660600280928161c2f8586363d2779b6dc7b96c1721bc97ab043849251771782023-01-20 8:36:0412 days 23 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
0xd1d8468fe098a5038d075225e10ddce40eefd4e7b34e4384f1f69f88feefb84a251765412023-01-20 8:14:4712 days 23 hrs ago 0xb68f42c2c805b81dad78d2f07244917431c7f3220xfe6beca6b73c4f4d40ba199c8a27e706963569521 AVAX
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MechAvax

Compiler Version
v0.8.13+commit.abaa5c0e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 23 : LogisticToLinearVRGDA.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {unsafeWadDiv} from "solmate/utils/SignedWadMath.sol";

import {VRGDA} from "./VRGDA.sol";
import {LogisticVRGDA} from "./LogisticVRGDA.sol";

/// @title Logistic To Linear Variable Rate Gradual Dutch Auction
/// @author transmissions11 <[email protected]>
/// @author FrankieIsLost <[email protected]>
/// @notice VRGDA with a piecewise logistic and linear issuance curve.
abstract contract LogisticToLinearVRGDA is LogisticVRGDA {
    /*//////////////////////////////////////////////////////////////
                           PRICING PARAMETERS
    //////////////////////////////////////////////////////////////*/

    /// @dev The number of tokens that must be sold for the switch to occur.
    /// @dev Represented as an 18 decimal fixed point number.
    int256 internal immutable soldBySwitch;

    /// @dev The time soldBySwitch tokens were targeted to sell by.
    /// @dev Represented as an 18 decimal fixed point number.
    int256 internal immutable switchTime;

    /// @dev The total number of tokens to target selling every full unit of time.
    /// @dev Represented as an 18 decimal fixed point number.
    int256 internal immutable perTimeUnit;

    /// @notice Sets pricing parameters for the VRGDA.
    /// @param _targetPrice The target price for a token if sold on pace, scaled by 1e18.
    /// @param _priceDecayPercent The percent price decays per unit of time with no sales, scaled by 1e18.
    /// @param _logisticAsymptote The asymptote (minus 1) of the pre-switch logistic curve, scaled by 1e18.
    /// @param _timeScale The steepness of the pre-switch logistic curve, scaled by 1e18.
    /// @param _soldBySwitch The number of tokens that must be sold for the switch to occur.
    /// @param _switchTime The time soldBySwitch tokens were targeted to sell by, scaled by 1e18.
    /// @param _perTimeUnit The number of tokens to target selling in 1 full unit of time, scaled by 1e18.
    constructor(
        int256 _targetPrice,
        int256 _priceDecayPercent,
        int256 _logisticAsymptote,
        int256 _timeScale,
        int256 _soldBySwitch,
        int256 _switchTime,
        int256 _perTimeUnit
    ) LogisticVRGDA(_targetPrice, _priceDecayPercent, _logisticAsymptote, _timeScale) {
        soldBySwitch = _soldBySwitch;

        switchTime = _switchTime;

        perTimeUnit = _perTimeUnit;
    }

    /*//////////////////////////////////////////////////////////////
                              PRICING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @dev Given a number of tokens sold, return the target time that number of tokens should be sold by.
    /// @param sold A number of tokens sold, scaled by 1e18, to get the corresponding target sale time for.
    /// @return The target time the tokens should be sold by, scaled by 1e18, where the time is
    /// relative, such that 0 means the tokens should be sold immediately when the VRGDA begins.
    function getTargetSaleTime(int256 sold) public view virtual override returns (int256) {
        // If we've not yet reached the number of sales required for the switch
        // to occur, we'll continue using the standard logistic VRGDA schedule.
        if (sold < soldBySwitch) return LogisticVRGDA.getTargetSaleTime(sold);

        unchecked {
            return unsafeWadDiv(sold - soldBySwitch, perTimeUnit) + switchTime;
        }
    }
}

File 2 of 23 : LogisticVRGDA.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {wadLn, unsafeDiv, unsafeWadDiv} from "solmate/utils/SignedWadMath.sol";

import {VRGDA} from "./VRGDA.sol";

/// @title Logistic Variable Rate Gradual Dutch Auction
/// @author transmissions11 <[email protected]>
/// @author FrankieIsLost <[email protected]>
/// @notice VRGDA with a logistic issuance curve.
abstract contract LogisticVRGDA is VRGDA {
    /*//////////////////////////////////////////////////////////////
                           PRICING PARAMETERS
    //////////////////////////////////////////////////////////////*/

    /// @dev The maximum number of tokens of tokens to sell + 1. We add
    /// 1 because the logistic function will never fully reach its limit.
    /// @dev Represented as an 18 decimal fixed point number.
    int256 internal immutable logisticLimit;

    /// @dev The maximum number of tokens of tokens to sell + 1 multiplied
    /// by 2. We could compute it on the fly each time but this saves gas.
    /// @dev Represented as a 36 decimal fixed point number.
    int256 internal immutable logisticLimitDoubled;

    /// @dev Time scale controls the steepness of the logistic curve,
    /// which affects how quickly we will reach the curve's asymptote.
    /// @dev Represented as an 18 decimal fixed point number.
    int256 internal immutable timeScale;

    /// @notice Sets pricing parameters for the VRGDA.
    /// @param _targetPrice The target price for a token if sold on pace, scaled by 1e18.
    /// @param _priceDecayPercent The percent price decays per unit of time with no sales, scaled by 1e18.
    /// @param _maxSellable The maximum number of tokens to sell, scaled by 1e18.
    /// @param _timeScale The steepness of the logistic curve, scaled by 1e18.
    constructor(
        int256 _targetPrice,
        int256 _priceDecayPercent,
        int256 _maxSellable,
        int256 _timeScale
    ) VRGDA(_targetPrice, _priceDecayPercent) {
        // Add 1 wad to make the limit inclusive of _maxSellable.
        logisticLimit = _maxSellable + 1e18;

        // Scale by 2e18 to both double it and give it 36 decimals.
        logisticLimitDoubled = logisticLimit * 2e18;

        timeScale = _timeScale;
    }

    /*//////////////////////////////////////////////////////////////
                              PRICING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @dev Given a number of tokens sold, return the target time that number of tokens should be sold by.
    /// @param sold A number of tokens sold, scaled by 1e18, to get the corresponding target sale time for.
    /// @return The target time the tokens should be sold by, scaled by 1e18, where the time is
    /// relative, such that 0 means the tokens should be sold immediately when the VRGDA begins.
    function getTargetSaleTime(int256 sold) public view virtual override returns (int256) {
        unchecked {
            return -unsafeWadDiv(wadLn(unsafeDiv(logisticLimitDoubled, sold + logisticLimit) - 1e18), timeScale);
        }
    }
}

File 3 of 23 : VRGDA.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {wadExp, wadLn, wadMul, unsafeWadMul, toWadUnsafe} from "solmate/utils/SignedWadMath.sol";

/// @title Variable Rate Gradual Dutch Auction
/// @author transmissions11 <[email protected]>
/// @author FrankieIsLost <[email protected]>
/// @notice Sell tokens roughly according to an issuance schedule.
abstract contract VRGDA {
    /*//////////////////////////////////////////////////////////////
                            VRGDA PARAMETERS
    //////////////////////////////////////////////////////////////*/

    /// @notice Target price for a token, to be scaled according to sales pace.
    /// @dev Represented as an 18 decimal fixed point number.
    int256 public immutable targetPrice;

    /// @dev Precomputed constant that allows us to rewrite a pow() as an exp().
    /// @dev Represented as an 18 decimal fixed point number.
    int256 internal immutable decayConstant;

    /// @notice Sets target price and per time unit price decay for the VRGDA.
    /// @param _targetPrice The target price for a token if sold on pace, scaled by 1e18.
    /// @param _priceDecayPercent The percent price decays per unit of time with no sales, scaled by 1e18.
    constructor(int256 _targetPrice, int256 _priceDecayPercent) {
        targetPrice = _targetPrice;

        decayConstant = wadLn(1e18 - _priceDecayPercent);

        // The decay constant must be negative for VRGDAs to work.
        require(decayConstant < 0, "NON_NEGATIVE_DECAY_CONSTANT");
    }

    /*//////////////////////////////////////////////////////////////
                              PRICING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Calculate the price of a token according to the VRGDA formula.
    /// @param timeSinceStart Time passed since the VRGDA began, scaled by 1e18.
    /// @param sold The total number of tokens that have been sold so far.
    /// @return The price of a token according to VRGDA, scaled by 1e18.
    function getVRGDAPrice(int256 timeSinceStart, uint256 sold) public view virtual returns (uint256) {
        unchecked {
            // prettier-ignore
            return uint256(wadMul(targetPrice, wadExp(unsafeWadMul(decayConstant,
                // Theoretically calling toWadUnsafe with sold can silently overflow but under
                // any reasonable circumstance it will never be large enough. We use sold + 1 as
                // the VRGDA formula's n param represents the nth token and sold is the n-1th token.
                timeSinceStart - getTargetSaleTime(toWadUnsafe(sold + 1))
            ))));
        }
    }

    /// @dev Given a number of tokens sold, return the target time that number of tokens should be sold by.
    /// @param sold A number of tokens sold, scaled by 1e18, to get the corresponding target sale time for.
    /// @return The target time the tokens should be sold by, scaled by 1e18, where the time is
    /// relative, such that 0 means the tokens should be sold immediately when the VRGDA begins.
    function getTargetSaleTime(int256 sold) public view virtual returns (int256);
}

File 4 of 23 : LibGOO.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";

/// @title GOO (Gradual Ownership Optimization) Issuance
/// @author transmissions11 <[email protected]>
/// @author FrankieIsLost <[email protected]>
/// @notice Implementation of the GOO Issuance mechanism.
library LibGOO {
    using FixedPointMathLib for uint256;

    /// @notice Compute goo balance based on emission multiple, last balance, and time elapsed.
    /// @param emissionMultiple The multiple on emissions to consider when computing the balance.
    /// @param lastBalanceWad The last checkpointed balance to apply the emission multiple over time to, scaled by 1e18.
    /// @param timeElapsedWad The time elapsed since the last checkpoint, scaled by 1e18.
    function computeGOOBalance(
        uint256 emissionMultiple,
        uint256 lastBalanceWad,
        uint256 timeElapsedWad
    ) internal pure returns (uint256) {
        unchecked {
            // We use wad math here because timeElapsedWad is, as the name indicates, a wad.
            uint256 timeElapsedSquaredWad = timeElapsedWad.mulWadDown(timeElapsedWad);

            // prettier-ignore
            return lastBalanceWad + // The last recorded balance.

            // Don't need to do wad multiplication since we're
            // multiplying by a plain integer with no decimals.
            // Shift right by 2 is equivalent to division by 4.
            ((emissionMultiple * timeElapsedSquaredWad) >> 2) +

            timeElapsedWad.mulWadDown( // Terms are wads, so must mulWad.
                // No wad multiplication for emissionMultiple * lastBalance
                // because emissionMultiple is a plain integer with no decimals.
                // We multiply the sqrt's radicand by 1e18 because it expects ints.
                (emissionMultiple * lastBalanceWad * 1e18).sqrt()
            );
        }
    }
}

File 5 of 23 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

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

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

File 6 of 23 : ERC1155.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Minimalist and gas efficient standard ERC1155 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 amount
    );

    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] amounts
    );

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    /*//////////////////////////////////////////////////////////////
                             ERC1155 STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(address => mapping(uint256 => uint256)) public balanceOf;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                             METADATA LOGIC
    //////////////////////////////////////////////////////////////*/

    function uri(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                              ERC1155 LOGIC
    //////////////////////////////////////////////////////////////*/

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) public virtual {
        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        balanceOf[from][id] -= amount;
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, from, to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) public virtual {
        require(ids.length == amounts.length, "LENGTH_MISMATCH");

        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        // Storing these outside the loop saves ~15 gas per iteration.
        uint256 id;
        uint256 amount;

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

            balanceOf[from][id] -= amount;
            balanceOf[to][id] += amount;

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
        public
        view
        virtual
        returns (uint256[] memory balances)
    {
        require(owners.length == ids.length, "LENGTH_MISMATCH");

        balances = new uint256[](owners.length);

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < owners.length; ++i) {
                balances[i] = balanceOf[owners[i]][ids[i]];
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, address(0), to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchMint(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[to][ids[i]] += amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, address(0), to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchBurn(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[from][ids[i]] -= amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, address(0), ids, amounts);
    }

    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal virtual {
        balanceOf[from][id] -= amount;

        emit TransferSingle(msg.sender, from, address(0), id, amount);
    }
}

/// @notice A generic interface for a contract which properly accepts ERC1155 tokens.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155TokenReceiver {
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
    }
}

File 7 of 23 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

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

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

File 8 of 23 : ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(_ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

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

    function _burn(uint256 id) internal virtual {
        address owner = _ownerOf[id];

        require(owner != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

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

    /*//////////////////////////////////////////////////////////////
                        INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

File 9 of 23 : FixedPointMathLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol)
library FixedPointMathLib {
    /*//////////////////////////////////////////////////////////////
                    SIMPLIFIED FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    uint256 internal constant MAX_UINT256 = 2**256 - 1;

    uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s.

    function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down.
    }

    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up.
    }

    function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down.
    }

    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
        return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up.
    }

    /*//////////////////////////////////////////////////////////////
                    LOW LEVEL FIXED POINT OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function mulDivDown(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // Divide x * y by the denominator.
            z := div(mul(x, y), denominator)
        }
    }

    function mulDivUp(
        uint256 x,
        uint256 y,
        uint256 denominator
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y))
            if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
                revert(0, 0)
            }

            // If x * y modulo the denominator is strictly greater than 0,
            // 1 is added to round up the division of x * y by the denominator.
            z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
        }
    }

    function rpow(
        uint256 x,
        uint256 n,
        uint256 scalar
    ) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            switch x
            case 0 {
                switch n
                case 0 {
                    // 0 ** 0 = 1
                    z := scalar
                }
                default {
                    // 0 ** n = 0
                    z := 0
                }
            }
            default {
                switch mod(n, 2)
                case 0 {
                    // If n is even, store scalar in z for now.
                    z := scalar
                }
                default {
                    // If n is odd, store x in z for now.
                    z := x
                }

                // Shifting right by 1 is like dividing by 2.
                let half := shr(1, scalar)

                for {
                    // Shift n right by 1 before looping to halve it.
                    n := shr(1, n)
                } n {
                    // Shift n right by 1 each iteration to halve it.
                    n := shr(1, n)
                } {
                    // Revert immediately if x ** 2 would overflow.
                    // Equivalent to iszero(eq(div(xx, x), x)) here.
                    if shr(128, x) {
                        revert(0, 0)
                    }

                    // Store x squared.
                    let xx := mul(x, x)

                    // Round to the nearest number.
                    let xxRound := add(xx, half)

                    // Revert if xx + half overflowed.
                    if lt(xxRound, xx) {
                        revert(0, 0)
                    }

                    // Set x to scaled xxRound.
                    x := div(xxRound, scalar)

                    // If n is even:
                    if mod(n, 2) {
                        // Compute z * x.
                        let zx := mul(z, x)

                        // If z * x overflowed:
                        if iszero(eq(div(zx, x), z)) {
                            // Revert if x is non-zero.
                            if iszero(iszero(x)) {
                                revert(0, 0)
                            }
                        }

                        // Round to the nearest number.
                        let zxRound := add(zx, half)

                        // Revert if zx + half overflowed.
                        if lt(zxRound, zx) {
                            revert(0, 0)
                        }

                        // Return properly scaled zxRound.
                        z := div(zxRound, scalar)
                    }
                }
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                        GENERAL NUMBER UTILITIES
    //////////////////////////////////////////////////////////////*/

    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let y := x // We start y at x, which will help us make our initial estimate.

            z := 181 // The "correct" value is 1, but this saves a multiplication later.

            // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad
            // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically.

            // We check y >= 2^(k + 8) but shift right by k bits
            // each branch to ensure that if x >= 256, then y >= 256.
            if iszero(lt(y, 0x10000000000000000000000000000000000)) {
                y := shr(128, y)
                z := shl(64, z)
            }
            if iszero(lt(y, 0x1000000000000000000)) {
                y := shr(64, y)
                z := shl(32, z)
            }
            if iszero(lt(y, 0x10000000000)) {
                y := shr(32, y)
                z := shl(16, z)
            }
            if iszero(lt(y, 0x1000000)) {
                y := shr(16, y)
                z := shl(8, z)
            }

            // Goal was to get z*z*y within a small factor of x. More iterations could
            // get y in a tighter range. Currently, we will have y in [256, 256*2^16).
            // We ensured y >= 256 so that the relative difference between y and y+1 is small.
            // That's not possible if x < 256 but we can just verify those cases exhaustively.

            // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256.
            // Correctness can be checked exhaustively for x < 256, so we assume y >= 256.
            // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps.

            // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range
            // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256.

            // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate
            // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18.

            // There is no overflow risk here since y < 2^136 after the first branch above.
            z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181.

            // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough.
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))
            z := shr(1, add(z, div(x, z)))

            // If x+1 is a perfect square, the Babylonian method cycles between
            // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor.
            // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division
            // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case.
            // If you don't care whether the floor or ceil square root is returned, you can remove this statement.
            z := sub(z, lt(div(x, z), z))
        }
    }

    function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Mod x by y. Note this will return
            // 0 instead of reverting if y is zero.
            z := mod(x, y)
        }
    }

    function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Divide x by y. Note this will return
            // 0 instead of reverting if y is zero.
            r := div(x, y)
        }
    }

    function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Add 1 to x * y if x % y > 0. Note this will
            // return 0 instead of reverting if y is zero.
            z := add(gt(mod(x, y), 0), div(x, y))
        }
    }
}

File 10 of 23 : LibString.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Efficient library for creating string representations of integers.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibString.sol)
/// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/LibString.sol)
library LibString {
    function toString(uint256 value) internal pure returns (string memory str) {
        /// @solidity memory-safe-assembly
        assembly {
            // The maximum value of a uint256 contains 78 digits (1 byte per digit), but we allocate 160 bytes
            // to keep the free memory pointer word aligned. We'll need 1 word for the length, 1 word for the
            // trailing zeros padding, and 3 other words for a max of 78 digits. In total: 5 * 32 = 160 bytes.
            let newFreeMemoryPointer := add(mload(0x40), 160)

            // Update the free memory pointer to avoid overriding our string.
            mstore(0x40, newFreeMemoryPointer)

            // Assign str to the end of the zone of newly allocated memory.
            str := sub(newFreeMemoryPointer, 32)

            // Clean the last word of memory it may not be overwritten.
            mstore(str, 0)

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

            // We write the string from rightmost digit to leftmost digit.
            // The following is essentially a do-while loop that also handles the zero case.
            // prettier-ignore
            for { let temp := value } 1 {} {
                // Move the pointer 1 byte to the left.
                str := sub(str, 1)

                // Write the character to the pointer.
                // The ASCII index of the '0' character is 48.
                mstore8(str, add(48, mod(temp, 10)))

                // Keep dividing temp until zero.
                temp := div(temp, 10)

                 // prettier-ignore
                if iszero(temp) { break }
            }

            // Compute and cache the final total length of the string.
            let length := sub(end, str)

            // Move the pointer 32 bytes leftwards to make room for the length.
            str := sub(str, 32)

            // Store the string's length at the start of memory allocated for our string.
            mstore(str, length)
        }
    }
}

File 11 of 23 : MerkleProofLib.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Gas optimized merkle proof verification library.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
library MerkleProofLib {
    function verify(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool isValid) {
        /// @solidity memory-safe-assembly
        assembly {
            if proof.length {
                // Left shifting by 5 is like multiplying by 32.
                let end := add(proof.offset, shl(5, proof.length))

                // Initialize offset to the offset of the proof in calldata.
                let offset := proof.offset

                // Iterate over proof elements to compute root hash.
                // prettier-ignore
                for {} 1 {} {
                    // Slot where the leaf should be put in scratch space. If
                    // leaf > calldataload(offset): slot 32, otherwise: slot 0.
                    let leafSlot := shl(5, gt(leaf, calldataload(offset)))

                    // Store elements to hash contiguously in scratch space.
                    // The xor puts calldataload(offset) in whichever slot leaf
                    // is not occupying, so 0 if leafSlot is 32, and 32 otherwise.
                    mstore(leafSlot, leaf)
                    mstore(xor(leafSlot, 32), calldataload(offset))

                    // Reuse leaf to store the hash to reduce stack operations.
                    leaf := keccak256(0, 64) // Hash both slots of scratch space.

                    offset := add(offset, 32) // Shift 1 word per cycle.

                    // prettier-ignore
                    if iszero(lt(offset, end)) { break }
                }
            }

            isValid := eq(leaf, root) // The proof is valid if the roots match.
        }
    }
}

File 12 of 23 : SignedWadMath.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @notice Signed 18 decimal fixed point (wad) arithmetic library.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SignedWadMath.sol)
/// @author Modified from Remco Bloemen (https://xn--2-umb.com/22/exp-ln/index.html)

/// @dev Will not revert on overflow, only use where overflow is not possible.
function toWadUnsafe(uint256 x) pure returns (int256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        // Multiply x by 1e18.
        r := mul(x, 1000000000000000000)
    }
}

/// @dev Takes an integer amount of seconds and converts it to a wad amount of days.
/// @dev Will not revert on overflow, only use where overflow is not possible.
/// @dev Not meant for negative second amounts, it assumes x is positive.
function toDaysWadUnsafe(uint256 x) pure returns (int256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        // Multiply x by 1e18 and then divide it by 86400.
        r := div(mul(x, 1000000000000000000), 86400)
    }
}

/// @dev Takes a wad amount of days and converts it to an integer amount of seconds.
/// @dev Will not revert on overflow, only use where overflow is not possible.
/// @dev Not meant for negative day amounts, it assumes x is positive.
function fromDaysWadUnsafe(int256 x) pure returns (uint256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        // Multiply x by 86400 and then divide it by 1e18.
        r := div(mul(x, 86400), 1000000000000000000)
    }
}

/// @dev Will not revert on overflow, only use where overflow is not possible.
function unsafeWadMul(int256 x, int256 y) pure returns (int256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        // Multiply x by y and divide by 1e18.
        r := sdiv(mul(x, y), 1000000000000000000)
    }
}

/// @dev Will return 0 instead of reverting if y is zero and will
/// not revert on overflow, only use where overflow is not possible.
function unsafeWadDiv(int256 x, int256 y) pure returns (int256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        // Multiply x by 1e18 and divide it by y.
        r := sdiv(mul(x, 1000000000000000000), y)
    }
}

function wadMul(int256 x, int256 y) pure returns (int256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        // Store x * y in r for now.
        r := mul(x, y)

        // Equivalent to require(x == 0 || (x * y) / x == y)
        if iszero(or(iszero(x), eq(sdiv(r, x), y))) {
            revert(0, 0)
        }

        // Scale the result down by 1e18.
        r := sdiv(r, 1000000000000000000)
    }
}

function wadDiv(int256 x, int256 y) pure returns (int256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        // Store x * 1e18 in r for now.
        r := mul(x, 1000000000000000000)

        // Equivalent to require(y != 0 && ((x * 1e18) / 1e18 == x))
        if iszero(and(iszero(iszero(y)), eq(sdiv(r, 1000000000000000000), x))) {
            revert(0, 0)
        }

        // Divide r by y.
        r := sdiv(r, y)
    }
}

function wadExp(int256 x) pure returns (int256 r) {
    unchecked {
        // When the result is < 0.5 we return zero. This happens when
        // x <= floor(log(0.5e18) * 1e18) ~ -42e18
        if (x <= -42139678854452767551) return 0;

        // When the result is > (2**255 - 1) / 1e18 we can not represent it as an
        // int. This happens when x >= floor(log((2**255 - 1) / 1e18) * 1e18) ~ 135.
        if (x >= 135305999368893231589) revert("EXP_OVERFLOW");

        // x is now in the range (-42, 136) * 1e18. Convert to (-42, 136) * 2**96
        // for more intermediate precision and a binary basis. This base conversion
        // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78.
        x = (x << 78) / 5**18;

        // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers
        // of two such that exp(x) = exp(x') * 2**k, where k is an integer.
        // Solving this gives k = round(x / log(2)) and x' = x - k * log(2).
        int256 k = ((x << 96) / 54916777467707473351141471128 + 2**95) >> 96;
        x = x - k * 54916777467707473351141471128;

        // k is in the range [-61, 195].

        // Evaluate using a (6, 7)-term rational approximation.
        // p is made monic, we'll multiply by a scale factor later.
        int256 y = x + 1346386616545796478920950773328;
        y = ((y * x) >> 96) + 57155421227552351082224309758442;
        int256 p = y + x - 94201549194550492254356042504812;
        p = ((p * y) >> 96) + 28719021644029726153956944680412240;
        p = p * x + (4385272521454847904659076985693276 << 96);

        // We leave p in 2**192 basis so we don't need to scale it back up for the division.
        int256 q = x - 2855989394907223263936484059900;
        q = ((q * x) >> 96) + 50020603652535783019961831881945;
        q = ((q * x) >> 96) - 533845033583426703283633433725380;
        q = ((q * x) >> 96) + 3604857256930695427073651918091429;
        q = ((q * x) >> 96) - 14423608567350463180887372962807573;
        q = ((q * x) >> 96) + 26449188498355588339934803723976023;

        /// @solidity memory-safe-assembly
        assembly {
            // Div in assembly because solidity adds a zero check despite the unchecked.
            // The q polynomial won't have zeros in the domain as all its roots are complex.
            // No scaling is necessary because p is already 2**96 too large.
            r := sdiv(p, q)
        }

        // r should be in the range (0.09, 0.25) * 2**96.

        // We now need to multiply r by:
        // * the scale factor s = ~6.031367120.
        // * the 2**k factor from the range reduction.
        // * the 1e18 / 2**96 factor for base conversion.
        // We do this all at once, with an intermediate result in 2**213
        // basis, so the final right shift is always by a positive amount.
        r = int256((uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k));
    }
}

function wadLn(int256 x) pure returns (int256 r) {
    unchecked {
        require(x > 0, "UNDEFINED");

        // We want to convert x from 10**18 fixed point to 2**96 fixed point.
        // We do this by multiplying by 2**96 / 10**18. But since
        // ln(x * C) = ln(x) + ln(C), we can simply do nothing here
        // and add ln(2**96 / 10**18) at the end.

        /// @solidity memory-safe-assembly
        assembly {
            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            r := or(r, shl(2, lt(0xf, shr(r, x))))
            r := or(r, shl(1, lt(0x3, shr(r, x))))
            r := or(r, lt(0x1, shr(r, x)))
        }

        // Reduce range of x to (1, 2) * 2**96
        // ln(2^k * x) = k * ln(2) + ln(x)
        int256 k = r - 96;
        x <<= uint256(159 - k);
        x = int256(uint256(x) >> 159);

        // Evaluate using a (8, 8)-term rational approximation.
        // p is made monic, we will multiply by a scale factor later.
        int256 p = x + 3273285459638523848632254066296;
        p = ((p * x) >> 96) + 24828157081833163892658089445524;
        p = ((p * x) >> 96) + 43456485725739037958740375743393;
        p = ((p * x) >> 96) - 11111509109440967052023855526967;
        p = ((p * x) >> 96) - 45023709667254063763336534515857;
        p = ((p * x) >> 96) - 14706773417378608786704636184526;
        p = p * x - (795164235651350426258249787498 << 96);

        // We leave p in 2**192 basis so we don't need to scale it back up for the division.
        // q is monic by convention.
        int256 q = x + 5573035233440673466300451813936;
        q = ((q * x) >> 96) + 71694874799317883764090561454958;
        q = ((q * x) >> 96) + 283447036172924575727196451306956;
        q = ((q * x) >> 96) + 401686690394027663651624208769553;
        q = ((q * x) >> 96) + 204048457590392012362485061816622;
        q = ((q * x) >> 96) + 31853899698501571402653359427138;
        q = ((q * x) >> 96) + 909429971244387300277376558375;
        /// @solidity memory-safe-assembly
        assembly {
            // Div in assembly because solidity adds a zero check despite the unchecked.
            // The q polynomial is known not to have zeros in the domain.
            // No scaling required because p is already 2**96 too large.
            r := sdiv(p, q)
        }

        // r is in the range (0, 0.125) * 2**96

        // Finalization, we need to:
        // * multiply by the scale factor s = 5.549…
        // * add ln(2**96 / 10**18)
        // * add k * ln(2)
        // * multiply by 10**18 / 2**96 = 5**18 >> 78

        // mul s * 5e18 * 2**96, base is now 5**18 * 2**192
        r *= 1677202110996718588342820967067443963516166;
        // add ln(2) * k * 5e18 * 2**192
        r += 16597577552685614221487285958193947469193820559219878177908093499208371 * k;
        // add ln(2**96 / 10**18) * 5e18 * 2**192
        r += 600920179829731861736702779321621459595472258049074101567377883020018308;
        // base conversion: mul 2**18 / 2**192
        r >>= 174;
    }
}

/// @dev Will return 0 instead of reverting if y is zero.
function unsafeDiv(int256 x, int256 y) pure returns (int256 r) {
    /// @solidity memory-safe-assembly
    assembly {
        // Divide x by y.
        r := sdiv(x, y)
    }
}

File 13 of 23 : IERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev Interface for the NFT Royalty Standard.
 *
 * A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
 * support for royalty payments across all NFT marketplaces and ecosystem participants.
 *
 * _Available since v4.5._
 */
interface IERC2981 is IERC165 {
    /**
     * @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
     * exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
     */
    function royaltyInfo(uint256 tokenId, uint256 salePrice)
        external
        view
        returns (address receiver, uint256 royaltyAmount);
}

File 14 of 23 : ERC2981.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)

pragma solidity ^0.8.0;

import "../../interfaces/IERC2981.sol";
import "../../utils/introspection/ERC165.sol";

/**
 * @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
 *
 * Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
 * specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
 *
 * Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
 * fee is specified in basis points by default.
 *
 * IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
 * https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
 * voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
 *
 * _Available since v4.5._
 */
abstract contract ERC2981 is IERC2981, ERC165 {
    struct RoyaltyInfo {
        address receiver;
        uint96 royaltyFraction;
    }

    RoyaltyInfo private _defaultRoyaltyInfo;
    mapping(uint256 => RoyaltyInfo) private _tokenRoyaltyInfo;

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

    /**
     * @inheritdoc IERC2981
     */
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice) public view virtual override returns (address, uint256) {
        RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];

        if (royalty.receiver == address(0)) {
            royalty = _defaultRoyaltyInfo;
        }

        uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();

        return (royalty.receiver, royaltyAmount);
    }

    /**
     * @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
     * fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
     * override.
     */
    function _feeDenominator() internal pure virtual returns (uint96) {
        return 10000;
    }

    /**
     * @dev Sets the royalty information that all ids in this contract will default to.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setDefaultRoyalty(address receiver, uint96 feeNumerator) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: invalid receiver");

        _defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Removes default royalty information.
     */
    function _deleteDefaultRoyalty() internal virtual {
        delete _defaultRoyaltyInfo;
    }

    /**
     * @dev Sets the royalty information for a specific token id, overriding the global default.
     *
     * Requirements:
     *
     * - `receiver` cannot be the zero address.
     * - `feeNumerator` cannot be greater than the fee denominator.
     */
    function _setTokenRoyalty(
        uint256 tokenId,
        address receiver,
        uint96 feeNumerator
    ) internal virtual {
        require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
        require(receiver != address(0), "ERC2981: Invalid parameters");

        _tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
    }

    /**
     * @dev Resets royalty information for the token id back to the global default.
     */
    function _resetTokenRoyalty(uint256 tokenId) internal virtual {
        delete _tokenRoyaltyInfo[tokenId];
    }
}

File 15 of 23 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

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

File 16 of 23 : IERC165.sol
// 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 17 of 23 : Arms.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {LibString} from "solmate/utils/LibString.sol";
import {toDaysWadUnsafe} from "solmate/utils/SignedWadMath.sol";

import {LogisticToLinearVRGDA} from "VRGDAs/LogisticToLinearVRGDA.sol";

import {ArmsERC721} from "./utils/token/ArmsERC721.sol";

import {Shirak} from "./Shirak.sol";
import {MechAvax} from "./MechAvax.sol";



/// @title Armaments NFT
/// @notice Forked by 0xBoots
/// @author FrankieIsLost <[email protected]>
/// @author transmissions11 <[email protected]>
/// @notice Arms is an ERC721 that can hold custom art.
contract Arms is ArmsERC721, LogisticToLinearVRGDA {
    using LibString for uint256;

    

    /*//////////////////////////////////////////////////////////////
                                ADDRESSES
    //////////////////////////////////////////////////////////////*/

    /// @notice The address of the shirak ERC20 token contract.
    Shirak public immutable shirak;

    /// @notice The address which receives arms reserved for the community.
    address public immutable community;

    /*//////////////////////////////////////////////////////////////
                                  URIS
    //////////////////////////////////////////////////////////////*/

    /// @notice Base URI for minted arms.
    string public BASE_URI;
    
    /// @notice Uri file type extension.
    string public URI_EXTENSION = ".json";

    /*//////////////////////////////////////////////////////////////
                            VRGDA INPUT STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice Timestamp for the start of the VRGDA mint.
    uint256 public immutable mintStart;

    /// @notice Id of the most recently minted arm.
    /// @dev Will be 0 if no arms have been minted yet.
    uint128 public currentId;

    /*//////////////////////////////////////////////////////////////
                          COMMUNITY PAGES STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice The number of arms minted to the community reserve.
    uint128 public numMintedForCommunity;

    /*//////////////////////////////////////////////////////////////
                            PRICING CONSTANTS
    //////////////////////////////////////////////////////////////*/

    /// @dev The day the switch from a logistic to translated linear VRGDA is targeted to occur.
    /// @dev Represented as an 18 decimal fixed point number.
    int256 internal constant SWITCH_DAY_WAD = 233e18;

    /// @notice The minimum amount of arms that must be sold for the VRGDA issuance
    /// schedule to switch from logistic to the "post switch" translated linear formula.
    /// @dev Computed off-chain by plugging SWITCH_DAY_WAD into the uninverted pacing formula.
    /// @dev Represented as an 18 decimal fixed point number.
    int256 internal constant SOLD_BY_SWITCH_WAD = 8336.760939794622713006e18;

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event PagePurchased(address indexed user, uint256 indexed armId, uint256 price);

    event CommunityArmsMinted(address indexed user, uint256 lastMintedPageId, uint256 numArms);

    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    error ReserveImbalance();

    error PriceExceededMax(uint256 currentPrice);

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    /// @notice Sets VRGDA parameters, mint start, relevant addresses, and base URI.
    /// @param _mintStart Timestamp for the start of the VRGDA mint.
    /// @param _shirak Address of the Shirak contract.
    /// @param _community Address of the community reserve.
    /// @param _mechAvax Address of the MechAvax contract.
    /// @param _baseUri Base URI for token metadata.
    constructor(
        // Mint config:
        uint256 _mintStart,
        // Addresses:
        Shirak _shirak,
        address _community,
        MechAvax _mechAvax,
        // URIs:
        string memory _baseUri
    )
        ArmsERC721(_mechAvax, "Mechavax Blank Armament", "MARM")
        LogisticToLinearVRGDA(
            4.2069e18, // Target price.
            0.31e18, // Price decay percent.
            9000e18, // Logistic asymptote.
            0.014e18, // Logistic time scale.
            SOLD_BY_SWITCH_WAD, // Sold by switch.
            SWITCH_DAY_WAD, // Target switch day.
            9e18 // Arms to target per day.
        )
    {
        mintStart = _mintStart;

        shirak = _shirak;

        community = _community;

        BASE_URI = _baseUri;
    }

    /*//////////////////////////////////////////////
                        ROYALTY FUNCTION
    //////////////////////////////////////////////*/

    function updateRoyalties() external {
    
        _setDefaultRoyalty(mechAvax.royaltyPayout(), mechAvax.tokenRoyalties());
    }

    /*//////////////////////////////////////////////////////////////
                              MINTING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Mint a arm with shirak, burning the cost.
    /// @param maxPrice Maximum price to pay to mint the arm.
    /// @param useVirtualBalance Whether the cost is paid from the
    /// user's virtual shirak balance, or from their ERC20 shirak balance.
    /// @return armId The id of the arm that was minted.
    function mintFromShirak(uint256 maxPrice, bool useVirtualBalance) external returns (uint256 armId) {
        // Will revert if prior to mint start.
        uint256 currentPrice = armPrice();

        // If the current price is above the user's specified max, revert.
        if (currentPrice > maxPrice) revert PriceExceededMax(currentPrice);

        // Decrement the user's shirak balance by the current
        // price, either from virtual balance or ERC20 balance.
        useVirtualBalance
            ? mechAvax.burnShirakForArms(msg.sender, currentPrice)
            : shirak.burnForArms(msg.sender, currentPrice);

        unchecked {
            emit PagePurchased(msg.sender, armId = ++currentId, currentPrice);

            _mint(msg.sender, armId);
        }
    }

    /// @notice Calculate the mint cost of a arm.
    /// @dev If the number of sales is below a pre-defined threshold, we use the
    /// VRGDA pricing algorithm, otherwise we use the post-switch pricing formula.
    /// @dev Reverts due to underflow if minting hasn't started yet. Done to save gas.
    function armPrice() public view returns (uint256) {
        // We need checked math here to cause overflow
        // before minting has begun, preventing mints.
        uint256 timeSinceStart = block.timestamp - mintStart;

        unchecked {
            // The number of arms minted for the community reserve
            // should never exceed 10% of the total supply of arms.
            return getVRGDAPrice(toDaysWadUnsafe(timeSinceStart), currentId - numMintedForCommunity);
        }
    }

    /*//////////////////////////////////////////////////////////////
                      COMMUNITY PAGES MINTING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Mint a number of arms to the community reserve.
    /// @param numArms The number of arms to mint to the reserve.
    /// @dev Arms minted to the reserve cannot comprise more than 10% of the sum of the
    /// supply of shirak minted arms and the supply of arms minted to the community reserve.
    function mintCommunityArms(uint256 numArms) external returns (uint256 lastMintedPageId) {
        unchecked {
            // Optimistically increment numMintedForCommunity, may be reverted below.
            // Overflow in this calculation is possible but numArms would have to be so
            // large that it would cause the loop in _batchMint to run out of gas quickly.
            uint256 newNumMintedForCommunity = numMintedForCommunity += uint128(numArms);

            // Ensure that after this mint arms minted to the community reserve won't comprise more than
            // 10% of the new total arm supply. currentId is equivalent to the current total supply of arms.
            if (newNumMintedForCommunity > ((lastMintedPageId = currentId) + numArms) / 10) revert ReserveImbalance();

            // Mint the arms to the community reserve and update lastMintedPageId once minting is complete.
            lastMintedPageId = _batchMint(mechAvax.owner(), numArms, lastMintedPageId);

            currentId = uint128(lastMintedPageId); // Update currentId with the last minted arm id.

            emit CommunityArmsMinted(msg.sender, lastMintedPageId, numArms);
        }
    }

    /*//////////////////////////////////////////////////////////////
                                URI LOGIC
    //////////////////////////////////////////////////////////////*/

    function setBaseURI(string calldata baseURI_) external {
        require(msg.sender == mechAvax.owner(), "not auth");
        BASE_URI = baseURI_;
    }

    function setBaseExtension(string memory newBaseExtension) public {
        require(msg.sender == mechAvax.owner(), "not auth");
         URI_EXTENSION = newBaseExtension;
    }

    /*//////////////////////////////////////////////////////////////
                             TOKEN URI LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Returns a arm's URI if it has been minted.
    /// @param armId The id of the arm to get the URI for.
    function tokenURI(uint256 armId) public view virtual override returns (string memory) {
        if (armId == 0 || armId > currentId) revert("NOT_MINTED");

        return string.concat(BASE_URI, armId.toString(), URI_EXTENSION);
    }
}

File 18 of 23 : MechAvax.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;


import {Owned} from "solmate/auth/Owned.sol";
import {ERC721} from "solmate/tokens/ERC721.sol";
import {LibString} from "solmate/utils/LibString.sol";
import {MerkleProofLib} from "solmate/utils/MerkleProofLib.sol";
import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";
import {ERC1155, ERC1155TokenReceiver} from "solmate/tokens/ERC1155.sol";
import {toWadUnsafe, toDaysWadUnsafe} from "solmate/utils/SignedWadMath.sol";

import {LibGOO} from "shirak-issuance/LibGOO.sol";
import {LogisticVRGDA} from "VRGDAs/LogisticVRGDA.sol";

import {RandProvider} from "./utils/rand/RandProvider.sol";
import {MechsERC721} from "./utils/token/MechsERC721.sol";

import {Shirak} from "./Shirak.sol";
import {Arms} from "./Arms.sol";
import {MintERC721} from "./MintERC721.sol";

/// @title Mechavax NFT
/// @notice Forked by 0xBoots
/// @author FrankieIsLost <[email protected]>
/// @author transmissions11 <[email protected]>
/// @notice An experimental decentralized art factory by Justin Roiland and Paradigm.
contract MechAvax is MechsERC721, LogisticVRGDA, Owned, ERC1155TokenReceiver {
    using LibString for uint256;
    using FixedPointMathLib for uint256;

    /*//////////////////////////////////////////////////////////////
                                ROYALTIES
    //////////////////////////////////////////////////////////////*/
    
    /// @notice The royalty precentage.
    uint96 public tokenRoyalties = 1000; // 10% royalty

    /// @notice The address for rewards.
    address public royaltyPayout;

    /*//////////////////////////////////////////////////////////////
                                ADDRESSES
    //////////////////////////////////////////////////////////////*/

    /// @notice The address of the Shirak ERC20 token contract.
    Shirak public immutable shirak;

    /// @notice The address of the Arms ERC721 token contract.
    Arms public immutable arms;

    /// @notice The address of the ticket minted by other ERC721 token contract.
    address public immutable ticket;

    /// @notice The address of the ticket minted by initial ERC721 token contract.
    address public immutable EP;

    /// @notice The address of the new ticket minted by new ERC721 token contract.
    address public newEP;

    /// @notice The address which receives mechs reserved for the team.
    address public immutable team;

    /// @notice The address of a randomness provider. This provider will initially be
    /// a wrapper around Chainlink VRF v1, but can be changed in case it is fully sunset.
    RandProvider public randProvider;

    ///@notice the address of the approved stake locking contract. Initially set to null. Must be set via deploy.
    address public stakeLocker;

    /*//////////////////////////////////////////////////////////////
                            SUPPLY CONSTANTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Maximum number of mintable mechs.
    uint256 public constant MAX_SUPPLY = 4500;

    /// @notice Maximum amount of mechs mintable via claimMech.
    uint256 public constant MINTLIST_SUPPLY = 2206;

    /// @notice Maximum amount of mintable legendary mechs.
    uint256 public constant LEGENDARY_SUPPLY = 12;

    /// @notice Maximum amount of mechs split between the reserves.
    /// @dev Set to comprise 20% of the sum of shirak mintable mechs + reserved mechs.
    uint256 public constant RESERVED_SUPPLY = 312;

    /// @notice Maximum amount of mechs that can be minted via VRGDA.
    // prettier-ignore
    uint256 public constant MAX_MINTABLE = MAX_SUPPLY
        - MINTLIST_SUPPLY
        - LEGENDARY_SUPPLY
        - RESERVED_SUPPLY;

    /*//////////////////////////////////////////////////////////////
                           METADATA CONSTANTS
    //////////////////////////////////////////////////////////////*/

    /// @notice Provenance hash for mech metadata.
    bytes32 public PROVENANCE_HASH;

    /// @notice URI for mechs pending reveal.
    string public UNREVEALED_URI;

    /// @notice Base URI for minted mechs.
    string public BASE_URI;

    /// @notice Uri file type extension.
    string public URI_EXTENSION = ".json";

    /*//////////////////////////////////////////////////////////////
                            VRGDA INPUT STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice Timestamp for the start of minting.
    uint256 public immutable mintStart;

    /// @notice Number of mechs minted from shirak.
    uint128 public numMintedFromShirak;

    /*//////////////////////////////////////////////////////////////
                         STAKING & TRANSFER STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice Struct containing staked bool.
    struct MechStaked {
        // if true and noTransferStaking == true then no transfer allowed.
        bool isStaked;
    }
    /// @notice Mapping of staked struct to tokenID.
    mapping(uint256 => MechStaked) public mechStaked;

    /// @notice Check if transfers are allowed while staked
    bool public noTransferStaking = false;


    /*//////////////////////////////////////////////////////////////
                         LGENDARY LOCK STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice Check if legendary mint lock is on
    bool public legLock = false;

    /// @notice address of the permitted legendary minter
    address public legMinter;


    /*//////////////////////////////////////////////////////////////
                         STANDARD MECH STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice Id of the most recently minted non legendary mech.
    /// @dev Will be 0 if no non legendary mechs have been minted yet.
    uint128 public currentNonLegendaryId;

    /// @notice The number of mechs minted to the reserves.
    uint256 public numMintedForReserves;

    /*//////////////////////////////////////////////////////////////
                     LEGENDARY MECH AUCTION STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice Initial legendary mech auction price.
    uint256 public constant LEGENDARY_MECH_INITIAL_START_PRICE = 42;

    /// @notice The last LEGENDARY_SUPPLY ids are reserved for legendary mechs.
    uint256 public constant FIRST_LEGENDARY_MECH_ID = MAX_SUPPLY - LEGENDARY_SUPPLY + 1;

    /// @notice Legendary auctions begin each time a multiple of these many mechs have been minted from shirak.
    /// @dev We add 1 to LEGENDARY_SUPPLY because legendary auctions begin only after the first interval.
    uint256 public constant LEGENDARY_AUCTION_INTERVAL = MAX_MINTABLE / (LEGENDARY_SUPPLY + 1);

    /// @notice Struct holding data required for legendary mech auctions.
    struct LegendaryMechAuctionData {
        // Start price of current legendary mech auction.
        uint128 startPrice;
        // Number of legendary mechs sold so far.
        uint128 numSold;
    }

    /// @notice Data about the current legendary mech auction.
    LegendaryMechAuctionData public legendaryMechAuctionData;

    /*//////////////////////////////////////////////////////////////
                          MECH REVEAL STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice Struct holding data required for mech reveals.
    struct MechRevealsData {
        // Last randomness obtained from the rand provider.
        uint64 randomSeed;
        // Next reveal cannot happen before this timestamp.
        uint64 nextRevealTimestamp;
        // Id of latest mech which has been revealed so far.
        uint64 lastRevealedId;
        // Remaining mechs to be revealed with the current seed.
        uint56 toBeRevealed;
        // Whether we are waiting to receive a seed from the provider.
        bool waitingForSeed;
    }

    /// @notice Data about the current state of mech reveals.
    MechRevealsData public mechRevealsData;

    /*//////////////////////////////////////////////////////////////
                            SOULBOUND ARMAMENT STATE
    //////////////////////////////////////////////////////////////*/

    /// @notice Maps mech ids to NFT contracts and their ids to the # of those NFT ids gobbled by the mech.
    mapping(uint256 => mapping(address => mapping(uint256 => uint256))) public getCopiesOfArmsBondedToMech;

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event ShirakBalanceUpdated(address indexed user, uint256 newShirakBalance);

    event MechClaimed(address indexed user, uint256 indexed mechId);
    event MechPurchased(address indexed user, uint256 indexed mechId, uint256 price);
    event LegendaryMechMinted(address indexed user, uint256 indexed mechId, uint256[] burnedMechIds);
    event ReservedMechsMinted(address indexed user, uint256 lastMintedMechId, uint256 numMechsEach);

    event RandomnessFulfilled(uint256 randomness);
    event RandomnessRequested(address indexed user, uint256 toBeRevealed);
    event RandProviderUpgraded(address indexed user, RandProvider indexed newRandProvider);

    event MechsRevealed(address indexed user, uint256 numMechs, uint256 lastRevealedId);

    event ArmsBonded(address indexed user, uint256 indexed mechId, address indexed nft, uint256 id);

    event PhashUpdated(bytes32 oldPhash, bytes32 newPhash, address updater);

    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    error InvalidProof();
    error AlreadyClaimed();
    error MintStartPending();

    error SeedPending();
    error RevealsPending();
    error RequestTooEarly();
    error ZeroToBeRevealed();
    error NotRandProvider();

    error ReserveImbalance();

    error Cannibalism();
    error OwnerMismatch(address owner);

    error NoRemainingLegendaryMechs();
    error CannotBurnLegendary(uint256 mechId);
    error InsufficientMechAmount(uint256 cost);
    error LegendaryAuctionNotStarted(uint256 mechsLeft);

    error PriceExceededMax(uint256 currentPrice);

    error NotEnoughRemainingToBeRevealed(uint256 totalRemainingToBeRevealed);

    error UnauthorizedCaller(address caller);

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    /// @notice Sets VRGDA parameters, mint config, relevant addresses, and URIs.
    /// @param _ep address of initial EP
    /// @param _ticket address of second ticket
    /// @param _mintStart Timestamp for the start of the VRGDA mint.
    /// @param _shirak Address of the Shirak contract.
    /// @param _team Address of the team reserve.
    /// @param _randProvider Address of the randomness provider.
    /// @param _baseUri Base URI for revealed mechs.
    /// @param _unrevealedUri URI for unrevealed mechs.
    /// @param _provenanceHash Provenance Hash for mech metadata.
    constructor(
        // Mint config:
        address _ep,
        uint256 _mintStart,
        // Addresses:
        Shirak _shirak,
        Arms _arms,
        address _team,
        address _ticket, 
        RandProvider _randProvider,
        // URIs:
        string memory _baseUri,
        string memory _unrevealedUri,
        // Provenance:
        bytes32 _provenanceHash
    )
        MechsERC721("Mechavax", "MECH")
        Owned(msg.sender)
        LogisticVRGDA(
            69.42e18, // Target price.
            0.39e18, // Price decay percent.
            // Max mechs mintable via VRGDA.
            toWadUnsafe(MAX_MINTABLE),
            0.0042e18 // Time scale.
        )
    {
  
        mintStart = _mintStart;
        EP = _ep;
                
        shirak = _shirak;
        arms = _arms;
        team = _team;
        ticket = _ticket;
        randProvider = _randProvider;

        BASE_URI = _baseUri;
        UNREVEALED_URI = _unrevealedUri;

        PROVENANCE_HASH = _provenanceHash;

        // Set the starting price for the first legendary mech auction.
        legendaryMechAuctionData.startPrice = uint128(LEGENDARY_MECH_INITIAL_START_PRICE);

        // Reveal for initial mint must wait a day from the start of the mint.
        mechRevealsData.nextRevealTimestamp = uint64(_mintStart + 1 days);
    }

    modifier callerIsUser() {
        require(tx.origin == msg.sender, "The caller is another contract");
        _;
    }

    /*//////////////////////////////////////////////
                        NEWEP FUNCTION
    //////////////////////////////////////////////*/

    function setNewEP(address _newEP) external onlyOwner {
        newEP = _newEP;
    }

    /*//////////////////////////////////////////////
                PROVENANCE HASH FUNCTION
    //////////////////////////////////////////////*/

    function setPHash(bytes32 _provenanceHash) external onlyOwner {
        bytes32 oldHash = PROVENANCE_HASH;
        PROVENANCE_HASH = _provenanceHash;
        emit PhashUpdated(oldHash, PROVENANCE_HASH, msg.sender);
    }

    /*//////////////////////////////////////////////
                        ROYALTY FUNCTION
    //////////////////////////////////////////////*/

    function setTokenRoyalties(uint96 _royalties) external onlyOwner {
        tokenRoyalties = _royalties;
        _setDefaultRoyalty(royaltyPayout, tokenRoyalties);
    }

    function setRoyaltyPayoutAddress(address _payoutAddress) external onlyOwner
    {
        royaltyPayout = _payoutAddress;
        _setDefaultRoyalty(royaltyPayout, tokenRoyalties);
    }

    /*//////////////////////////////////////////////////////////////
                          MINTLIST CLAIM LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Claim from mintlist, using a ticket system.
    /// @dev Function does not directly enforce the MINTLIST_SUPPLY limit for gas efficiency. The
    /// limit is enforced during the creation of the ticket system, which will be shared publicly.
    /// @param _ticketIds the ID of tickets user wants to burn.
    /// @return mechId The id of the mech that was claimed.
    function claimMech(uint256[] calldata _ticketIds) payable external callerIsUser returns (uint256 mechId) {
        // If minting has not yet begun, revert.
        if (mintStart > block.timestamp) revert MintStartPending();
        //check for empty array
        require(_ticketIds.length > 0, "empty array");

        if(msg.value == 0){

            for (uint256 i = 0; i < _ticketIds.length; ++i) {

                ERC721(ticket).transferFrom(msg.sender, address(this), _ticketIds[i]);

                unchecked {
                    // Overflow should be impossible due to supply cap of 10,000.
                    emit MechClaimed(msg.sender, mechId = ++currentNonLegendaryId);
                }

                _mint(msg.sender, mechId); 
            }
        }

        else if(msg.value >= 1 ether * _ticketIds.length){
            
            require(payable(owner).send(msg.value));

            for (uint256 i = 0; i < _ticketIds.length; ++i) {
                 
                ERC721(EP).transferFrom(msg.sender, address(this), _ticketIds[i]);
                MintERC721(newEP).mint(msg.sender, _ticketIds[i]);
                unchecked {
                    // Overflow should be impossible due to supply cap of 10,000.
                    emit MechClaimed(msg.sender, mechId = ++currentNonLegendaryId);
                }

                _mint(msg.sender, mechId); 
            }
        }

        else revert("mint condition mismatch");
        

    }
    

    /*//////////////////////////////////////////////////////////////
                              MINTING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Mint a mech, paying with shirak.
    /// @param maxPrice Maximum price to pay to mint the mech.
    /// @param useVirtualBalance Whether the cost is paid from the
    /// user's virtual shirak balance, or from their ERC20 shirak balance.
    /// @return mechId The id of the mech that was minted.
    function mintFromShirak(uint256 maxPrice, bool useVirtualBalance) external returns (uint256 mechId) {
        // No need to check if we're at MAX_MINTABLE,
        // mechPrice() will revert once we reach it due to its
        // logistic nature. It will also revert prior to the mint start.
        uint256 currentPrice = mechPrice();

        // If the current price is above the user's specified max, revert.
        if (currentPrice > maxPrice) revert PriceExceededMax(currentPrice);

        // Decrement the user's shirak balance by the current
        // price, either from virtual balance or ERC20 balance.
        useVirtualBalance
            ? updateUserShirakBalance(msg.sender, currentPrice, ShirakBalanceUpdateType.DECREASE)
            : shirak.burnForMechs(msg.sender, currentPrice);

        unchecked {
            ++numMintedFromShirak; // Overflow should be impossible due to the supply cap.

            emit MechPurchased(msg.sender, mechId = ++currentNonLegendaryId, currentPrice);
        }

        _mint(msg.sender, mechId);
    }

    /// @notice Mech pricing in terms of shirak.
    /// @dev Will revert if called before minting starts
    /// or after all mechs have been minted via VRGDA.
    /// @return Current price of a mech in terms of shirak.
    function mechPrice() public view returns (uint256) {
        // We need checked math here to cause underflow
        // before minting has begun, preventing mints.
        uint256 timeSinceStart = block.timestamp - mintStart;

        return getVRGDAPrice(toDaysWadUnsafe(timeSinceStart), numMintedFromShirak);
    }

    /*//////////////////////////////////////////////////////////////
                     LEGENDARY GOBBLER AUCTION LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Mint a legendary mech by burning multiple standard mechs.
    /// @param mechIds The ids of the standard mechs to burn.
    /// @return mechId The id of the legendary mech that was minted.
    function mintLegendaryMech(uint256[] calldata mechIds) external returns (uint256 mechId) {
        if (legLock == true){
            require(msg.sender == legMinter, "not authorized");
        }
        // Get the number of legendary mechs sold up until this point.
        uint256 numSold = legendaryMechAuctionData.numSold;

        mechId = FIRST_LEGENDARY_MECH_ID + numSold; // Assign id.

        // This will revert if the auction hasn't started yet or legendaries
        // have sold out entirely, so there is no need to check here as well.
        uint256 cost = legendaryMechPrice();

        if (mechIds.length < cost) revert InsufficientMechAmount(cost);

        // Overflow should not occur in here, as most math is on emission multiples, which are inherently small.
        unchecked {
            uint256 burnedMultipleTotal; // The legendary's emissionMultiple will be 2x the sum of the mechs burned.

            /*//////////////////////////////////////////////////////////////
                                    BATCH BURN LOGIC
            //////////////////////////////////////////////////////////////*/

            uint256 id; // Storing outside the loop saves ~7 gas per iteration.

            for (uint256 i = 0; i < cost; ++i) {
                id = mechIds[i];

                if (id >= FIRST_LEGENDARY_MECH_ID) revert CannotBurnLegendary(id);

                MechData storage mech = getMechData[id];

                require(mech.owner == msg.sender, "WRONG_FROM");

                burnedMultipleTotal += mech.emissionMultiple;

                delete getApproved[id];

                emit Transfer(msg.sender, mech.owner = address(0), id);
            }

            /*//////////////////////////////////////////////////////////////
                                 LEGENDARY MINTING LOGIC
            //////////////////////////////////////////////////////////////*/

            // The legendary's emissionMultiple is 2x the sum of the multiples of the mechs burned.
            getMechData[mechId].emissionMultiple = uint32(burnedMultipleTotal * 2);

            // Update the user's user data struct in one big batch. We add burnedMultipleTotal to their
            // emission multiple (not burnedMultipleTotal * 2) to account for the standard mechs that
            // were burned and hence should have their multiples subtracted from the user's total multiple.
            getUserData[msg.sender].lastBalance = uint128(shirakBalance(msg.sender)); // Checkpoint balance.
            getUserData[msg.sender].lastTimestamp = uint64(block.timestamp); // Store time alongside it.
            getUserData[msg.sender].emissionMultiple += uint32(burnedMultipleTotal); // Update multiple.
            // Update the total number of mechs owned by the user. The call to _mint
            // below will increase the count by 1 to account for the new legendary mech.
            getUserData[msg.sender].mechsOwned -= uint32(cost);

            // New start price is the max of LEGENDARY_MECH_INITIAL_START_PRICE and cost * 2.
            legendaryMechAuctionData.startPrice = uint128(
                cost <= LEGENDARY_MECH_INITIAL_START_PRICE / 2 ? LEGENDARY_MECH_INITIAL_START_PRICE : cost * 2
            );
            legendaryMechAuctionData.numSold = uint128(numSold + 1); // Increment the # of legendaries sold.

            // If mechIds has 1,000 elements this should cost around ~270,000 gas.
            emit LegendaryMechMinted(msg.sender, mechId, mechIds[:cost]);

            _mint(msg.sender, mechId);
        }
    }

    /// @notice Calculate the legendary mech price in terms of mechs, according to a linear decay function.
    /// @dev The price of a legendary mech decays as mechs are minted. The first legendary auction begins when
    /// 1 LEGENDARY_AUCTION_INTERVAL worth of mechs are minted, and the price decays linearly while the next interval of
    /// mechs are minted. Every time an additional interval is minted, a new auction begins until all legendaries have been sold.
    /// @dev Will revert if the auction hasn't started yet or legendaries have sold out entirely.
    /// @return The current price of the legendary mech being auctioned, in terms of mechs.
    function legendaryMechPrice() public view returns (uint256) {
        // Retrieve and cache various auction parameters and variables.
        uint256 startPrice = legendaryMechAuctionData.startPrice;
        uint256 numSold = legendaryMechAuctionData.numSold;

        // If all legendary mechs have been sold, there are none left to auction.
        if (numSold == LEGENDARY_SUPPLY) revert NoRemainingLegendaryMechs();

        unchecked {
            // Get and cache the number of standard mechs sold via VRGDA up until this point.
            uint256 mintedFromShirak = numMintedFromShirak;

            // The number of mechs minted at the start of the auction is computed by multiplying the # of
            // intervals that must pass before the next auction begins by the number of mechs in each interval.
            uint256 numMintedAtStart = (numSold + 1) * LEGENDARY_AUCTION_INTERVAL;

            // If not enough mechs have been minted to start the auction yet, return how many need to be minted.
            if (numMintedAtStart > mintedFromShirak) revert LegendaryAuctionNotStarted(numMintedAtStart - mintedFromShirak);

            // Compute how many mechs were minted since the auction began.
            uint256 numMintedSinceStart = mintedFromShirak - numMintedAtStart;

            // prettier-ignore
            // If we've minted the full interval or beyond it, the price has decayed to 0.
            if (numMintedSinceStart >= LEGENDARY_AUCTION_INTERVAL) return 0;
            // Otherwise decay the price linearly based on what fraction of the interval has been minted.
            else return FixedPointMathLib.unsafeDivUp(startPrice * (LEGENDARY_AUCTION_INTERVAL - numMintedSinceStart), LEGENDARY_AUCTION_INTERVAL);
        }
    }

    /*//////////////////////////////////////////////////////////////
                            RANDOMNESS LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Request a new random seed for revealing mechs.
    function requestRandomSeed() external returns (bytes32) {
        uint256 nextRevealTimestamp = mechRevealsData.nextRevealTimestamp;

        // A new random seed cannot be requested before the next reveal timestamp.
        if (block.timestamp < nextRevealTimestamp) revert RequestTooEarly();

        // A random seed can only be requested when all mechs from the previous seed have been revealed.
        // This prevents a user from requesting additional randomness in hopes of a more favorable outcome.
        if (mechRevealsData.toBeRevealed != 0) revert RevealsPending();

        unchecked {
            // Prevent revealing while we wait for the seed.
            mechRevealsData.waitingForSeed = true;

            // Compute the number of mechs to be revealed with the seed.
            uint256 toBeRevealed = currentNonLegendaryId - mechRevealsData.lastRevealedId;

            // Ensure that there are more than 0 mechs to be revealed,
            // otherwise the contract could waste LINK revealing nothing.
            if (toBeRevealed == 0) revert ZeroToBeRevealed();

            // Lock in the number of mechs to be revealed from seed.
            mechRevealsData.toBeRevealed = uint56(toBeRevealed);

            // We enable reveals for a set of mechs every 24 hours.
            // Timestamp overflow is impossible on human timescales.
            mechRevealsData.nextRevealTimestamp = uint64(nextRevealTimestamp + 1 days);

            emit RandomnessRequested(msg.sender, toBeRevealed);
        }

        // Call out to the randomness provider.
        return randProvider.requestRandomBytes();
    }

    /// @notice Callback from rand provider. Sets randomSeed. Can only be called by the rand provider.
    /// @param randomness The 256 bits of verifiable randomness provided by the rand provider.
    function acceptRandomSeed(bytes32, uint256 randomness) external {
        // The caller must be the randomness provider, revert in the case it's not.
        if (msg.sender != address(randProvider)) revert NotRandProvider();

        // The unchecked cast to uint64 is equivalent to moduloing the randomness by 2**64.
        mechRevealsData.randomSeed = uint64(randomness); // 64 bits of randomness is plenty.

        mechRevealsData.waitingForSeed = false; // We have the seed now, open up reveals.

        emit RandomnessFulfilled(randomness);
    }

    /// @notice Upgrade the rand provider contract. Useful if current VRF is sunset.
    /// @param newRandProvider The new randomness provider contract address.
    function upgradeRandProvider(RandProvider newRandProvider) external onlyOwner {
        // Reset reveal state when we upgrade while the seed is pending. This gives us a
        // safeguard against malfunctions since we won't be stuck waiting for a seed forever.
        if (mechRevealsData.waitingForSeed) {
            mechRevealsData.waitingForSeed = false;
            mechRevealsData.toBeRevealed = 0;
            mechRevealsData.nextRevealTimestamp -= 1 days;
        }

        randProvider = newRandProvider; // Update the randomness provider.

        emit RandProviderUpgraded(msg.sender, newRandProvider);
    }

    /*//////////////////////////////////////////////////////////////
                          GOBBLER REVEAL LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Knuth shuffle to progressively reveal
    /// new mechs using entropy from a random seed.
    /// @param numMechs The number of mechs to reveal.
    function revealMechs(uint256 numMechs) external {
        uint256 randomSeed = mechRevealsData.randomSeed;

        uint256 lastRevealedId = mechRevealsData.lastRevealedId;

        uint256 totalRemainingToBeRevealed = mechRevealsData.toBeRevealed;

        // Can't reveal if we're still waiting for a new seed.
        if (mechRevealsData.waitingForSeed) revert SeedPending();

        // Can't reveal more mechs than are currently remaining to be revealed with the seed.
        if (numMechs > totalRemainingToBeRevealed) revert NotEnoughRemainingToBeRevealed(totalRemainingToBeRevealed);

        // Implements a Knuth shuffle. If something in
        // here can overflow, we've got bigger problems.
        unchecked {
            for (uint256 i = 0; i < numMechs; ++i) {
                /*//////////////////////////////////////////////////////////////
                                      DETERMINE RANDOM SWAP
                //////////////////////////////////////////////////////////////*/

                // Number of ids that have not been revealed. Subtract 1
                // because we don't want to include any legendaries in the swap.
                uint256 remainingIds = FIRST_LEGENDARY_MECH_ID - lastRevealedId - 1;

                // Randomly pick distance for swap.
                uint256 distance = randomSeed % remainingIds;

                // Current id is consecutive to last reveal.
                uint256 currentId = ++lastRevealedId;

                // Select swap id, adding distance to next reveal id.
                uint256 swapId = currentId + distance;

                /*//////////////////////////////////////////////////////////////
                                       GET INDICES FOR IDS
                //////////////////////////////////////////////////////////////*/

                // Get the index of the swap id.
                uint64 swapIndex = getMechData[swapId].idx == 0
                    ? uint64(swapId) // Hasn't been shuffled before.
                    : getMechData[swapId].idx; // Shuffled before.

                // Get the owner of the current id.
                address currentIdOwner = getMechData[currentId].owner;

                // Get the index of the current id.
                uint64 currentIndex = getMechData[currentId].idx == 0
                    ? uint64(currentId) // Hasn't been shuffled before.
                    : getMechData[currentId].idx; // Shuffled before.

                /*//////////////////////////////////////////////////////////////
                                  SWAP INDICES AND SET MULTIPLE
                //////////////////////////////////////////////////////////////*/

                // Determine the current id's new emission multiple.
                uint256 newCurrentIdMultiple = 9; // For beyond 7963.

                // The branchless expression below is equivalent to:
                //      if (swapIndex <= 3054) newCurrentIdMultiple = 6;
                // else if (swapIndex <= 5672) newCurrentIdMultiple = 7;
                // else if (swapIndex <= 7963) newCurrentIdMultiple = 8;
                assembly {
                    // prettier-ignore
                    newCurrentIdMultiple := sub(sub(sub(
                        newCurrentIdMultiple,
                        lt(swapIndex, 3584)),
                        lt(swapIndex, 2552)),
                        lt(swapIndex, 1374)
                    )
                }

                // Swap the index and multiple of the current id.
                getMechData[currentId].idx = swapIndex;
                getMechData[currentId].emissionMultiple = uint32(newCurrentIdMultiple);

                // Swap the index of the swap id.
                getMechData[swapId].idx = currentIndex;

                /*//////////////////////////////////////////////////////////////
                                   UPDATE CURRENT ID MULTIPLE
                //////////////////////////////////////////////////////////////*/

                // Update the user data for the owner of the current id.
                getUserData[currentIdOwner].lastBalance = uint128(shirakBalance(currentIdOwner));
                getUserData[currentIdOwner].lastTimestamp = uint64(block.timestamp);
                getUserData[currentIdOwner].emissionMultiple += uint32(newCurrentIdMultiple);

                // Update the random seed to choose a new distance for the next iteration.
                // It is critical that we cast to uint64 here, as otherwise the random seed
                // set after calling revealMechs(1) thrice would differ from the seed set
                // after calling revealMechs(3) a single time. This would enable an attacker
                // to choose from a number of different seeds and use whichever is most favorable.
                // Equivalent to randomSeed = uint64(uint256(keccak256(abi.encodePacked(randomSeed))))
                assembly {
                    mstore(0, randomSeed) // Store the random seed in scratch space.

                    // Moduloing by 2 ** 64 is equivalent to a uint64 cast.
                    randomSeed := mod(keccak256(0, 32), exp(2, 64))
                }
            }

            // Update all relevant reveal state.
            mechRevealsData.randomSeed = uint64(randomSeed);
            mechRevealsData.lastRevealedId = uint64(lastRevealedId);
            mechRevealsData.toBeRevealed = uint56(totalRemainingToBeRevealed - numMechs);

            emit MechsRevealed(msg.sender, numMechs, lastRevealedId);
        }
    }

    /*//////////////////////////////////////////////////////////////
                                URI LOGIC
    //////////////////////////////////////////////////////////////*/

    function setBaseURI(string calldata baseURI_) external onlyOwner {
    BASE_URI = baseURI_;
    }

    function setUnrevealedURI(string calldata UnrevealedURI_) external onlyOwner {
    UNREVEALED_URI = UnrevealedURI_;
    }

    function setBaseExtension(string memory newBaseExtension) public onlyOwner {
    URI_EXTENSION = newBaseExtension;
    }

    /// @notice Returns a token's URI if it has been minted.
    /// @param mechId The id of the token to get the URI for.
    function tokenURI(uint256 mechId) public view virtual override returns (string memory) {
        // Between 0 and lastRevealed are revealed normal mechs.
        if (mechId <= mechRevealsData.lastRevealedId) {
            if (mechId == 0) revert("NOT_MINTED"); // 0 is not a valid id for Art Mechs.

            return string.concat(BASE_URI, uint256(getMechData[mechId].idx).toString(), URI_EXTENSION);
        }

        // Between lastRevealed + 1 and currentNonLegendaryId are minted but not revealed.
        if (mechId <= currentNonLegendaryId) return UNREVEALED_URI;

        // Between currentNonLegendaryId and FIRST_LEGENDARY_MECH_ID are unminted.
        if (mechId < FIRST_LEGENDARY_MECH_ID) revert("NOT_MINTED");

        // Between FIRST_LEGENDARY_MECH_ID and FIRST_LEGENDARY_MECH_ID + numSold are minted legendaries.
        if (mechId < FIRST_LEGENDARY_MECH_ID + legendaryMechAuctionData.numSold)
            return string.concat(BASE_URI, mechId.toString(), URI_EXTENSION);

        revert("NOT_MINTED"); // Unminted legendaries and invalid token ids.
    } 

    /*//////////////////////////////////////////////////////////////
                            EQUIP ARM LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Soulbond armament to a mech.
    /// @param mechId The mech to feed the work of art.
    /// @param nft The ERC721 or ERC1155 contract of the armament.
    /// @param id The id of the armament.
    /// @param isERC1155 Whether the armament is an ERC1155 token.
    function bondArms(
        uint256 mechId,
        address nft,
        uint256 id,
        bool isERC1155
    ) external {
        // Get the owner of the mech to feed.
        address owner = getMechData[mechId].owner;

        // The caller must own the mech they're feeding.
        if (owner != msg.sender) revert OwnerMismatch(owner);

        // Mechs have taken a vow not to eat other mechs.
        if (nft == address(this)) revert Cannibalism();

        unchecked {
            // Increment the # of copies gobbled by the mech. Unchecked is
            // safe, as an NFT can't have more than type(uint256).max copies.
            ++getCopiesOfArmsBondedToMech[mechId][nft][id];
        }

        emit ArmsBonded(msg.sender, mechId, nft, id);

        isERC1155
            ? ERC1155(nft).safeTransferFrom(msg.sender, address(this), id, 1, "")
            : ERC721(nft).transferFrom(msg.sender, address(this), id);
    }

    /*//////////////////////////////////////////////////////////////
                                SHIRAK LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Calculate a user's virtual shirak balance.
    /// @param user The user to query balance for.
    function shirakBalance(address user) public view returns (uint256) {
        // Compute the user's virtual shirak balance using LibGOO.
        // prettier-ignore
        return LibGOO.computeGOOBalance(
            getUserData[user].emissionMultiple,
            getUserData[user].lastBalance,
            uint256(toDaysWadUnsafe(block.timestamp - getUserData[user].lastTimestamp))
        );
    }

    /// @notice Add shirak to your emission balance,
    /// burning the corresponding ERC20 balance.
    /// @param shirakAmount The amount of shirak to add.
    function addShirak(uint256 shirakAmount) external {
        // Burn shirak being added to mech.
        shirak.burnForMechs(msg.sender, shirakAmount);

        // Increase msg.sender's virtual shirak balance.
        updateUserShirakBalance(msg.sender, shirakAmount, ShirakBalanceUpdateType.INCREASE);
    }

    /// @notice Remove shirak from your emission balance, and
    /// add the corresponding amount to your ERC20 balance.
    /// @param shirakAmount The amount of shirak to remove.
    function removeShirak(uint256 shirakAmount) external {
        // Decrease msg.sender's virtual shirak balance.
        updateUserShirakBalance(msg.sender, shirakAmount, ShirakBalanceUpdateType.DECREASE);

        // Mint the corresponding amount of ERC20 shirak.
        shirak.mintForMechs(msg.sender, shirakAmount);
    }

    /// @notice Burn an amount of a user's virtual shirak balance. Only callable
    /// by the Arms contract to enable purchasing arms with virtual balance.
    /// @param user The user whose virtual shirak balance we should burn from.
    /// @param shirakAmount The amount of shirak to burn from the user's virtual balance.
    function burnShirakForArms(address user, uint256 shirakAmount) external {
        // The caller must be the Arms contract, revert otherwise.
        if (msg.sender != address(arms)) revert UnauthorizedCaller(msg.sender);

        // Burn the requested amount of shirak from the user's virtual shirak balance.
        // Will revert if the user doesn't have enough shirak in their virtual balance.
        updateUserShirakBalance(user, shirakAmount, ShirakBalanceUpdateType.DECREASE);
    }

    /// @dev An enum for representing whether to
    /// increase or decrease a user's shirak balance.
    enum ShirakBalanceUpdateType {
        INCREASE,
        DECREASE
    }

    /// @notice Update a user's virtual shirak balance.
    /// @param user The user whose virtual shirak balance we should update.
    /// @param shirakAmount The amount of shirak to update the user's virtual balance by.
    /// @param updateType Whether to increase or decrease the user's balance by shirakAmount.
    function updateUserShirakBalance(
        address user,
        uint256 shirakAmount,
        ShirakBalanceUpdateType updateType
    ) internal {
        // Will revert due to underflow if we're decreasing by more than the user's current balance.
        // Don't need to do checked addition in the increase case, but we do it anyway for convenience.
        uint256 updatedBalance = updateType == ShirakBalanceUpdateType.INCREASE
            ? shirakBalance(user) + shirakAmount
            : shirakBalance(user) - shirakAmount;

        // Snapshot the user's new shirak balance with the current timestamp.
        getUserData[user].lastBalance = uint128(updatedBalance);
        getUserData[user].lastTimestamp = uint64(block.timestamp);

        emit ShirakBalanceUpdated(user, updatedBalance);
    }

    /*//////////////////////////////////////////////////////////////
                     RESERVED MECHS MINTING LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Mint a number of mechs to the reserves.
    /// @param numMechsEach The number of mechs to mint to each reserve.
    /// @dev Mechs minted to reserves cannot comprise more than reserved supply.
    function mintReservedMechs(uint256 numMechsEach) external returns (uint256 lastMintedMechId) {
        unchecked {
            // Optimistically increment numMintedForReserves, may be reverted below.
            // Overflow in this calculation is possible but numMechsEach would have to
            // be so large that it would cause the loop in _batchMint to run out of gas quickly.
            uint256 newNumMintedForReserves = numMintedForReserves += (numMechsEach);

            // Ensure that after this mint mechs minted to reserves won't comprise more then the 
            // calculated reserve supply.
            if (newNumMintedForReserves > RESERVED_SUPPLY) revert ReserveImbalance();
        }

        // Mint numMechsEach mechs to the team for auction.
        lastMintedMechId = _batchMint(team, numMechsEach, currentNonLegendaryId);

        currentNonLegendaryId = uint128(lastMintedMechId); // Set currentNonLegendaryId.

        emit ReservedMechsMinted(msg.sender, lastMintedMechId, numMechsEach);
    }

    /*//////////////////////////////////////////////////////////////
                          CONVENIENCE FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @notice Convenience function to get emissionMultiple for a mech.
    /// @param mechId The mech to get emissionMultiple for.
    function getMechEmissionMultiple(uint256 mechId) external view returns (uint256) {
        return getMechData[mechId].emissionMultiple;
    }

    /// @notice Convenience function to get emissionMultiple for a user.
    /// @param user The user to get emissionMultiple for.
    function getUserEmissionMultiple(address user) external view returns (uint256) {
        return getUserData[user].emissionMultiple;
    }

    /*//////////////////////////////////////////////////////////////
                              ENUMERABLE SIMULATION
    //////////////////////////////////////////////////////////////*/

    function tokensOfOwner(address owner) public view returns (uint256[] memory) {
        unchecked {
            uint256 tokenIdsIdx;
            address currOwnershipAddr;
            address ownership;
            uint256 tokenIdsLength = getUserData[owner].mechsOwned;
            uint256[] memory tokenIds = new uint256[](tokenIdsLength);
            for (uint256 i = 1; tokenIdsIdx != tokenIdsLength; ++i) {
                ownership = getMechData[i].owner;
                if (ownership == address(0)) {
                    continue;
                }
                if (ownership != address(0)) {
                    currOwnershipAddr = ownership;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            return tokenIds;
        }
    }

    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256) {
        require(index < getUserData[owner].mechsOwned, "ERC721Enumerable: owner index out of bounds");
        return tokensOfOwner(owner)[index];
    }

    /*//////////////////////////////////////////////////////////////
                              STAKING LOGIC
    //////////////////////////////////////////////////////////////*/

    function setNoTransferStaking (bool _bool) external onlyOwner {
        noTransferStaking = _bool;
    }

    function setStakeLocker (address _stakeLocker) external onlyOwner {
        stakeLocker = _stakeLocker;
    }

    function setMechStaked (uint256 _id, bool _staked) external {
        require(msg.sender == stakeLocker, "not authorized" );
        MechStaked storage mech = mechStaked[_id];
        mech.isStaked  = _staked;
    }

    /*//////////////////////////////////////////////////////////////
                              LEGENDARY LOCK LOGIC
    //////////////////////////////////////////////////////////////*/

    function setLegLock (bool _bool) external onlyOwner {
        legLock = _bool;
    }

    function setLegMinter (address _legMinter) external onlyOwner {
        legMinter = _legMinter;
    }

   
    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public override {
        if (noTransferStaking == true) {
            require (mechStaked[id].isStaked == false, "Token is staked");
        }

        require(from == getMechData[id].owner, "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        delete getApproved[id];

        getMechData[id].owner = to;

        unchecked {
            uint32 emissionMultiple = getMechData[id].emissionMultiple; // Caching saves gas.

            // We update their last balance before updating their emission multiple to avoid
            // penalizing them by retroactively applying their new (lower) emission multiple.
            getUserData[from].lastBalance = uint128(shirakBalance(from));
            getUserData[from].lastTimestamp = uint64(block.timestamp);
            getUserData[from].emissionMultiple -= emissionMultiple;
            getUserData[from].mechsOwned -= 1;

            // We update their last balance before updating their emission multiple to avoid
            // overpaying them by retroactively applying their new (higher) emission multiple.
            getUserData[to].lastBalance = uint128(shirakBalance(to));
            getUserData[to].lastTimestamp = uint64(block.timestamp);
            getUserData[to].emissionMultiple += emissionMultiple;
            getUserData[to].mechsOwned += 1;
        }

        emit Transfer(from, to, id);
    }
}

File 19 of 23 : MintERC721.sol
pragma solidity ^0.8.13;

interface MintERC721 {
   function mint(address, uint256) external returns(bool);
}

File 20 of 23 : Shirak.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {ERC20} from "solmate/tokens/ERC20.sol";



/// @title Shirak Token (SHK)
/// @notice Forked by 0xBoots
/// @author FrankieIsLost <[email protected]>
/// @author transmissions11 <[email protected]>
/// @notice Shirak is the in-game token for ArtMechs. It's a standard ERC20
/// token that can be burned and minted by the mechs and arms contract.
contract Shirak is ERC20("Shirak", "SHK", 18) {
    /*//////////////////////////////////////////////////////////////
                                ADDRESSES
    //////////////////////////////////////////////////////////////*/

    /// @notice The address of the Art Mechs contract.
    address public immutable mechAvax;

    /// @notice The address of the Arms contract.
    address public immutable arms;

    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    error Unauthorized();

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    /// @notice Sets the addresses of relevant contracts.
    /// @param _mechAvax Address of the ArtMechs contract.
    /// @param _arms Address of the Arms contract.
    constructor(address _mechAvax, address _arms) {
        mechAvax = _mechAvax;
        arms = _arms;
    }

    /*//////////////////////////////////////////////////////////////
                             MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    /// @notice Requires caller address to match user address.
    modifier only(address user) {
        if (msg.sender != user) revert Unauthorized();

        _;
    }

    /// @notice Mint any amount of shirak to a user. Can only be called by ArtMechs.
    /// @param to The address of the user to mint shirak to.
    /// @param amount The amount of shirak to mint.
    function mintForMechs(address to, uint256 amount) external only(mechAvax) {
        _mint(to, amount);
    }

    /// @notice Burn any amount of shirak from a user. Can only be called by ArtMechs.
    /// @param from The address of the user to burn shirak from.
    /// @param amount The amount of shirak to burn.
    function burnForMechs(address from, uint256 amount) external only(mechAvax) {
        _burn(from, amount);
    }

    /// @notice Burn any amount of shirak from a user. Can only be called by Arms.
    /// @param from The address of the user to burn shirak from.
    /// @param amount The amount of shirak to burn.
    function burnForArms(address from, uint256 amount) external only(arms) {
        _burn(from, amount);
    }
}

File 21 of 23 : RandProvider.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @title Randomness Provider Interface.
/// @author FrankieIsLost <[email protected]>
/// @author transmissions11 <[email protected]>
/// @notice Generic asynchronous randomness provider interface.
interface RandProvider {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event RandomBytesRequested(bytes32 requestId);
    event RandomBytesReturned(bytes32 requestId, uint256 randomness);

    /*//////////////////////////////////////////////////////////////
                                FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /// @dev Request random bytes from the randomness provider.
    function requestRandomBytes() external returns (bytes32 requestId);
}

File 22 of 23 : ArmsERC721.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {ERC721TokenReceiver} from "solmate/tokens/ERC721.sol";
import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol";
import {MechAvax} from "../../MechAvax.sol";


/// @notice ERC721 implementation optimized for Arms by pre-approving them to the MechAvax contract.
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ArmsERC721 is ERC2981{
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) external view virtual returns (string memory);


    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    MechAvax public immutable mechAvax;

    constructor(
        MechAvax _mechAvax,
        string memory _name,
        string memory _symbol
    ) {
        name = _name;
        symbol = _symbol;
        mechAvax = _mechAvax;
    }

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) external view returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) external view returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) internal _isApprovedForAll;

    function isApprovedForAll(address owner, address operator) public view returns (bool isApproved) {
        if (operator == address(mechAvax)) return true; // Skip approvals for the MechAvax contract.

        return _isApprovedForAll[owner][operator];
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) external {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll(owner, msg.sender), "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) external {
        _isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll(from, msg.sender) || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) external {
        transferFrom(from, to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) external {
        transferFrom(from, to, id);

        if (to.code.length != 0)
            require(
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                    ERC721TokenReceiver.onERC721Received.selector,
                "UNSAFE_RECIPIENT"
            );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view override(ERC2981) returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f || // ERC165 Interface ID for 
            super.supportsInterface(interfaceId); //ERC2981 support
           
            
    }

    /*//////////////////////////////////////////////////////////////
                           INTERNAL MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal {
        // Does not check the token has not been already minted
        // or is being minted to address(0) because ids in Arms.sol
        // are set using a monotonically increasing counter and only
        // minted to safe addresses or msg.sender who cannot be zero.

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

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

    function _batchMint(
        address to,
        uint256 amount,
        uint256 lastMintedId
    ) internal returns (uint256) {
        // Doesn't check if the tokens were already minted or the recipient is address(0)
        // because Arms.sol manages its ids in a way that it ensures it won't double
        // mint and will only mint to safe addresses or msg.sender who cannot be zero.

        unchecked {
            _balanceOf[to] += amount;

            for (uint256 i = 0; i < amount; ++i) {
                _ownerOf[++lastMintedId] = to;

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

        return lastMintedId;
    }
}

File 23 of 23 : MechsERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC721TokenReceiver} from "solmate/tokens/ERC721.sol";
import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol";

/// @notice ERC721 implementation optimized for MechAvax by packing balanceOf/ownerOf with user/attribute data.
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract MechsERC721 is ERC2981{
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) external view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                         GOBBLERS/ERC721 STORAGE
    //////////////////////////////////////////////////////////////*/

    /// @notice Struct holding mech data.
    struct MechData {
        // The current owner of the mech.
        address owner;
        // Index of token after shuffle.
        uint64 idx;
        // Multiple on shirak issuance.
        uint32 emissionMultiple;
    }

    /// @notice Maps mech ids to their data.
    mapping(uint256 => MechData) public getMechData;

    /// @notice Struct holding data relevant to each user's account.
    struct UserData {
        // The total number of mechs currently owned by the user.
        uint32 mechsOwned;
        // The sum of the multiples of all mechs the user holds.
        uint32 emissionMultiple;
        // User's shirak balance at time of last checkpointing.
        uint128 lastBalance;
        // Timestamp of the last shirak balance checkpoint.
        uint64 lastTimestamp;
    }

    /// @notice Maps user addresses to their account data.
    mapping(address => UserData) public getUserData;

    function ownerOf(uint256 id) external view returns (address owner) {
        require((owner = getMechData[id].owner) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) external view returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return getUserData[owner].mechsOwned;
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) external {
        address owner = getMechData[id].owner;

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) external {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual;

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) external {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) external {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }


    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view override(ERC2981) returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f ||  // ERC165 Interface ID for ERC721Metadata
            super.supportsInterface(interfaceId);
    }

    /*//////////////////////////////////////////////////////////////
                           INTERNAL MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal {
        // Does not check if the token was already minted or the recipient is address(0)
        // because MechAvax.sol manages its ids in such a way that it ensures it won't
        // double mint and will only mint to safe addresses or msg.sender who cannot be zero.

        unchecked {
            ++getUserData[to].mechsOwned;
        }

        getMechData[id].owner = to;

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

    function _batchMint(
        address to,
        uint256 amount,
        uint256 lastMintedId
    ) internal returns (uint256) {
        // Doesn't check if the tokens were already minted or the recipient is address(0)
        // because MechAvax.sol manages its ids in such a way that it ensures it won't
        // double mint and will only mint to safe addresses or msg.sender who cannot be zero.

        unchecked {
            getUserData[to].mechsOwned += uint32(amount);

            for (uint256 i = 0; i < amount; ++i) {
                getMechData[++lastMintedId].owner = to;

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

        return lastMintedId;
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/=node_modules/@openzeppelin/",
    "VRGDAs/=lib/VRGDAs/src/",
    "chainlink/=lib/chainlink/contracts/src/",
    "ds-test/=lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "goo-issuance/=lib/goo-issuance/src/",
    "shirak-issuance/=lib/shirak-issuance/src/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_ep","type":"address"},{"internalType":"uint256","name":"_mintStart","type":"uint256"},{"internalType":"contract Shirak","name":"_shirak","type":"address"},{"internalType":"contract Arms","name":"_arms","type":"address"},{"internalType":"address","name":"_team","type":"address"},{"internalType":"address","name":"_ticket","type":"address"},{"internalType":"contract RandProvider","name":"_randProvider","type":"address"},{"internalType":"string","name":"_baseUri","type":"string"},{"internalType":"string","name":"_unrevealedUri","type":"string"},{"internalType":"bytes32","name":"_provenanceHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"Cannibalism","type":"error"},{"inputs":[{"internalType":"uint256","name":"mechId","type":"uint256"}],"name":"CannotBurnLegendary","type":"error"},{"inputs":[{"internalType":"uint256","name":"cost","type":"uint256"}],"name":"InsufficientMechAmount","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[{"internalType":"uint256","name":"mechsLeft","type":"uint256"}],"name":"LegendaryAuctionNotStarted","type":"error"},{"inputs":[],"name":"MintStartPending","type":"error"},{"inputs":[],"name":"NoRemainingLegendaryMechs","type":"error"},{"inputs":[{"internalType":"uint256","name":"totalRemainingToBeRevealed","type":"uint256"}],"name":"NotEnoughRemainingToBeRevealed","type":"error"},{"inputs":[],"name":"NotRandProvider","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnerMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"currentPrice","type":"uint256"}],"name":"PriceExceededMax","type":"error"},{"inputs":[],"name":"RequestTooEarly","type":"error"},{"inputs":[],"name":"ReserveImbalance","type":"error"},{"inputs":[],"name":"RevealsPending","type":"error"},{"inputs":[],"name":"SeedPending","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"UnauthorizedCaller","type":"error"},{"inputs":[],"name":"ZeroToBeRevealed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"mechId","type":"uint256"},{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"}],"name":"ArmsBonded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"mechId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"burnedMechIds","type":"uint256[]"}],"name":"LegendaryMechMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"mechId","type":"uint256"}],"name":"MechClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"mechId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"MechPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"numMechs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lastRevealedId","type":"uint256"}],"name":"MechsRevealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"oldPhash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"newPhash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"updater","type":"address"}],"name":"PhashUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"contract RandProvider","name":"newRandProvider","type":"address"}],"name":"RandProviderUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"RandomnessFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"toBeRevealed","type":"uint256"}],"name":"RandomnessRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"lastMintedMechId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numMechsEach","type":"uint256"}],"name":"ReservedMechsMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newShirakBalance","type":"uint256"}],"name":"ShirakBalanceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BASE_URI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FIRST_LEGENDARY_MECH_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEGENDARY_AUCTION_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEGENDARY_MECH_INITIAL_START_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LEGENDARY_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MINTABLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTLIST_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROVENANCE_HASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESERVED_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNREVEALED_URI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"URI_EXTENSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"randomness","type":"uint256"}],"name":"acceptRandomSeed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shirakAmount","type":"uint256"}],"name":"addShirak","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"arms","outputs":[{"internalType":"contract Arms","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mechId","type":"uint256"},{"internalType":"address","name":"nft","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bool","name":"isERC1155","type":"bool"}],"name":"bondArms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"shirakAmount","type":"uint256"}],"name":"burnShirakForArms","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_ticketIds","type":"uint256[]"}],"name":"claimMech","outputs":[{"internalType":"uint256","name":"mechId","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"currentNonLegendaryId","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getCopiesOfArmsBondedToMech","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getMechData","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint64","name":"idx","type":"uint64"},{"internalType":"uint32","name":"emissionMultiple","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mechId","type":"uint256"}],"name":"getMechEmissionMultiple","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"sold","type":"int256"}],"name":"getTargetSaleTime","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getUserData","outputs":[{"internalType":"uint32","name":"mechsOwned","type":"uint32"},{"internalType":"uint32","name":"emissionMultiple","type":"uint32"},{"internalType":"uint128","name":"lastBalance","type":"uint128"},{"internalType":"uint64","name":"lastTimestamp","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserEmissionMultiple","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"int256","name":"timeSinceStart","type":"int256"},{"internalType":"uint256","name":"sold","type":"uint256"}],"name":"getVRGDAPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legLock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legMinter","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legendaryMechAuctionData","outputs":[{"internalType":"uint128","name":"startPrice","type":"uint128"},{"internalType":"uint128","name":"numSold","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"legendaryMechPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mechPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mechRevealsData","outputs":[{"internalType":"uint64","name":"randomSeed","type":"uint64"},{"internalType":"uint64","name":"nextRevealTimestamp","type":"uint64"},{"internalType":"uint64","name":"lastRevealedId","type":"uint64"},{"internalType":"uint56","name":"toBeRevealed","type":"uint56"},{"internalType":"bool","name":"waitingForSeed","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"mechStaked","outputs":[{"internalType":"bool","name":"isStaked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxPrice","type":"uint256"},{"internalType":"bool","name":"useVirtualBalance","type":"bool"}],"name":"mintFromShirak","outputs":[{"internalType":"uint256","name":"mechId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"mechIds","type":"uint256[]"}],"name":"mintLegendaryMech","outputs":[{"internalType":"uint256","name":"mechId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numMechsEach","type":"uint256"}],"name":"mintReservedMechs","outputs":[{"internalType":"uint256","name":"lastMintedMechId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newEP","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"noTransferStaking","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numMintedForReserves","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numMintedFromShirak","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"randProvider","outputs":[{"internalType":"contract RandProvider","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shirakAmount","type":"uint256"}],"name":"removeShirak","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestRandomSeed","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numMechs","type":"uint256"}],"name":"revealMechs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"royaltyPayout","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"newBaseExtension","type":"string"}],"name":"setBaseExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"baseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_bool","type":"bool"}],"name":"setLegLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_legMinter","type":"address"}],"name":"setLegMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"},{"internalType":"bool","name":"_staked","type":"bool"}],"name":"setMechStaked","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newEP","type":"address"}],"name":"setNewEP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_bool","type":"bool"}],"name":"setNoTransferStaking","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_provenanceHash","type":"bytes32"}],"name":"setPHash","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_payoutAddress","type":"address"}],"name":"setRoyaltyPayoutAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeLocker","type":"address"}],"name":"setStakeLocker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint96","name":"_royalties","type":"uint96"}],"name":"setTokenRoyalties","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"UnrevealedURI_","type":"string"}],"name":"setUnrevealedURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shirak","outputs":[{"internalType":"contract Shirak","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"shirakBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakeLocker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetPrice","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"team","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ticket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenRoyalties","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"mechId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract RandProvider","name":"newRandProvider","type":"address"}],"name":"upgradeRandProvider","outputs":[],"stateMutability":"nonpayable","type":"function"}]

600880546001600160a01b0316607d60a31b17905561022060405260056101e081905264173539b7b760d91b61020090815262000040916010919062000547565b506013805461ffff191690553480156200005957600080fd5b5060405162005702380380620057028339810160408190526200007c91620006d7565b336803c3656232739e00006705698eef06670000620000ce610138600c620000a961089e611194620007dd565b620000b59190620007dd565b620000c19190620007dd565b670de0b6b3a76400000290565b604080518082018252600881526709acac6d0c2ecc2f60c31b60208083019182528351808501909452600484526309a8a86960e31b908401528151660eebe0b40e800093879387939092620001269160029162000547565b5080516200013c90600390602084019062000547565b5050506080829052620001626200015c82670de0b6b3a7640000620007f7565b6200031e565b60a0819052600013620001bc5760405162461bcd60e51b815260206004820152601b60248201527f4e4f4e5f4e454741544956455f44454341595f434f4e5354414e54000000000060448201526064015b60405180910390fd5b50620001d3905082670de0b6b3a76400006200083c565b60c0819052620001ec90671bc16d674ec8000062000883565b60e052610100525050600880546001600160a01b0319166001600160a01b0384169081179091556040519091506000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506101c08990526001600160a01b038a81166101805288811661012052878116610140528681166101a05285811661016052600b80546001600160a01b03191691861691909117905582516200029f90600f90602086019062000547565b508151620002b590600e90602085019062000547565b50600d819055601680546001600160801b031916602a179055620002dd896201518062000914565b601780546001600160401b03929092166801000000000000000002600160401b600160801b0319909216919091179055506200096b98505050505050505050565b60008082136200035d5760405162461bcd60e51b815260206004820152600960248201526815539111519253915160ba1b6044820152606401620001b3565b5060606001600160801b03821160071b82811c6001600160401b031060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110600190811b90911783811c90911017609f81810383019390931b90921c6c465772b2bbbb5f824b15207a3081018102821d6d0388eaa27412d5aca026815d636e018102821d6d0df99ac502031bf953eff472fdcc018102821d6d13cdffb29d51d99322bdff5f2211018102821d6d0a0f742023def783a307a986912e018102821d6d01920d8043ca89b5239253284e42018102821d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7882018202831d6d0139601a2efabe717e604cbb4894018202831d6d02247f7a7b6594320649aa03aba1018202831d6c8c3f38e95a6b1ff2ab1c3b343619018202831d6d02384773bdf1ac5676facced60901901820290921d6cb9a025d814b29c212b8b1a07cd19010260016c0504a838426634cdd8738f543560611b03190105711340daa0d5f769dba1915cef59f0815a550602605f19919091017d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b82805462000555906200092f565b90600052602060002090601f016020900481019282620005795760008555620005c4565b82601f106200059457805160ff1916838001178555620005c4565b82800160010185558215620005c4579182015b82811115620005c4578251825591602001919060010190620005a7565b50620005d2929150620005d6565b5090565b5b80821115620005d25760008155600101620005d7565b80516001600160a01b03811681146200060557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200063257600080fd5b81516001600160401b03808211156200064f576200064f6200060a565b604051601f8301601f19908116603f011681019082821181831017156200067a576200067a6200060a565b816040528381526020925086838588010111156200069757600080fd5b600091505b83821015620006bb57858201830151818301840152908201906200069c565b83821115620006cd5760008385830101525b9695505050505050565b6000806000806000806000806000806101408b8d031215620006f857600080fd5b620007038b620005ed565b995060208b015198506200071a60408c01620005ed565b97506200072a60608c01620005ed565b96506200073a60808c01620005ed565b95506200074a60a08c01620005ed565b94506200075a60c08c01620005ed565b60e08c01519094506001600160401b03808211156200077857600080fd5b620007868e838f0162000620565b94506101008d01519150808211156200079e57600080fd5b50620007ad8d828e0162000620565b9250506101208b015190509295989b9194979a5092959850565b634e487b7160e01b600052601160045260246000fd5b600082821015620007f257620007f2620007c7565b500390565b60008083128015600160ff1b850184121615620008185762000818620007c7565b6001600160ff1b0384018313811615620008365762000836620007c7565b50500390565b600080821280156001600160ff1b0384900385131615620008615762000861620007c7565b600160ff1b83900384128116156200087d576200087d620007c7565b50500190565b60006001600160ff1b0381841382841380821686840486111615620008ac57620008ac620007c7565b600160ff1b6000871282811687830589121615620008ce57620008ce620007c7565b60008712925087820587128484161615620008ed57620008ed620007c7565b87850587128184161615620009065762000906620007c7565b505050929093029392505050565b600082198211156200092a576200092a620007c7565b500190565b600181811c908216806200094457607f821691505b6020821081036200096557634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516101c051614cca62000a38600039600081816107ce015281816116410152612b59015260008181610d060152612638015260008181610e4d0152611849015260008181610bf001526116cf015260008181610dc401526128490152600081816106cf015281816124b801528181612954015261319b01526000612805015260006127dd015260006127ba015260006138aa01526000818161101e01526138830152614cca6000f3fe6080604052600436106104c05760003560e01c80636d891dda11610276578063c23d2bf61161014f578063e1da26c6116100c1578063f2fde38b11610085578063f2fde38b14611131578063f3c07b7e14611151578063f466d4ab14611171578063fe2c7fee14611191578063ff1b6556146111b1578063ffc9896b146111c757600080fd5b8063e1da26c614611060578063e73bf18714611075578063e8a51ea8146110af578063e985e9c5146110c9578063f23a6e611461110457600080fd5b8063d768a10711610113578063d768a10714610f97578063d7b5da1914610fb7578063da3ef23f14610fd7578063dbddb26a14610ff7578063dc38679c1461100c578063dcad0d281461104057600080fd5b8063c23d2bf614610f0c578063c86c2d3614610f21578063c87b56dd14610f41578063c911c1b414610f61578063ca8165a114610f7757600080fd5b80639158aa01116101e8578063a675f80e116101ac578063a675f80e14610e1b578063b10abe4414610e3b578063b1901a2414610e6f578063b589d14314610e84578063b88d4fde14610ea4578063bc197c8114610ec457600080fd5b80639158aa0114610d7d57806395d89b4114610d9d5780639883da6714610db2578063a0ab3aa614610de6578063a22cb46514610dfb57600080fd5b8063767cbac81161023a578063767cbac814610ca75780638462151c14610cc757806385f2aef214610cf45780638a4cfc4c14610d285780638b584eeb14610d3d5780638da5cb5b14610d5d57600080fd5b80636d891dda14610c125780636d9856e514610c275780636d9d33b714610c475780636fb3b96414610c6757806370a0823114610c8757600080fd5b80632a55205a116103a857806349773cc71161031a57806363c10040116102de57806363c1004014610b305780636613e79014610b6e57806367ad53ef14610b835780636ab6591514610ba95780636afb29fe14610bbe5780636cc25db714610bde57600080fd5b806349773cc714610a8b578063507862d114610abb57806355f804b314610ad05780636075475b14610af05780636352211e14610b1057600080fd5b806332cb6b0c1161036c57806332cb6b0c146109045780633f879faf1461091a57806342842e0e1461092f57806344481c0f1461094f57806345aeefde146109d857806348bda33a146109f857600080fd5b80632a55205a146108305780632dff84231461086f5780632f745c59146108ae5780632fd9c876146108ce57806331a53e9a146108ee57600080fd5b806313b45a4711610441578063208e28b111610405578063208e28b114610751578063210386e01461076457806323b872dd1461079c578063255e4685146107bc578063260cf66a146107f0578063291a66ed1461081057600080fd5b806313b45a471461069d57806313faef69146106bd5780631413ee87146106f1578063184c404d146107115780631ebdcaae1461073157600080fd5b8063095ea7b311610488578063095ea7b3146105ae5780630de8a7ca146105d057806311f93e781461061b5780631278650c1461065e57806312ba17061461067e57600080fd5b806301ffc9a7146104c5578063033b1cf0146104fa5780630697e1731461053257806306fdde0314610556578063081812fc14610578575b600080fd5b3480156104d157600080fd5b506104e56104e03660046142af565b611268565b60405190151581526020015b60405180910390f35b34801561050657600080fd5b50600c5461051a906001600160a01b031681565b6040516001600160a01b0390911681526020016104f1565b34801561053e57600080fd5b5061054860155481565b6040519081526020016104f1565b34801561056257600080fd5b5061056b6112c9565b6040516104f191906142fc565b34801561058457600080fd5b5061051a61059336600461432f565b6006602052600090815260409020546001600160a01b031681565b3480156105ba57600080fd5b506105ce6105c936600461435d565b611357565b005b3480156105dc57600080fd5b506016546105fb906001600160801b0380821691600160801b90041682565b604080516001600160801b039384168152929091166020830152016104f1565b34801561062757600080fd5b50610548610636366004614389565b6001600160a01b0316600090815260056020526040902054600160201b900463ffffffff1690565b34801561066a57600080fd5b506105ce6106793660046143b4565b61143e565b34801561068a57600080fd5b506013546104e590610100900460ff1681565b3480156106a957600080fd5b506105ce6106b83660046143e4565b6114a9565b3480156106c957600080fd5b5061051a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106fd57600080fd5b506105ce61070c366004614389565b611534565b34801561071d57600080fd5b50600b5461051a906001600160a01b031681565b34801561073d57600080fd5b506105ce61074c366004614406565b611588565b61054861075f366004614473565b6115ed565b34801561077057600080fd5b50601154610784906001600160801b031681565b6040516001600160801b0390911681526020016104f1565b3480156107a857600080fd5b506105ce6107b73660046144b4565b611a4e565b3480156107c857600080fd5b506105487f000000000000000000000000000000000000000000000000000000000000000081565b3480156107fc57600080fd5b506105ce61080b366004614389565b611d91565b34801561081c57600080fd5b5061054861082b366004614473565b611ddd565b34801561083c57600080fd5b5061085061084b3660046143e4565b6120f9565b604080516001600160a01b0390931683526020830191909152016104f1565b34801561087b57600080fd5b5060085461089690600160a01b90046001600160601b031681565b6040516001600160601b0390911681526020016104f1565b3480156108ba57600080fd5b506105486108c936600461435d565b6121a7565b3480156108da57600080fd5b506105486108e9366004614389565b612252565b3480156108fa57600080fd5b5061054861013881565b34801561091057600080fd5b5061054861119481565b34801561092657600080fd5b506105486122c6565b34801561093b57600080fd5b506105ce61094a3660046144b4565b6122f0565b34801561095b57600080fd5b506109a561096a36600461432f565b6004602052600090815260409020546001600160a01b03811690600160a01b81046001600160401b031690600160e01b900463ffffffff1683565b604080516001600160a01b0390941684526001600160401b03909216602084015263ffffffff16908201526060016104f1565b3480156109e457600080fd5b506105ce6109f3366004614389565b6123e8565b348015610a0457600080fd5b50601754610a49906001600160401b0380821691600160401b8104821691600160801b82041690600160c01b810466ffffffffffffff1690600160f81b900460ff1685565b604080516001600160401b0396871681529486166020860152929094169183019190915266ffffffffffffff166060820152901515608082015260a0016104f1565b348015610a9757600080fd5b506104e5610aa636600461432f565b60126020526000908152604090205460ff1681565b348015610ac757600080fd5b5061056b61244d565b348015610adc57600080fd5b506105ce610aeb366004614536565b61245a565b348015610afc57600080fd5b506105ce610b0b36600461432f565b612490565b348015610b1c57600080fd5b5061051a610b2b36600461432f565b61251f565b348015610b3c57600080fd5b50610548610b4b36600461456b565b601860209081526000938452604080852082529284528284209052825290205481565b348015610b7a57600080fd5b50610548612559565b348015610b8f57600080fd5b5060135461051a906201000090046001600160a01b031681565b348015610bb557600080fd5b50610548600c81565b348015610bca57600080fd5b50610548610bd936600461432f565b6125fe565b348015610bea57600080fd5b5061051a7f000000000000000000000000000000000000000000000000000000000000000081565b348015610c1e57600080fd5b50610548602a81565b348015610c3357600080fd5b506105ce610c42366004614389565b6126c6565b348015610c5357600080fd5b50610548610c6236600461432f565b6127a7565b348015610c7357600080fd5b506105ce610c8236600461435d565b61283e565b348015610c9357600080fd5b50610548610ca2366004614389565b612899565b348015610cb357600080fd5b50610548610cc23660046143b4565b612902565b348015610cd357600080fd5b50610ce7610ce2366004614389565b612a56565b6040516104f19190614592565b348015610d0057600080fd5b5061051a7f000000000000000000000000000000000000000000000000000000000000000081565b348015610d3457600080fd5b50610548612b51565b348015610d4957600080fd5b5060095461051a906001600160a01b031681565b348015610d6957600080fd5b5060085461051a906001600160a01b031681565b348015610d8957600080fd5b506105ce610d983660046145d6565b612baa565b348015610da957600080fd5b5061056b612be7565b348015610dbe57600080fd5b5061051a7f000000000000000000000000000000000000000000000000000000000000000081565b348015610df257600080fd5b50610548612bf4565b348015610e0757600080fd5b506105ce610e163660046145f3565b612c0c565b348015610e2757600080fd5b506105ce610e36366004614621565b612c78565b348015610e4757600080fd5b5061051a7f000000000000000000000000000000000000000000000000000000000000000081565b348015610e7b57600080fd5b5061056b612e3d565b348015610e9057600080fd5b50600a5461051a906001600160a01b031681565b348015610eb057600080fd5b506105ce610ebf36600461466b565b612e4a565b348015610ed057600080fd5b50610ef3610edf3660046146dd565b63bc197c8160e01b98975050505050505050565b6040516001600160e01b031990911681526020016104f1565b348015610f1857600080fd5b50610548612f2b565b348015610f2d57600080fd5b506105ce610f3c366004614389565b612f68565b348015610f4d57600080fd5b5061056b610f5c36600461432f565b612fb4565b348015610f6d57600080fd5b5061054861089e81565b348015610f8357600080fd5b50601454610784906001600160801b031681565b348015610fa357600080fd5b506105ce610fb236600461432f565b61317f565b348015610fc357600080fd5b506105ce610fd236600461432f565b61320b565b348015610fe357600080fd5b506105ce610ff23660046147b1565b61327d565b34801561100357600080fd5b5061056b6132ba565b34801561101857600080fd5b506105487f000000000000000000000000000000000000000000000000000000000000000081565b34801561104c57600080fd5b506105ce61105b3660046145d6565b6132c7565b34801561106c57600080fd5b5061054861330b565b34801561108157600080fd5b5061054861109036600461432f565b600090815260046020526040902054600160e01b900463ffffffff1690565b3480156110bb57600080fd5b506013546104e59060ff1681565b3480156110d557600080fd5b506104e56110e4366004614861565b600760209081526000928352604080842090915290825290205460ff1681565b34801561111057600080fd5b50610ef361111f36600461488f565b63f23a6e6160e01b9695505050505050565b34801561113d57600080fd5b506105ce61114c366004614389565b6134e0565b34801561115d57600080fd5b506105ce61116c36600461432f565b613556565b34801561117d57600080fd5b5061054861118c3660046143e4565b61387c565b34801561119d57600080fd5b506105ce6111ac366004614536565b613901565b3480156111bd57600080fd5b50610548600d5481565b3480156111d357600080fd5b506112296111e2366004614389565b60056020526000908152604090205463ffffffff80821691600160201b810490911690600160401b81046001600160801b031690600160c01b90046001600160401b031684565b6040805163ffffffff95861681529490931660208501526001600160801b03909116918301919091526001600160401b031660608201526080016104f1565b60006301ffc9a760e01b6001600160e01b03198316148061129957506380ac58cd60e01b6001600160e01b03198316145b806112b45750635b5e139f60e01b6001600160e01b03198316145b806112c357506112c382613937565b92915050565b600280546112d69061490a565b80601f01602080910402602001604051908101604052809291908181526020018280546113029061490a565b801561134f5780601f106113245761010080835404028352916020019161134f565b820191906000526020600020905b81548152906001019060200180831161133257829003601f168201915b505050505081565b6000818152600460205260409020546001600160a01b0316338114806113a057506001600160a01b038116600090815260076020908152604080832033845290915290205460ff165b6113e25760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064015b60405180910390fd5b60008281526006602052604080822080546001600160a01b0319166001600160a01b0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b600c546001600160a01b031633146114895760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b60448201526064016113d9565b600091825260126020526040909120805460ff1916911515919091179055565b600b546001600160a01b031633146114d4576040516369b82b9960e01b815260040160405180910390fd5b6017805468010000000000000000600160f81b03166001600160401b0383161790556040517f0678731ae5818cd1d7fea152b34c7ce35819233a9559e8b988bc2b7d7d216a4f906115289083815260200190565b60405180910390a15050565b6008546001600160a01b0316331461155e5760405162461bcd60e51b81526004016113d990614944565b601380546001600160a01b03909216620100000262010000600160b01b0319909216919091179055565b6008546001600160a01b031633146115b25760405162461bcd60e51b81526004016113d990614944565b600880546001600160601b03808416600160a01b9081026001600160a01b0393841617938490556009546115ea94931692041661396c565b50565b600032331461163e5760405162461bcd60e51b815260206004820152601e60248201527f5468652063616c6c657220697320616e6f7468657220636f6e7472616374000060448201526064016113d9565b427f0000000000000000000000000000000000000000000000000000000000000000111561167f5760405163dc0847d160e01b815260040160405180910390fd5b816116ba5760405162461bcd60e51b815260206004820152600b60248201526a656d70747920617272617960a81b60448201526064016113d9565b346000036117f35760005b828110156117ed577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd33308787868181106117105761171061496a565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b15801561176757600080fd5b505af115801561177b573d6000803e3d6000fd5b5050601480546001600160801b03808216600101166001600160801b031990911681179091556040519094508492503391507f6c4e200da7fa361550c9d2ad4f247f2b09e6bb5b1326cd213883a8488096538b90600090a36117dd3383613a69565b6117e681614996565b90506116c5565b506112c3565b61180582670de0b6b3a76400006149af565b3410611a06576008546040516001600160a01b03909116903480156108fc02916000818181858888f1935050505061183c57600080fd5b60005b828110156117ed577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166323b872dd333087878681811061188a5761188a61496a565b6040516001600160e01b031960e088901b1681526001600160a01b03958616600482015294909316602485015250602090910201356044820152606401600060405180830381600087803b1580156118e157600080fd5b505af11580156118f5573d6000803e3d6000fd5b5050600a546001600160a01b031691506340c10f1990503386868581811061191f5761191f61496a565b6040516001600160e01b031960e087901b1681526001600160a01b03909416600485015260200291909101356024830152506044016020604051808303816000875af1158015611973573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061199791906149ce565b50601480546001600160801b03808216600101166001600160801b03199091168117909155604051909250829033907f6c4e200da7fa361550c9d2ad4f247f2b09e6bb5b1326cd213883a8488096538b90600090a36119f63383613a69565b6119ff81614996565b905061183f565b60405162461bcd60e51b815260206004820152601760248201527f6d696e7420636f6e646974696f6e206d69736d6174636800000000000000000060448201526064016113d9565b60135460ff161515600103611aae5760008181526012602052604090205460ff1615611aae5760405162461bcd60e51b815260206004820152600f60248201526e151bdad95b881a5cc81cdd185ad959608a1b60448201526064016113d9565b6000818152600460205260409020546001600160a01b03848116911614611b045760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016113d9565b6001600160a01b038216611b4e5760405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b60448201526064016113d9565b336001600160a01b0384161480611b8857506001600160a01b038316600090815260076020908152604080832033845290915290205460ff165b80611ba957506000818152600660205260409020546001600160a01b031633145b611be65760405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b60448201526064016113d9565b600081815260066020908152604080832080546001600160a01b0319908116909155600490925290912080549091166001600160a01b0384161790819055600160e01b900463ffffffff16611c3a84612252565b6001600160a01b0385166000908152600560205260409020805460001963ffffffff600160201b6001600160401b03428116600160c01b026001600160c01b036001600160801b0398909816600160401b02979097169416939093179490941782810485168690038516909202808516858416179190910190931663ffffffff1990931667ffffffffffffffff1990911617919091179055611cdb83612252565b6001600160a01b03808516600081815260056020526040808220805463ffffffff600160201b6001600160401b03428116600160c01b026001600160c01b036001600160801b039b909b16600160401b029a909a169316929092179790971781810488169098018716028087168789161760010190961663ffffffff1990961667ffffffffffffffff1990971696909617949094179094559151849391871691600080516020614c7583398151915291a4505050565b6008546001600160a01b03163314611dbb5760405162461bcd60e51b81526004016113d990614944565b600c80546001600160a01b0319166001600160a01b0392909216919091179055565b601354600090610100900460ff161515600103611e45576013546201000090046001600160a01b03163314611e455760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b60448201526064016113d9565b601654600160801b90046001600160801b031680611e66600c6111946149eb565b611e71906001614a02565b611e7b9190614a02565b91506000611e87612559565b905080841015611ead5760405163e7fb19eb60e01b8152600481018290526024016113d9565b60008060005b83811015611fac57878782818110611ecd57611ecd61496a565b60200291909101359250506111898210611efd5760405163400316c160e01b8152600481018390526024016113d9565b600082815260046020526040902080546001600160a01b03163314611f515760405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b60448201526064016113d9565b805460008481526006602052604080822080546001600160a01b0319908116909155845416845551600160e01b90920463ffffffff16959095019484913390600080516020614c75833981519152908390a450600101611eb3565b50600085815260046020526040902080546001600160e01b0316600160e01b6002850263ffffffff1602179055611fe233612252565b336000908152600560205260409020805463ffffffff600160201b6001600160401b03428116600160c01b026001600160c01b036001600160801b0397909716600160401b0296909616931692909217939093178181048416860184169091028084168483161787900390931663ffffffff1990931667ffffffffffffffff19909116179190911790556002602a048311156120815782600202612084565b602a5b600185016001600160801b03908116600160801b0291161760165584337f598c505f54f09219ac935c0b6da96a00ad232ceb248894c73a4ffceaf9cf6d046120cf8660008b8d614a30565b6040516120dd929190614a5e565b60405180910390a36120ef3386613a69565b5050505092915050565b60008281526001602090815260408083208151808301909252546001600160a01b038116808352600160a01b9091046001600160601b031692820192909252829161216e5750604080518082019091526000546001600160a01b0381168252600160a01b90046001600160601b031660208201525b60208101516000906127109061218d906001600160601b0316876149af565b6121979190614a9a565b91519350909150505b9250929050565b6001600160a01b03821660009081526005602052604081205463ffffffff1682106122285760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b60648201526084016113d9565b61223183612a56565b82815181106122425761224261496a565b6020026020010151905092915050565b6001600160a01b0381166000908152600560205260408120546112c390600160201b810463ffffffff1690600160401b81046001600160801b0316906122c1906122ac90600160c01b90046001600160401b0316426149eb565b62015180670de0b6b3a7640000919091020490565b613ad5565b610138600c6122d961089e6111946149eb565b6122e391906149eb565b6122ed91906149eb565b81565b6122fb838383611a4e565b6001600160a01b0382163b15806123a45750604051630a85bd0160e11b8082523360048301526001600160a01b03858116602484015260448301849052608060648401526000608484015290919084169063150b7a029060a4016020604051808303816000875af1158015612374573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123989190614abc565b6001600160e01b031916145b6123e35760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016113d9565b505050565b6008546001600160a01b031633146124125760405162461bcd60e51b81526004016113d990614944565b600980546001600160a01b0319166001600160a01b0383169081179091556008546115ea9190600160a01b90046001600160601b031661396c565b600e80546112d69061490a565b6008546001600160a01b031633146124845760405162461bcd60e51b81526004016113d990614944565b6123e3600f838361418c565b61249c33826001613b15565b604051631cee961560e31b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063e774b0a890604401600060405180830381600087803b15801561250457600080fd5b505af1158015612518573d6000803e3d6000fd5b5050505050565b6000818152600460205260409020546001600160a01b0316806125545760405162461bcd60e51b81526004016113d990614ad9565b919050565b6016546000906001600160801b0380821691600160801b900416600b19810161259557604051635985323f60e11b815260040160405180910390fd5b6011546001600160801b031660018201609702818111156125cd5760405163276ce00d60e21b815282820360048201526024016113d9565b808203609781106125e45760009550505050505090565b609781810386028181049190061515019550505050505090565b6015805482019081905560009061013881111561262e57604051631852d2df60e01b815260040160405180910390fd5b50601454612668907f00000000000000000000000000000000000000000000000000000000000000009084906001600160801b0316613bde565b601480546001600160801b0319166001600160801b038316179055604080518281526020810185905291925033917f4bb18b43439830ce70e710e800aaea6bb5becc2a28d6cec8674792cfb5296818910160405180910390a2919050565b6008546001600160a01b031633146126f05760405162461bcd60e51b81526004016113d990614944565b601754600160f81b900460ff161561275b57601780546001600160c01b0316808255620151809190600890612736908490600160401b90046001600160401b0316614afd565b92506101000a8154816001600160401b0302191690836001600160401b031602179055505b600b80546001600160a01b0319166001600160a01b03831690811790915560405133907fb935ae081db04fbe2c80c7b2d69b4b8396f38acee91ddeb9f5edfe89044bf2ab90600090a350565b6000612835612803670de0b6b3a76400007f000000000000000000000000000000000000000000000000000000000000000085017f00000000000000000000000000000000000000000000000000000000000000000503613c76565b7f0000000000000000000000000000000000000000000000000000000000000000670de0b6b3a7640000919091020590565b60000392915050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146128895760405163d86ad9cf60e01b81523360048201526024016113d9565b61289582826001613b15565b5050565b60006001600160a01b0382166128e05760405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b60448201526064016113d9565b506001600160a01b031660009081526005602052604090205463ffffffff1690565b60008061290d612b51565b90508381111561293357604051630403a3a160e21b8152600481018290526024016113d9565b826129bd57604051630bac621f60e21b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632eb1887c90604401600060405180830381600087803b1580156129a057600080fd5b505af11580156129b4573d6000803e3d6000fd5b505050506129c9565b6129c933826001613b15565b601180546001600160801b03808216600190810182166001600160801b031993841617909355601480548083169094019091169290911682179055604051909250829033907f99e1b4d0696d139b91daf3afeec99fc64df2d933be4a006aa4729bb34fae28a090612a3d9085815260200190565b60405180910390a3612a4f3383613a69565b5092915050565b6001600160a01b038116600090815260056020526040812054606091908190819063ffffffff1681816001600160401b03811115612a9657612a9661479b565b604051908082528060200260200182016040528015612abf578160200160208202803683370190505b50905060015b828614612b46576000818152600460205260409020546001600160a01b031693508315612b3e576001600160a01b03841615612aff578394505b876001600160a01b0316856001600160a01b031603612b3e5780828780600101985081518110612b3157612b3161496a565b6020026020010181815250505b600101612ac5565b509695505050505050565b600080612b7e7f0000000000000000000000000000000000000000000000000000000000000000426149eb565b9050612ba462015180670de0b6b3a76400008302046011546001600160801b031661387c565b91505090565b6008546001600160a01b03163314612bd45760405162461bcd60e51b81526004016113d990614944565b6013805460ff1916911515919091179055565b600380546112d69061490a565b612c01600c6111946149eb565b6122ed906001614a02565b3360008181526007602090815260408083206001600160a01b03871680855290835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b6000848152600460205260409020546001600160a01b0316338114612cbb5760405163387341cf60e11b81526001600160a01b03821660048201526024016113d9565b306001600160a01b03851603612ce45760405163f92dd0b560e01b815260040160405180910390fd5b60008581526018602090815260408083206001600160a01b0388168085529083528184208785528352928190208054600101905551858152879133917f8dac06e2c3d1d1c0739de11e4ec409d0f1543ccf7c00a536aeab4f97ed52eaaa910160405180910390a481612dbb576040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b038516906323b872dd90606401600060405180830381600087803b158015612d9e57600080fd5b505af1158015612db2573d6000803e3d6000fd5b50505050612518565b604051637921219560e11b8152336004820152306024820152604481018490526001606482015260a06084820152600060a48201526001600160a01b0385169063f242432a9060c401600060405180830381600087803b158015612e1e57600080fd5b505af1158015612e32573d6000803e3d6000fd5b505050505050505050565b601080546112d69061490a565b612e55858585611a4e565b6001600160a01b0384163b1580612eec5750604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290612e9d9033908a90899089908990600401614b25565b6020604051808303816000875af1158015612ebc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ee09190614abc565b6001600160e01b031916145b6125185760405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b60448201526064016113d9565b612f37600c6001614a02565b610138600c612f4a61089e6111946149eb565b612f5491906149eb565b612f5e91906149eb565b6122ed9190614a9a565b6008546001600160a01b03163314612f925760405162461bcd60e51b81526004016113d990614944565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b601754606090600160801b90046001600160401b031682116130455781600003612ff05760405162461bcd60e51b81526004016113d990614ad9565b600082815260046020526040902054600f9061301b90600160a01b90046001600160401b0316613ea3565b601060405160200161302f93929190614c12565b6040516020818303038152906040529050919050565b6014546001600160801b031682116130e957600e80546130649061490a565b80601f01602080910402602001604051908101604052809291908181526020018280546130909061490a565b80156130dd5780601f106130b2576101008083540402835291602001916130dd565b820191906000526020600020905b8154815290600101906020018083116130c057829003601f168201915b50505050509050919050565b6130f6600c6111946149eb565b613101906001614a02565b8210156131205760405162461bcd60e51b81526004016113d990614ad9565b601654600160801b90046001600160801b0316613140600c6111946149eb565b61314b906001614a02565b6131559190614a02565b82101561316757600f61301b83613ea3565b60405162461bcd60e51b81526004016113d990614ad9565b604051630bac621f60e21b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632eb1887c90604401600060405180830381600087803b1580156131e757600080fd5b505af11580156131fb573d6000803e3d6000fd5b505050506115ea33826000613b15565b6008546001600160a01b031633146132355760405162461bcd60e51b81526004016113d990614944565b600d805490829055604080518281526020810184905233918101919091527fc8cc7a0d8d99c409787f00f618a77263d69418ebe424b4f784726862034dd07e90606001611528565b6008546001600160a01b031633146132a75760405162461bcd60e51b81526004016113d990614944565b8051612895906010906020840190614210565b600f80546112d69061490a565b6008546001600160a01b031633146132f15760405162461bcd60e51b81526004016113d990614944565b601380549115156101000261ff0019909216919091179055565b601754600090600160401b90046001600160401b031642811115613342576040516318021ced60e21b815260040160405180910390fd5b601754600160c01b900466ffffffffffffff16156133735760405163639dbd7360e01b815260040160405180910390fd5b60178054600160f81b6001600160f81b039091161790819055601454600160801b9091046001600160401b03166001600160801b03918216031660008190036133cf57604051633264c00360e11b815260040160405180910390fd5b601780547fff00000000000000ffffffffffffffff0000000000000000ffffffffffffffff16600160c01b66ffffffffffffff8416026fffffffffffffffff0000000000000000191617600160401b6201518085016001600160401b03160217905560405181815233907fc0412d082261082b733ae39d66dd3b4c4d14c47283f37f52dc3a3bb8a70efabe9060200160405180910390a250600b60009054906101000a90046001600160a01b03166001600160a01b03166395733bab6040518163ffffffff1660e01b81526004016020604051808303816000875af11580156134bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba49190614c45565b6008546001600160a01b0316331461350a5760405162461bcd60e51b81526004016113d990614944565b600880546001600160a01b0319166001600160a01b03831690811790915560405133907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6017546001600160401b0380821691600160801b810490911690600160c01b810466ffffffffffffff1690600160f81b900460ff16156135a95760405163aacbcaa560e01b815260040160405180910390fd5b808411156135cd5760405163e6bdccb560e01b8152600481018290526024016113d9565b60005b848110156137da576000196111898490030160008186816135f3576135f3614a1a565b0685810160019081016000818152600460205260408120549290980197929350879290916001600160401b03600160a01b909104161561365157600082815260046020526040902054600160a01b90046001600160401b0316613653565b815b6000848152600460205260408120549192506001600160a01b03821691600160a01b90046001600160401b0316156136a957600085815260046020526040902054600160a01b90046001600160401b03166136ab565b845b60008681526004602052604080822080546001600160a01b0316600160a01b6001600160401b03808a1682026001600160e01b031692909217600160e01b61055e8b106109f88c10610e008d10010160090363ffffffff8116919091029190911790935589855292909320805467ffffffffffffffff60a01b191693851690920292909217905590915061373e83612252565b6001600160a01b0390931660009081526005602090815260408220805463ffffffff600160201b6001600160401b03428116600160c01b026001600160c01b036001600160801b039b909b16600160401b029a909a16938116939093179890981788810482169096011690960267ffffffff0000000019909416939093179092559b8c52909a20169850505060019390930192506135d0915050565b50601780546001600160401b0385811677ffffffffffffffff0000000000000000ffffffffffffffff1990921691909117600160801b918516919091021766ffffffffffffff60c01b1916600160c01b86840366ffffffffffffff1602179055604080518581526020810184905233917ff8b7de4b0eeddb184583c6d243438d17f72f084fa8200ed2694aafa3cd90d7a991015b60405180910390a250505050565b60006138fa7f00000000000000000000000000000000000000000000000000000000000000006138f56138f07f00000000000000000000000000000000000000000000000000000000000000006138df670de0b6b3a764000060018901026127a7565b8803670de0b6b3a764000091020590565b613ee7565b614090565b9392505050565b6008546001600160a01b0316331461392b5760405162461bcd60e51b81526004016113d990614944565b6123e3600e838361418c565b60006001600160e01b0319821663152a902d60e11b14806112c357506301ffc9a760e01b6001600160e01b03198316146112c3565b6127106001600160601b03821611156139da5760405162461bcd60e51b815260206004820152602a60248201527f455243323938313a20726f79616c7479206665652077696c6c206578636565646044820152692073616c65507269636560b01b60648201526084016113d9565b6001600160a01b038216613a305760405162461bcd60e51b815260206004820152601960248201527f455243323938313a20696e76616c69642072656365697665720000000000000060448201526064016113d9565b604080518082019091526001600160a01b039092168083526001600160601b039091166020909201829052600160a01b90910217600055565b6001600160a01b0382166000818152600560209081526040808320805463ffffffff8082166001011663ffffffff19909116179055848352600490915280822080546001600160a01b031916841790555183929190600080516020614c75833981519152908290a45050565b600080613ae283806140b5565b9050613b03613afc858702670de0b6b3a7640000026140ca565b84906140b5565b90850260021c84010190509392505050565b600080826001811115613b2a57613b2a614c5e565b14613b485782613b3985612252565b613b4391906149eb565b613b5c565b82613b5285612252565b613b5c9190614a02565b6001600160a01b0385166000818152600560205260409081902080546001600160401b03428116600160c01b026001600160c01b036001600160801b038816600160401b0216919092161717905551919250907fcd957807d7c0a61194f68abf2c33dcc1bed9690439e158cae2f6543c67575c1a9061386e9084815260200190565b6001600160a01b0383166000908152600560205260408120805463ffffffff80821686011663ffffffff19909116179055805b83811015613c6d57600190920160008181526004602052604080822080546001600160a01b0389166001600160a01b031990911681179091559051929492859290600080516020614c75833981519152908290a4600101613c11565b50909392505050565b6000808213613cb35760405162461bcd60e51b815260206004820152600960248201526815539111519253915160ba1b60448201526064016113d9565b5060606001600160801b03821160071b82811c6001600160401b031060061b1782811c63ffffffff1060051b1782811c61ffff1060041b1782811c60ff10600390811b90911783811c600f1060021b1783811c909110600190811b90911783811c90911017609f81810383019390931b90921c6c465772b2bbbb5f824b15207a3081018102821d6d0388eaa27412d5aca026815d636e018102821d6d0df99ac502031bf953eff472fdcc018102821d6d13cdffb29d51d99322bdff5f2211018102821d6d0a0f742023def783a307a986912e018102821d6d01920d8043ca89b5239253284e42018102821d6c0b7a86d7375468fac667a0a527016c29508e458543d8aa4df2abee7882018202831d6d0139601a2efabe717e604cbb4894018202831d6d02247f7a7b6594320649aa03aba1018202831d6c8c3f38e95a6b1ff2ab1c3b343619018202831d6d02384773bdf1ac5676facced60901901820290921d6cb9a025d814b29c212b8b1a07cd190102780a09507084cc699bb0e71ea869ffffffffffffffffffffffff190105711340daa0d5f769dba1915cef59f0815a550602605f19919091017d0267a36c0c95b3975ab3ee5b203a7614a3f75373f047d803ae7b6687f2b302017d57115e47018c7177eebf7cd370a3356a1b7863008a5ae8028c72b88642840160ae1d90565b606060a06040510180604052602081039150506000815280825b600183039250600a81066030018353600a900480613ebd5750819003601f19909101908152919050565b6000680248ce36a70cb26b3e198213613f0257506000919050565b680755bf798b4a1bf1e58212613f495760405162461bcd60e51b815260206004820152600c60248201526b4558505f4f564552464c4f5760a01b60448201526064016113d9565b6503782dace9d9604e83901b059150600060606bb17217f7d1cf79abc9e3b39884821b056001605f1b01901d6bb17217f7d1cf79abc9e3b39881029093036c240c330e9fb2d9cbaf0fd5aafb1981018102606090811d6d0277594991cfc85f6e2461837cd9018202811d6d1a521255e34f6a5061b25ef1c9c319018202811d6db1bbb201f443cf962f1a1d3db4a5018202811d6e02c72388d9f74f51a9331fed693f1419018202811d6e05180bb14799ab47a8a8cb2a527d57016d02d16720577bd19bf614176fe9ea6c10fe68e7fd37d0007b713f765084018402831d9081019084016d01d3967ed30fc4f89c02bab5708119010290911d6e0587f503bb6ea29d25fcb740196450019091026d360d7aeea093263ecc6e0ecb291760621b010574029d9dc38563c32e5c2f6dc192ee70ef65f9978af30260c3939093039290921c92915050565b81810282158382058314176140a457600080fd5b670de0b6b3a7640000900592915050565b60006138fa8383670de0b6b3a764000061416e565b60b581600160881b81106140e35760409190911b9060801c5b690100000000000000000081106140ff5760209190911b9060401c5b6501000000000081106141175760109190911b9060201c5b6301000000811061412d5760089190911b9060101c5b62010000010260121c80820401600190811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b600082600019048411830215820261418557600080fd5b5091020490565b8280546141989061490a565b90600052602060002090601f0160209004810192826141ba5760008555614200565b82601f106141d35782800160ff19823516178555614200565b82800160010185558215614200579182015b828111156142005782358255916020019190600101906141e5565b5061420c929150614284565b5090565b82805461421c9061490a565b90600052602060002090601f01602090048101928261423e5760008555614200565b82601f1061425757805160ff1916838001178555614200565b82800160010185558215614200579182015b82811115614200578251825591602001919060010190614269565b5b8082111561420c5760008155600101614285565b6001600160e01b0319811681146115ea57600080fd5b6000602082840312156142c157600080fd5b81356138fa81614299565b60005b838110156142e75781810151838201526020016142cf565b838111156142f6576000848401525b50505050565b602081526000825180602084015261431b8160408501602087016142cc565b601f01601f19169190910160400192915050565b60006020828403121561434157600080fd5b5035919050565b6001600160a01b03811681146115ea57600080fd5b6000806040838503121561437057600080fd5b823561437b81614348565b946020939093013593505050565b60006020828403121561439b57600080fd5b81356138fa81614348565b80151581146115ea57600080fd5b600080604083850312156143c757600080fd5b8235915060208301356143d9816143a6565b809150509250929050565b600080604083850312156143f757600080fd5b50508035926020909101359150565b60006020828403121561441857600080fd5b81356001600160601b03811681146138fa57600080fd5b60008083601f84011261444157600080fd5b5081356001600160401b0381111561445857600080fd5b6020830191508360208260051b85010111156121a057600080fd5b6000806020838503121561448657600080fd5b82356001600160401b0381111561449c57600080fd5b6144a88582860161442f565b90969095509350505050565b6000806000606084860312156144c957600080fd5b83356144d481614348565b925060208401356144e481614348565b929592945050506040919091013590565b60008083601f84011261450757600080fd5b5081356001600160401b0381111561451e57600080fd5b6020830191508360208285010111156121a057600080fd5b6000806020838503121561454957600080fd5b82356001600160401b0381111561455f57600080fd5b6144a8858286016144f5565b60008060006060848603121561458057600080fd5b8335925060208401356144e481614348565b6020808252825182820181905260009190848201906040850190845b818110156145ca578351835292840192918401916001016145ae565b50909695505050505050565b6000602082840312156145e857600080fd5b81356138fa816143a6565b6000806040838503121561460657600080fd5b823561461181614348565b915060208301356143d9816143a6565b6000806000806080858703121561463757600080fd5b84359350602085013561464981614348565b9250604085013591506060850135614660816143a6565b939692955090935050565b60008060008060006080868803121561468357600080fd5b853561468e81614348565b9450602086013561469e81614348565b93506040860135925060608601356001600160401b038111156146c057600080fd5b6146cc888289016144f5565b969995985093965092949392505050565b60008060008060008060008060a0898b0312156146f957600080fd5b883561470481614348565b9750602089013561471481614348565b965060408901356001600160401b038082111561473057600080fd5b61473c8c838d0161442f565b909850965060608b013591508082111561475557600080fd5b6147618c838d0161442f565b909650945060808b013591508082111561477a57600080fd5b506147878b828c016144f5565b999c989b5096995094979396929594505050565b634e487b7160e01b600052604160045260246000fd5b6000602082840312156147c357600080fd5b81356001600160401b03808211156147da57600080fd5b818401915084601f8301126147ee57600080fd5b8135818111156148005761480061479b565b604051601f8201601f19908116603f011681019083821181831017156148285761482861479b565b8160405282815287602084870101111561484157600080fd5b826020860160208301376000928101602001929092525095945050505050565b6000806040838503121561487457600080fd5b823561487f81614348565b915060208301356143d981614348565b60008060008060008060a087890312156148a857600080fd5b86356148b381614348565b955060208701356148c381614348565b9450604087013593506060870135925060808701356001600160401b038111156148ec57600080fd5b6148f889828a016144f5565b979a9699509497509295939492505050565b600181811c9082168061491e57607f821691505b60208210810361493e57634e487b7160e01b600052602260045260246000fd5b50919050565b6020808252600c908201526b15539055551213d49256915160a21b604082015260600190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016149a8576149a8614980565b5060010190565b60008160001904831182151516156149c9576149c9614980565b500290565b6000602082840312156149e057600080fd5b81516138fa816143a6565b6000828210156149fd576149fd614980565b500390565b60008219821115614a1557614a15614980565b500190565b634e487b7160e01b600052601260045260246000fd5b60008085851115614a4057600080fd5b83861115614a4d57600080fd5b5050600583901b0193919092039150565b6020808252810182905260006001600160fb1b03831115614a7e57600080fd5b8260051b80856040850137600092016040019182525092915050565b600082614ab757634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215614ace57600080fd5b81516138fa81614299565b6020808252600a90820152691393d517d3525395115160b21b604082015260600190565b60006001600160401b0383811690831681811015614b1d57614b1d614980565b039392505050565b6001600160a01b038681168252851660208201526040810184905260806060820181905281018290526000828460a0840137600060a0848401015260a0601f19601f85011683010190509695505050505050565b8054600090600181811c9080831680614b9357607f831692505b60208084108203614bb457634e487b7160e01b600052602260045260246000fd5b818015614bc85760018114614bd957614c06565b60ff19861689528489019650614c06565b60008881526020902060005b86811015614bfe5781548b820152908501908301614be5565b505084890196505b50505050505092915050565b6000614c1e8286614b79565b8451614c2e8183602089016142cc565b614c3a81830186614b79565b979650505050505050565b600060208284031215614c5757600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220dfb77884f04ab4b54aa75d0b8841a6a2262002bf8b278f80f8c93fad3e44143a64736f6c634300080d00330000000000000000000000007b7a932c61755dd87e1ffc2e7a8828673831573c0000000000000000000000000000000000000000000000000000000063c977100000000000000000000000007d57f563db93f257bd556d86e6fee7079c80226e000000000000000000000000311e1a6c9190fa6847dc6b4617ae36c1277fb24b000000000000000000000000f32f79df40dc792d4e09ffe82b9f35e74e730bef000000000000000000000000d20918515d498b25f57674d20ef5fc278dc1516e000000000000000000000000e84d6d832742f6be889dc096bd3f92d43c74998600000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000180628f3ac523165f5cf33334938a6211f0065ce6dc20a095d5274c34df8504d6e4000000000000000000000000000000000000000000000000000000000000001b68747470733a2f2f6d656368617661782e636f6d2f6d656368732f0000000000000000000000000000000000000000000000000000000000000000000000002568747470733a2f2f6d656368617661782e636f6d2f6d656368732f756e72657665616c6564000000000000000000000000000000000000000000000000000000

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000007b7a932c61755dd87e1ffc2e7a8828673831573c0000000000000000000000000000000000000000000000000000000063c977100000000000000000000000007d57f563db93f257bd556d86e6fee7079c80226e000000000000000000000000311e1a6c9190fa6847dc6b4617ae36c1277fb24b000000000000000000000000f32f79df40dc792d4e09ffe82b9f35e74e730bef000000000000000000000000d20918515d498b25f57674d20ef5fc278dc1516e000000000000000000000000e84d6d832742f6be889dc096bd3f92d43c74998600000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000180628f3ac523165f5cf33334938a6211f0065ce6dc20a095d5274c34df8504d6e4000000000000000000000000000000000000000000000000000000000000001b68747470733a2f2f6d656368617661782e636f6d2f6d656368732f0000000000000000000000000000000000000000000000000000000000000000000000002568747470733a2f2f6d656368617661782e636f6d2f6d656368732f756e72657665616c6564000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _ep (address): 0x7b7a932c61755dd87e1ffc2e7a8828673831573c
Arg [1] : _mintStart (uint256): 1674147600
Arg [2] : _shirak (address): 0x7d57f563db93f257bd556d86e6fee7079c80226e
Arg [3] : _arms (address): 0x311e1a6c9190fa6847dc6b4617ae36c1277fb24b
Arg [4] : _team (address): 0xf32f79df40dc792d4e09ffe82b9f35e74e730bef
Arg [5] : _ticket (address): 0xd20918515d498b25f57674d20ef5fc278dc1516e
Arg [6] : _randProvider (address): 0xe84d6d832742f6be889dc096bd3f92d43c749986
Arg [7] : _baseUri (string): https://mechavax.com/mechs/
Arg [8] : _unrevealedUri (string): https://mechavax.com/mechs/unrevealed
Arg [9] : _provenanceHash (bytes32): 0x628f3ac523165f5cf33334938a6211f0065ce6dc20a095d5274c34df8504d6e4

-----Encoded View---------------
15 Constructor Arguments found :
Arg [0] : 0000000000000000000000007b7a932c61755dd87e1ffc2e7a8828673831573c
Arg [1] : 0000000000000000000000000000000000000000000000000000000063c97710
Arg [2] : 0000000000000000000000007d57f563db93f257bd556d86e6fee7079c80226e
Arg [3] : 000000000000000000000000311e1a6c9190fa6847dc6b4617ae36c1277fb24b
Arg [4] : 000000000000000000000000f32f79df40dc792d4e09ffe82b9f35e74e730bef
Arg [5] : 000000000000000000000000d20918515d498b25f57674d20ef5fc278dc1516e
Arg [6] : 000000000000000000000000e84d6d832742f6be889dc096bd3f92d43c749986
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [9] : 628f3ac523165f5cf33334938a6211f0065ce6dc20a095d5274c34df8504d6e4
Arg [10] : 000000000000000000000000000000000000000000000000000000000000001b
Arg [11] : 68747470733a2f2f6d656368617661782e636f6d2f6d656368732f0000000000
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000025
Arg [13] : 68747470733a2f2f6d656368617661782e636f6d2f6d656368732f756e726576
Arg [14] : 65616c6564000000000000000000000000000000000000000000000000000000


Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.