ETH Price: $1,619.20 (-1.37%)

Contract

0xdc5F7aEd25A04D5004Efcb0D61175924424479c4

Overview

ETH Balance

50.61 ETH

ETH Value

$81,947.82 (@ $1,619.20/ETH)

Token Holdings

Transaction Hash
Method
Block
From
To
Claim Rewards66742802025-04-14 0:43:5820 secs ago1744591438IN
0xdc5F7aEd...4424479c4
0 ETH0.000006130.04525
Claim Rewards66742712025-04-14 0:43:4929 secs ago1744591429IN
0xdc5F7aEd...4424479c4
0 ETH0.000006650.04525
Claim Rewards66742592025-04-14 0:43:3741 secs ago1744591417IN
0xdc5F7aEd...4424479c4
0 ETH0.000004440.04525
Buy Miner66742592025-04-14 0:43:3741 secs ago1744591417IN
0xdc5F7aEd...4424479c4
0 ETH0.000010840.04525
Claim Rewards66742582025-04-14 0:43:3642 secs ago1744591416IN
0xdc5F7aEd...4424479c4
0 ETH0.000006410.04525
Claim Rewards66742352025-04-14 0:43:131 min ago1744591393IN
0xdc5F7aEd...4424479c4
0 ETH0.000006160.04525
Buy Miner66742282025-04-14 0:43:051 min ago1744591385IN
0xdc5F7aEd...4424479c4
0 ETH0.000011050.04525
Claim Rewards66742122025-04-14 0:42:491 min ago1744591369IN
0xdc5F7aEd...4424479c4
0 ETH0.000006950.04525
Claim Rewards66742092025-04-14 0:42:461 min ago1744591366IN
0xdc5F7aEd...4424479c4
0 ETH0.000006160.04525
Claim Rewards66741982025-04-14 0:42:351 min ago1744591355IN
0xdc5F7aEd...4424479c4
0 ETH0.000004320.04525
Claim Rewards66741952025-04-14 0:42:321 min ago1744591352IN
0xdc5F7aEd...4424479c4
0 ETH0.000006660.04525
Claim Rewards66741942025-04-14 0:42:311 min ago1744591351IN
0xdc5F7aEd...4424479c4
0 ETH0.000006670.04525
Claim Rewards66741822025-04-14 0:42:191 min ago1744591339IN
0xdc5F7aEd...4424479c4
0 ETH0.000006160.04525
Claim Rewards66741552025-04-14 0:41:522 mins ago1744591312IN
0xdc5F7aEd...4424479c4
0 ETH0.000006130.04525
Claim Rewards66741402025-04-14 0:41:372 mins ago1744591297IN
0xdc5F7aEd...4424479c4
0 ETH0.000006950.04525
Claim Rewards66741292025-04-14 0:41:262 mins ago1744591286IN
0xdc5F7aEd...4424479c4
0 ETH0.000004480.04525
Claim Rewards66741262025-04-14 0:41:232 mins ago1744591283IN
0xdc5F7aEd...4424479c4
0 ETH0.000006160.04525
Claim Rewards66741222025-04-14 0:41:192 mins ago1744591279IN
0xdc5F7aEd...4424479c4
0 ETH0.000006960.04525
Claim Rewards66741052025-04-14 0:41:013 mins ago1744591261IN
0xdc5F7aEd...4424479c4
0 ETH0.000006160.04525
Claim Rewards66740922025-04-14 0:40:483 mins ago1744591248IN
0xdc5F7aEd...4424479c4
0 ETH0.000006950.04525
Claim Rewards66740882025-04-14 0:40:443 mins ago1744591244IN
0xdc5F7aEd...4424479c4
0 ETH0.000006650.04525
Claim Rewards66740752025-04-14 0:40:313 mins ago1744591231IN
0xdc5F7aEd...4424479c4
0 ETH0.000006160.04525
Claim Rewards66740712025-04-14 0:40:273 mins ago1744591227IN
0xdc5F7aEd...4424479c4
0 ETH0.000006050.04525
Claim Rewards66740582025-04-14 0:40:144 mins ago1744591214IN
0xdc5F7aEd...4424479c4
0 ETH0.000006040.04525
Claim Rewards66740502025-04-14 0:40:064 mins ago1744591206IN
0xdc5F7aEd...4424479c4
0 ETH0.000005990.04525
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
66735082025-04-14 0:30:4413 mins ago1744590644
0xdc5F7aEd...4424479c4
0.015 ETH
66719972025-04-14 0:04:5739 mins ago1744589097
0xdc5F7aEd...4424479c4
0.015 ETH
66712122025-04-13 23:51:1853 mins ago1744588278
0xdc5F7aEd...4424479c4
0.015 ETH
66695572025-04-13 23:23:081 hr ago1744586588
0xdc5F7aEd...4424479c4
0.015 ETH
66691162025-04-13 23:15:211 hr ago1744586121
0xdc5F7aEd...4424479c4
0.015 ETH
66691092025-04-13 23:15:141 hr ago1744586114
0xdc5F7aEd...4424479c4
0.015 ETH
66687162025-04-13 23:08:321 hr ago1744585712
0xdc5F7aEd...4424479c4
0.015 ETH
66686512025-04-13 23:07:271 hr ago1744585647
0xdc5F7aEd...4424479c4
0.015 ETH
66685422025-04-13 23:05:361 hr ago1744585536
0xdc5F7aEd...4424479c4
0.015 ETH
66683972025-04-13 23:03:091 hr ago1744585389
0xdc5F7aEd...4424479c4
0.015 ETH
66679302025-04-13 22:55:051 hr ago1744584905
0xdc5F7aEd...4424479c4
0.015 ETH
66677202025-04-13 22:51:321 hr ago1744584692
0xdc5F7aEd...4424479c4
0.015 ETH
66670162025-04-13 22:39:432 hrs ago1744583983
0xdc5F7aEd...4424479c4
0.015 ETH
66653732025-04-13 22:11:392 hrs ago1744582299
0xdc5F7aEd...4424479c4
0.015 ETH
66652262025-04-13 22:09:122 hrs ago1744582152
0xdc5F7aEd...4424479c4
0.015 ETH
66648442025-04-13 22:02:292 hrs ago1744581749
0xdc5F7aEd...4424479c4
0.015 ETH
66640862025-04-13 21:49:332 hrs ago1744580973
0xdc5F7aEd...4424479c4
0.015 ETH
66639602025-04-13 21:47:252 hrs ago1744580845
0xdc5F7aEd...4424479c4
0.015 ETH
66633982025-04-13 21:37:573 hrs ago1744580277
0xdc5F7aEd...4424479c4
0.015 ETH
66632572025-04-13 21:35:353 hrs ago1744580135
0xdc5F7aEd...4424479c4
0.015 ETH
66629682025-04-13 21:30:313 hrs ago1744579831
0xdc5F7aEd...4424479c4
0.015 ETH
66628542025-04-13 21:28:373 hrs ago1744579717
0xdc5F7aEd...4424479c4
0.015 ETH
66626502025-04-13 21:25:123 hrs ago1744579512
0xdc5F7aEd...4424479c4
0.015 ETH
66622522025-04-13 21:18:333 hrs ago1744579113
0xdc5F7aEd...4424479c4
0.015 ETH
66589962025-04-13 20:23:134 hrs ago1744575793
0xdc5F7aEd...4424479c4
0.015 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Main

Compiler Version
v0.8.24+commit.e11b9ed9

ZkSolc Version
v1.5.12

Optimization Enabled:
Yes with Mode 3

Other Settings:
paris EvmVersion
File 1 of 12 : Main.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {EnumerableSetLib} from "solady/src/utils/EnumerableSetLib.sol";
import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol";
import {IMinetendo} from "./interfaces/IMinetendo.sol";
import {IV3SwapRouter} from "./interfaces/ISwapRouter.sol";
import {Miner} from "./types/Miner.sol";
import {Facility} from "./types/Facility.sol";
import {NewFacility} from "./types/NewFacility.sol";
import {Errors} from "./libraries/Errors.sol";
import {Events} from "./libraries/Events.sol";

contract Main is Ownable {
    using EnumerableSetLib for EnumerableSetLib.Uint256Set;

    address public constant SWAP_ROUTER =
        0x7712FA47387542819d4E35A23f8116C90C18767C;
    address public constant WETH = 0x3439153EB7AF838Ad19d56E1571FBD09333C2809;

    address public minetendo;

    /// @dev minetoshi fee recipient.
    address public minetoshi;

    /// @dev Mining start block.
    uint256 public startBlock;
    bool public miningHasStarted;

    // every miner has an id
    uint256 universalMinerId;

    /// @dev Total unique miners.
    uint256 public uniqueMinerCount;

    /// @dev Total facilities.
    uint256 public facilityCount;

    /// @dev Tracks last time we updated rewards.
    uint256 public lastRewardBlock;

    /// @dev Total network hashrate.
    uint256 public totalHashrate;

    bool public enableUpgradeFacility;

    /// @dev Tracks Minetendo per single hash.
    uint256 public cumulativeMinetendoPerHash;

    /// @dev Initial cooldown time is 24H.
    uint256 public cooldown = 24 hours;

    /// @dev Initial tier 1 referral fee is 2%.
    uint256 public referralFee = 0.02e18;

    /// @dev Initial tier 2 referral fee is 1%.
    uint256 public secondTierReferralFee = 0.01e18;

    /// @dev Initial burn is 80%.
    uint256 public burnPct = 0.8e18;

    /// @dev Players total hashrate.
    mapping(address => uint256) public playerHashrate;

    /// @dev Players pending rewards.
    mapping(address => uint256) public playerPendingRewards;

    /// @dev Players debt (updated after rewards are updated for a player).
    mapping(address => uint256) public playerMinetendoDebt;

    /// @dev Tracks different miners and its stats.
    mapping(uint256 => Miner) public miners;

    /// @dev Tracks different facilities and its stats.
    mapping(uint256 => NewFacility) public facilities;

    /// @dev Tracks how many of each miner a player has. Only tracks Id.
    mapping(address => EnumerableSetLib.Uint256Set) public playerMinersOwned;

    /// @dev Maps minerId to the actual miner struct
    mapping(uint256 => Miner) public playerMinersId;

    /// @dev Tracks players facility stats.
    mapping(address => Facility) public ownerToFacility;

    /// @dev Tracks new players initializing in the game.
    mapping(address => bool) public initializedStarterFacility;

    /// @dev Tracks if a player has acquired a free miner.
    mapping(address => bool) public acquiredStarterMiner;

    /// @dev Tracks if a there's a secondary market for a certain miner.
    mapping(uint256 => uint256) public minerSecondHandMarket;

    mapping(address => uint256) public lastFacilityUpgradeTimestamp;

    /// @dev Tracks direct referrals (tier 1).
    mapping(address => address) public referrals;

    /// @dev Tracks indirect referrals (tier 2) by storing the referrer of my referrer.
    mapping(address => address) public secondTierReferrals;

    /// @dev Tracks referred users.
    mapping(address => address[]) public referredUsers;

    /// @dev Track how much each referrer got paid from direct referrals.
    mapping(address => uint256) public referralBonusPaid;

    /// @dev Track how much each referrer got paid from indirect referrals.
    mapping(address => uint256) public secondTierReferralBonusPaid;

    /// @dev Purchasing initial facility price in ETH.
    uint256 public initialFacilityPrice = 0.01 ether;

    /// @dev start miner and facility index (these will never change since every player starts with same facility).
    uint256 public immutable STARTER_MINER_INDEX;
    uint256 public immutable STARTER_FACILITY_INDEX;

    /// @dev Halvening every 345,600 blocks, roughly 04 days
    uint256 public constant HALVING_INTERVAL = 345_600;

    /// @dev Initial Minetendo per block
    uint256 public constant INITIAL_MINETENDO_PER_BLOCK = 30e18; // 30 Minetendo per block

    uint256 public constant REWARDS_PRECISION = 1e18;

    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    //          CONSTRUCTOR
    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    constructor() Ownable(msg.sender) {
        STARTER_MINER_INDEX = ++uniqueMinerCount;

        // add starter free miner
        miners[STARTER_MINER_INDEX] = Miner(
            STARTER_MINER_INDEX,
            type(uint256).max,
            10,
            2,
            type(uint256).max, // this is the free starter miner, people cannot buy it
            false
        );

        // add starter facility
        facilities[++facilityCount] = NewFacility(
            1000,
            500,
            type(uint256).max, // starter facility, people cannot buy it
            false
        );

        STARTER_FACILITY_INDEX = facilityCount;
    }

    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    //        USER FUNCTIONS
    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    /**
     * @dev All new players must purchase an initial facility with ETH.
     *
     * Players can only purchase new facilities after acquiring initial Facility.
     */
    function purchaseInitialFacility(address referrer) external payable {
        if (msg.value != initialFacilityPrice) {
            revert Errors.IncorrectValue();
        }

        if (initializedStarterFacility[msg.sender]) {
            revert Errors.AlreadyPurchasedInitialFactory();
        }

        if (referrer == msg.sender) {
            revert Errors.InvalidReferrer();
        }

        initializedStarterFacility[msg.sender] = true;

        if (referrer != address(0)) {
            referrals[msg.sender] = referrer;
            referredUsers[referrer].push(msg.sender);

            // Set second tier referral (referrer's referrer)
            address secondTierReferrer = referrals[referrer];
            if (secondTierReferrer != address(0)) {
                secondTierReferrals[msg.sender] = secondTierReferrer;
            }
        }

        NewFacility memory newFacility = facilities[STARTER_FACILITY_INDEX];
        Facility storage facility = ownerToFacility[msg.sender];

        // initialize players starter facility
        facility.facilityIndex = STARTER_FACILITY_INDEX;
        facility.maxMiners = newFacility.maxMiners;
        facility.totalPowerOutput = newFacility.totalPowerOutput;

        _getFreeStarterMiner(msg.sender);

        emit Events.InitialFacilityPurchased(msg.sender);
    }

    /**
     * @dev Purchase new miners using Minetendo.
     */
    function buyMiner(uint256 minerIndex) external {
        // check user has enough funds for miner and facility allows it
        Miner memory miner = miners[minerIndex];
        Facility storage facility = ownerToFacility[msg.sender];

        // this case will cover if an index too large is passed in
        if (!miner.inProduction) revert Errors.MinerNotInProduction();

        if (IMinetendo(minetendo).balanceOf(msg.sender) < miner.cost) {
            revert Errors.TooPoor();
        }

        if (
            facility.currPowerOutput + miner.powerConsumption >
            facility.totalPowerOutput
        ) {
            revert Errors.FacilityInadequatePowerOutput();
        }

        // transfer correct amt of Minetendo
        IMinetendo(minetendo).transferFrom(
            msg.sender,
            address(this),
            miner.cost
        );

        uint256 amountToBurn = FixedPointMathLib.mulWad(miner.cost, burnPct);
        // burn
        IMinetendo(minetendo).burn(amountToBurn);

        uint256 amountToETH = miner.cost - amountToBurn;
        // swap MINE to ETH
        _swapMINEtoETH(amountToETH);

        miner.id = ++universalMinerId;

        playerMinersOwned[msg.sender].add(universalMinerId);
        playerMinersId[universalMinerId] = miner;

        // increase facility miners
        facility.currMiners++;

        // increase power consumption from factory
        facility.currPowerOutput += miner.powerConsumption;

        emit Events.MinerBought(
            msg.sender,
            minerIndex,
            miner.cost,
            universalMinerId
        );

        _increaseHashrate(msg.sender, miner.hashrate);
    }

    function sellMiner(uint256 minerId) external {
        if (!playerMinersOwned[msg.sender].contains(minerId)) {
            revert Errors.PlayerDoesNotOwnMiner();
        }

        Miner memory miner = playerMinersId[minerId];

        uint256 secondHandPrice = minerSecondHandMarket[miner.minerIndex];

        if (secondHandPrice > IMinetendo(minetendo).balanceOf(address(this))) {
            revert Errors.GreatDepression();
        }

        Facility storage facility = ownerToFacility[msg.sender];

        facility.currMiners--;

        facility.currPowerOutput -= miner.powerConsumption;

        playerMinersOwned[msg.sender].remove(minerId);
        delete playerMinersId[minerId];

        emit Events.MinerSold(
            msg.sender,
            miner.minerIndex,
            secondHandPrice,
            minerId
        );

        _decreaseHashrate(msg.sender, miner.hashrate);

        if (secondHandPrice > 0) {
            IMinetendo(minetendo).transfer(msg.sender, secondHandPrice);
        }
    }

    /**
     * @dev Purchase larger or more power output facility.
     *
     * Players must linearly climb the facilities.
     */
    function upgradeFacility() external {
        if (!enableUpgradeFacility) {
            revert Errors.UpgradeFacilityDisabled();
        }

        // need to purchase initial facility first
        if (!initializedStarterFacility[msg.sender]) {
            revert Errors.NeedToInitializeFacility();
        }

        Facility storage currFacility = ownerToFacility[msg.sender];
        uint256 currFacilityIndex = currFacility.facilityIndex;

        if (currFacilityIndex == facilityCount) {
            revert Errors.AlreadyAtMaxFacility();
        }

        // 24H cooldown between each facility upgrade
        if (
            block.timestamp - lastFacilityUpgradeTimestamp[msg.sender] <
            cooldown
        ) {
            revert Errors.CantBuyNewFacilityYet();
        }

        NewFacility memory newFacility = facilities[currFacilityIndex + 1];

        if (!newFacility.inProduction) {
            revert Errors.NewFacilityNotInProduction();
        }

        if (IMinetendo(minetendo).balanceOf(msg.sender) < newFacility.cost) {
            revert Errors.TooPoor();
        }

        IMinetendo(minetendo).transferFrom(
            msg.sender,
            address(this),
            newFacility.cost
        );

        uint256 amountToBurn = FixedPointMathLib.mulWad(
            newFacility.cost,
            burnPct
        );
        // burn

        IMinetendo(minetendo).burn(amountToBurn);

        currFacility.facilityIndex++;
        currFacility.maxMiners = newFacility.maxMiners;
        currFacility.totalPowerOutput = newFacility.totalPowerOutput;

        lastFacilityUpgradeTimestamp[msg.sender] = block.timestamp;

        emit Events.FacilityBought(
            msg.sender,
            currFacility.facilityIndex,
            newFacility.cost
        );
    }

    /**
     * @dev Claim rewards for player.
     */
    function claimRewards() external {
        _updateRewards(msg.sender);

        uint256 rewards = playerPendingRewards[msg.sender];
        if (rewards == 0) {
            revert Errors.NoRewardsPending();
        }

        playerPendingRewards[msg.sender] = 0;

        // Calculate tier 1 and tier 2 referral bonuses
        uint256 tier1Bonus = FixedPointMathLib.mulWad(rewards, referralFee);
        uint256 tier2Bonus = FixedPointMathLib.mulWad(
            rewards,
            secondTierReferralFee
        );
        uint256 finalRewards = rewards - tier1Bonus - tier2Bonus;

        // Mint rewards to player
        IMinetendo(minetendo).mint(msg.sender, finalRewards);

        // Handle tier 1 referral
        address tier1Referrer = referrals[msg.sender];
        if (tier1Referrer != address(0)) {
            IMinetendo(minetendo).mint(tier1Referrer, tier1Bonus);
            referralBonusPaid[tier1Referrer] += tier1Bonus;
        } else {
            IMinetendo(minetendo).mint(address(this), tier1Bonus);
            referralBonusPaid[address(this)] += tier1Bonus;
        }

        // Handle tier 2 referral
        address tier2Referrer = secondTierReferrals[msg.sender];
        if (tier2Referrer != address(0)) {
            IMinetendo(minetendo).mint(tier2Referrer, tier2Bonus);
            secondTierReferralBonusPaid[tier2Referrer] += tier2Bonus;
        } else {
            // No referrers at all, mint to contract
            IMinetendo(minetendo).mint(address(this), tier2Bonus);
            secondTierReferralBonusPaid[address(this)] += tier2Bonus;
        }

        emit Events.RewardsClaimed(msg.sender, rewards);
    }

    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    //       INTERNAL FUNCTIONS
    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    function _getFreeStarterMiner(address user) internal {
        if (acquiredStarterMiner[user]) {
            revert Errors.StarterMinerAlreadyAcquired();
        }

        acquiredStarterMiner[user] = true;

        Miner memory miner = miners[STARTER_MINER_INDEX];
        Facility storage facility = ownerToFacility[user];

        if (
            facility.currPowerOutput + miner.powerConsumption >
            facility.totalPowerOutput
        ) {
            revert Errors.FacilityInadequatePowerOutput();
        }

        miner.id = ++universalMinerId;

        playerMinersOwned[user].add(universalMinerId);
        playerMinersId[universalMinerId] = miner;

        // increase facility miners
        facility.currMiners++;

        // increase power consumption from factory
        facility.currPowerOutput += miner.powerConsumption;

        // emit Events.FreeMinerRedeemed(user);
        emit Events.MinerBought(user, STARTER_MINER_INDEX, 0, universalMinerId);

        _increaseHashrate(user, miner.hashrate);
    }

    /**
     * @dev Update global cumulative rewards before game state changes.
     */
    function _updateCumulativeRewards() internal {
        if (totalHashrate == 0) {
            lastRewardBlock = block.number;
            return;
        }

        uint256 currentBlock = lastRewardBlock;
        uint256 lastMinetendoPerBlock = INITIAL_MINETENDO_PER_BLOCK /
            (2 ** ((lastRewardBlock - startBlock) / HALVING_INTERVAL));

        while (currentBlock < block.number) {
            uint256 nextHalvingBlock = (startBlock % HALVING_INTERVAL) +
                ((currentBlock / HALVING_INTERVAL) + 1) *
                HALVING_INTERVAL;
            uint256 endBlock = (nextHalvingBlock < block.number)
                ? nextHalvingBlock
                : block.number;

            // apply correct emission rate for this segment
            cumulativeMinetendoPerHash += ((lastMinetendoPerBlock *
                (endBlock - currentBlock) *
                REWARDS_PRECISION) / totalHashrate);

            // move to next segment
            currentBlock = endBlock;

            // if a halving has happened, apply the new rate
            if (currentBlock == nextHalvingBlock) {
                lastMinetendoPerBlock /= 2;
            }
        }

        lastRewardBlock = block.number;
    }

    function _updateRewards(address player) internal {
        _updateCumulativeRewards();

        playerPendingRewards[player] +=
            (playerHashrate[player] *
                (cumulativeMinetendoPerHash - playerMinetendoDebt[player])) /
            REWARDS_PRECISION;

        playerMinetendoDebt[player] = cumulativeMinetendoPerHash;
    }

    /**
     * @dev Increase players hashrate.
     */
    function _increaseHashrate(address player, uint256 hashrate) internal {
        if (!miningHasStarted) {
            miningHasStarted = true;
            startBlock = block.number;
            lastRewardBlock = block.number;

            emit Events.MiningStarted(startBlock);
        }

        // update rewards and global state before modifying players state
        _updateRewards(player);

        totalHashrate += hashrate;
        playerHashrate[player] += hashrate;

        emit Events.PlayerHashrateIncreased(
            msg.sender,
            playerHashrate[player],
            playerPendingRewards[player]
        );
    }

    /**
     * @dev Decrease players hashrate.
     */
    function _decreaseHashrate(address player, uint256 hashrate) internal {
        // update rewards and global state before modifying players state
        _updateRewards(player);

        totalHashrate -= hashrate;
        playerHashrate[player] -= hashrate;

        emit Events.PlayerHashrateDecreased(
            msg.sender,
            playerHashrate[player],
            playerPendingRewards[player]
        );
    }

    function _swapMINEtoETH(uint256 _amount) internal {
        IMinetendo(minetendo).approve(SWAP_ROUTER, _amount);
        try
            IV3SwapRouter(SWAP_ROUTER).exactInputSingle(
                IV3SwapRouter.ExactInputSingleParams({
                    tokenIn: minetendo,
                    tokenOut: WETH,
                    fee: 10000,
                    recipient: minetoshi,
                    amountIn: _amount,
                    amountOutMinimum: 0,
                    sqrtPriceLimitX96: 0
                })
            )
        {} catch {}
    }

    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    //         VIEW FUNCTIONS
    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    /**
     * @dev Get the current mining emission rate based on halvings
     */
    function getMinetendoPerBlock() public view returns (uint256) {
        if (!miningHasStarted) {
            return 0;
        }

        uint256 halvingsSinceStart = (block.number - startBlock) /
            HALVING_INTERVAL;

        return INITIAL_MINETENDO_PER_BLOCK / (2 ** halvingsSinceStart);
    }

    /**
     * @dev Get current pending rewards for player.
     */
    function pendingRewards(address player) external view returns (uint256) {
        // below is basically the same logic as _updateCumulativeRewards() but doesnt change state
        if (!miningHasStarted) {
            return 0;
        }

        if (totalHashrate == 0) {
            return
                FixedPointMathLib.mulWad(
                    playerPendingRewards[player],
                    1e18 - referralFee - secondTierReferralFee
                );
        }

        uint256 currentBlock = lastRewardBlock;
        uint256 lastMinetendoPerBlock = INITIAL_MINETENDO_PER_BLOCK /
            (2 ** ((lastRewardBlock - startBlock) / HALVING_INTERVAL));

        uint256 simulatedCumulativeMinetendoPerHash = cumulativeMinetendoPerHash;

        while (currentBlock < block.number) {
            uint256 nextHalvingBlock = (startBlock % HALVING_INTERVAL) +
                ((currentBlock / HALVING_INTERVAL) + 1) *
                HALVING_INTERVAL;
            uint256 endBlock = (nextHalvingBlock < block.number)
                ? nextHalvingBlock
                : block.number;

            // simulate rewards accumulation
            if (totalHashrate > 0) {
                simulatedCumulativeMinetendoPerHash += ((lastMinetendoPerBlock *
                    (endBlock - currentBlock) *
                    REWARDS_PRECISION) / totalHashrate);
            }

            // move to next segment
            currentBlock = endBlock;

            // if we reached a halving point, apply the new emission rate
            if (currentBlock == nextHalvingBlock) {
                lastMinetendoPerBlock /= 2;
            }
        }

        return
            FixedPointMathLib.mulWad(
                playerPendingRewards[player] +
                    ((playerHashrate[player] *
                        (simulatedCumulativeMinetendoPerHash -
                            playerMinetendoDebt[player])) / REWARDS_PRECISION),
                1e18 - referralFee - secondTierReferralFee
            );
    }

    function playerMinetendoPerBlock(
        address player
    ) external view returns (uint256) {
        if (totalHashrate == 0) {
            return 0; // Prevent division by zero
        }

        uint256 currMinetendoPerBlock = INITIAL_MINETENDO_PER_BLOCK /
            (2 ** ((block.number - startBlock) / HALVING_INTERVAL));

        return
            FixedPointMathLib.mulDiv(
                playerHashrate[player],
                currMinetendoPerBlock,
                totalHashrate
            );
    }

    /**
     * @dev Get blocks till next halvening.
     */
    function blocksUntilNextHalving() external view returns (uint256) {
        if (startBlock == 0) revert Errors.MiningHasntStarted();

        uint256 nextHalvingBlock = (startBlock % HALVING_INTERVAL) +
            ((block.number / HALVING_INTERVAL) + 1) *
            HALVING_INTERVAL;

        return nextHalvingBlock - block.number;
    }

    /**
     * @dev Get next available facility upgrade time.
     */
    function timeUntilNextFacilityUpgrade(
        address player
    ) external view returns (uint256) {
        if (lastFacilityUpgradeTimestamp[player] + cooldown < block.timestamp) {
            return 0;
        }

        return
            (lastFacilityUpgradeTimestamp[player] + cooldown) - block.timestamp;
    }

    /**
     * @dev Get all miners for a player.
     */
    function getPlayerMinersPaginated(
        address player,
        uint256 startIndex,
        uint256 size
    ) external view returns (Miner[] memory) {
        EnumerableSetLib.Uint256Set storage set = playerMinersOwned[player];
        uint256 length = set.length();

        // Return empty array if start index is beyond array bounds
        if (startIndex >= length) {
            return new Miner[](0);
        }

        // Calculate how many items we can actually return
        uint256 remaining = length - startIndex;
        uint256 returnSize = size > remaining ? remaining : size;

        Miner[] memory playerMiners = new Miner[](returnSize);
        for (uint256 i = 0; i < returnSize; i++) {
            playerMiners[i] = playerMinersId[set.at(startIndex + i)];
        }

        return playerMiners;
    }

    function getTotalMiners(address player) external view returns (uint256) {
        return playerMinersOwned[player].length();
    }

    /**
     * @dev Get all referred users.
     */
    function getReferrals(
        address referrer
    ) external view returns (address[] memory) {
        return referredUsers[referrer];
    }

    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    //        OWNER FUNCTIONS
    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    /**
     * @dev Add new miner to game.
     */
    function addMiner(
        uint256 hashrate,
        uint256 powerConsumption,
        uint256 cost,
        bool inProduction
    ) external onlyOwner {
        // must increment first cause compiler evaluates function arg before evaluating the assignment
        ++uniqueMinerCount;
        miners[uniqueMinerCount] = Miner(
            uniqueMinerCount,
            0,
            hashrate,
            powerConsumption,
            cost,
            inProduction
        );

        emit Events.NewMinerAdded(
            uniqueMinerCount,
            hashrate,
            powerConsumption,
            cost,
            inProduction
        );
    }

    /**
     * @dev Allows or prevents miner from being purchased.
     *
     * Miners cannot be removed, only toggled off from purchased.
     */
    function toggleMinerProduction(
        uint256 minerIndex,
        bool inProduction
    ) external onlyOwner {
        if (minerIndex < STARTER_MINER_INDEX || minerIndex > uniqueMinerCount) {
            revert Errors.InvalidMinerIndex();
        }
        Miner storage miner = miners[minerIndex];
        miner.inProduction = inProduction;

        emit Events.MinerProductionToggled(minerIndex, inProduction);
    }

    /**
     * @dev Add new facility to game.
     */
    function addFacility(
        uint256 maxMiners,
        uint256 totalPowerOutput,
        uint256 cost,
        bool inProduction
    ) external onlyOwner {
        if (facilities[facilityCount].totalPowerOutput > totalPowerOutput) {
            revert Errors.InvalidPowerOutput();
        }

        facilities[++facilityCount] = NewFacility(
            maxMiners,
            totalPowerOutput,
            cost,
            inProduction
        );

        emit Events.NewFacilityAdded(
            facilityCount,
            totalPowerOutput,
            cost,
            inProduction
        );
    }

    /**
     * @dev Allows or prevents new facilities from being purchased.
     *
     * New facilities cannot be removed, only toggled off from purchased.
     */
    function toggleFacilityProduction(
        uint256 facilityIndex,
        bool inProduction
    ) external onlyOwner {
        if (
            facilityIndex < STARTER_FACILITY_INDEX ||
            facilityIndex > facilityCount
        ) {
            revert Errors.InvalidFacilityIndex();
        }

        NewFacility storage facility = facilities[facilityIndex];
        facility.inProduction = inProduction;

        emit Events.FacilityProductionToggled(facilityIndex, inProduction);
    }

    /**
     * @dev Add secondary market for a miner.
     */
    function addSecondaryMarketForMiner(
        uint256 minerIndex,
        uint256 price
    ) external onlyOwner {
        minerSecondHandMarket[minerIndex] = price;

        emit Events.MinerSecondaryMarketAdded(minerIndex, price);
    }

    function setMinetendo(address _minetendo) external onlyOwner {
        minetendo = _minetendo;
    }

    function setMinetoshi(address _minetoshi) external onlyOwner {
        minetoshi = _minetoshi;
    }

    function setInitialFacilityPrice(uint256 _initialPrice) external onlyOwner {
        initialFacilityPrice = _initialPrice;
    }

    function setReferralFee(uint256 fee) external onlyOwner {
        if (fee > 1e18) revert Errors.InvalidFee();
        referralFee = fee;
    }

    function setSecondTierReferralFee(uint256 fee) external onlyOwner {
        if (fee > 1e18) revert Errors.InvalidFee();
        secondTierReferralFee = fee;
    }

    function setBurnPct(uint256 burn) external onlyOwner {
        if (burn > 1e18) revert Errors.InvalidFee();

        burnPct = burn;
    }

    function setEnableUpgradeFacility(bool enable) external onlyOwner {
        enableUpgradeFacility = enable;
    }

    function setCooldown(uint256 _cooldown) external onlyOwner {
        cooldown = _cooldown;
    }

    function withdraw() external onlyOwner {
        uint256 balance = address(this).balance;
        (bool success, ) = payable(minetoshi).call{value: balance}("");

        if (!success) revert Errors.WithdrawFailed();
    }

    function withdrawMinetendo(uint256 amt) external onlyOwner {
        IMinetendo(minetendo).transfer(minetoshi, amt);
    }

    function changeMinerCost(
        uint256 minerIndex,
        uint256 newCost
    ) external onlyOwner {
        if (minerIndex > uniqueMinerCount) {
            revert Errors.NonExistentMiner();
        }

        if (minerIndex == STARTER_MINER_INDEX) {
            revert Errors.CantModifyStarterMiner();
        }

        Miner storage miner = miners[minerIndex];

        miner.cost = newCost;

        emit Events.MinerCostChanged(minerIndex, newCost);
    }

    function changeFacilityCost(
        uint256 facilityIndex,
        uint256 newCost
    ) external onlyOwner {
        if (facilityIndex > facilityCount) {
            revert Errors.NonExistentFacility();
        }

        if (facilityIndex == STARTER_FACILITY_INDEX) {
            revert Errors.CantModifyStarterFacility();
        }

        NewFacility storage facility = facilities[facilityIndex];

        facility.cost = newCost;

        emit Events.FacilityCostChanged(facilityIndex, newCost);
    }

    function changeMinerPowerConsumption(
        uint256 minerIndex,
        uint256 newPowerConsumption
    ) external onlyOwner {
        if (minerIndex > uniqueMinerCount) {
            revert Errors.NonExistentMiner();
        }

        Miner storage miner = miners[minerIndex];

        miner.powerConsumption = newPowerConsumption;

        emit Events.MinerPowerConsumptionChanged(
            minerIndex,
            newPowerConsumption
        );
    }
}

File 2 of 12 : IMinetendo.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.24;

interface IMinetendo {
    function mint(address to, uint256 amt) external;

    function burn(uint256 value) external;

    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address to, uint256 value) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transferFrom(address from, address to, uint256 value) external returns (bool);

    function setMinter(address _minter) external;

    function amtBurned() external view returns (uint256);

    function minter() external view returns (address);

    function MAX_SUPPLY() external view returns (uint256);
}

File 3 of 12 : NewFacility.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/**
 * @dev Facilities that can be purchased in game.
 */
struct NewFacility {
    uint256 maxMiners;
    uint256 totalPowerOutput;
    uint256 cost;
    bool inProduction;
}

File 4 of 12 : ISwapRouter.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.7.5;

/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface IV3SwapRouter  {
    struct ExactInputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 amountIn;
        uint256 amountOutMinimum;
        uint160 sqrtPriceLimitX96;
    }

    /// @notice Swaps `amountIn` of one token for as much as possible of another token
    /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance,
    /// and swap the entire amount, enabling contracts to send tokens before calling this function.
    /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata
    /// @return amountOut The amount of the received token
    function exactInputSingle(
        ExactInputSingleParams calldata params
    ) external payable returns (uint256 amountOut);

    struct ExactInputParams {
        bytes path;
        address recipient;
        uint256 amountIn;
        uint256 amountOutMinimum;
    }

    /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path
    /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance,
    /// and swap the entire amount, enabling contracts to send tokens before calling this function.
    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata
    /// @return amountOut The amount of the received token
    function exactInput(
        ExactInputParams calldata params
    ) external payable returns (uint256 amountOut);

    struct ExactOutputSingleParams {
        address tokenIn;
        address tokenOut;
        uint24 fee;
        address recipient;
        uint256 amountOut;
        uint256 amountInMaximum;
        uint160 sqrtPriceLimitX96;
    }

    /// @notice Swaps as little as possible of one token for `amountOut` of another token
    /// that may remain in the router after the swap.
    /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata
    /// @return amountIn The amount of the input token
    function exactOutputSingle(
        ExactOutputSingleParams calldata params
    ) external payable returns (uint256 amountIn);

    struct ExactOutputParams {
        bytes path;
        address recipient;
        uint256 amountOut;
        uint256 amountInMaximum;
    }

    /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed)
    /// that may remain in the router after the swap.
    /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata
    /// @return amountIn The amount of the input token
    function exactOutput(
        ExactOutputParams calldata params
    ) external payable returns (uint256 amountIn);
}

File 5 of 12 : Miner.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/**
 * @dev Miners that can be purchased in the game.
 */
struct Miner {
    uint256 minerIndex;
    uint256 id;
    uint256 hashrate;
    uint256 powerConsumption;
    uint256 cost;
    bool inProduction;
}

File 6 of 12 : Errors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

library Errors {
    error IncorrectValue();
    error AlreadyPurchasedInitialFactory();
    error StarterMinerAlreadyAcquired();
    error FacilityAtMaxCapacity();
    error FacilityInadequatePowerOutput();
    error PlayerDoesNotOwnMiner();
    error GreatDepression();
    error MinerNotInProduction();
    error TooPoor();
    error NewFacilityNotInProduction();
    error CannotDowngradeAFacility();
    error NoRewardsPending();
    error CannotDecreaseBelowZero();
    error InvalidMinerCoordinates();
    error NeedToInitializeFacility();
    error InvalidReferrer();
    error NonExistentMiner();
    error CantModifyStarterMiner();
    error NonExistentFacility();
    error CantModifyStarterFacility();
    error AlreadyAtMaxFacility();
    error CantBuyNewFacilityYet();
    error InvalidMinerIndex();
    error InvalidFacilityIndex();
    error InvalidFee();
    error InvalidPowerOutput();
    error MiningHasntStarted();
    error WithdrawFailed();
    error UpgradeFacilityDisabled();
}

File 7 of 12 : Facility.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/**
 * @dev Current player's facility.
 */
struct Facility {
    uint256 facilityIndex;
    uint256 maxMiners;
    uint256 currMiners;
    uint256 totalPowerOutput;
    uint256 currPowerOutput;
}

File 8 of 12 : Events.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

library Events {
    event MiningStarted(uint256 startBlock);

    event NewMinerAdded(
        uint256 indexed minerIndex,
        uint256 hashRate,
        uint256 powerConsumption,
        uint256 cost,
        bool inProduction
    );

    event MinerProductionToggled(uint256 indexed minerIndex, bool inProduction);

    event FacilityProductionToggled(
        uint256 indexed facilityIndex,
        bool inProduction
    );

    event NewFacilityAdded(
        uint256 indexed facilityIndex,
        uint256 totalPowerOutput,
        uint256 cost,
        bool inProduction
    );

    event MinerSecondaryMarketAdded(uint256 indexed minerIndex, uint256 price);

    event InitialFacilityPurchased(address indexed player);

    event FreeMinerRedeemed(address indexed player);

    event MinerSold(
        address indexed player,
        uint256 indexed minerIndex,
        uint256 secondHandPrice,
        uint256 minerId
    );

    event MinerBought(
        address indexed player,
        uint256 indexed minerIndex,
        uint256 cost,
        uint256 minerId
    );

    event FacilityBought(
        address indexed player,
        uint256 indexed facilityIndex,
        uint256 cost
    );

    event PlayerHashrateIncreased(
        address indexed player,
        uint256 playerHashrate,
        uint256 playerPendingRewards
    );

    event PlayerHashrateDecreased(
        address indexed player,
        uint256 playerHashrate,
        uint256 playerPendingRewards
    );

    event RewardsClaimed(address indexed player, uint256 rewards);

    event MinerCostChanged(uint256 indexed minerIndex, uint256 newCost);

    event FacilityCostChanged(uint256 indexed facilityIndex, uint256 newCost);

    event JackpotETHSwapped(uint256 amountIn, uint256 amountOut);

    event MinerPowerConsumptionChanged(
        uint256 indexed minerIndex,
        uint256 newPowerConsumption
    );
}

File 9 of 12 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

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

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

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

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

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

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

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

File 10 of 12 : EnumerableSetLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for managing enumerable sets in storage.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EnumerableSetLib.sol)
///
/// @dev Note:
/// In many applications, the number of elements in an enumerable set is small.
/// This enumerable set implementation avoids storing the length and indices
/// for up to 3 elements. Once the length exceeds 3 for the first time, the length
/// and indices will be initialized. The amortized cost of adding elements is O(1).
///
/// The AddressSet implementation packs the length with the 0th entry.
///
/// All enumerable sets except Uint8Set use a pop and swap mechanism to remove elements.
/// This means that the iteration order of elements can change between element removals.
library EnumerableSetLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The index must be less than the length.
    error IndexOutOfBounds();

    /// @dev The value cannot be the zero sentinel.
    error ValueIsZeroSentinel();

    /// @dev Cannot accommodate a new unique value with the capacity.
    error ExceedsCapacity();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A sentinel value to denote the zero value in storage.
    /// No elements can be equal to this value.
    /// `uint72(bytes9(keccak256(bytes("_ZERO_SENTINEL"))))`.
    uint256 private constant _ZERO_SENTINEL = 0xfbb67fda52d4bfb8bf;

    /// @dev The storage layout is given by:
    /// ```
    ///     mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
    ///     mstore(0x00, set.slot)
    ///     let rootSlot := keccak256(0x00, 0x24)
    ///     mstore(0x20, rootSlot)
    ///     mstore(0x00, shr(96, shl(96, value)))
    ///     let positionSlot := keccak256(0x00, 0x40)
    ///     let valueSlot := add(rootSlot, sload(positionSlot))
    ///     let valueInStorage := shr(96, sload(valueSlot))
    ///     let lazyLength := shr(160, shl(160, sload(rootSlot)))
    /// ```
    uint256 private constant _ENUMERABLE_ADDRESS_SET_SLOT_SEED = 0x978aab92;

    /// @dev The storage layout is given by:
    /// ```
    ///     mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
    ///     mstore(0x00, set.slot)
    ///     let rootSlot := keccak256(0x00, 0x24)
    ///     mstore(0x20, rootSlot)
    ///     mstore(0x00, value)
    ///     let positionSlot := keccak256(0x00, 0x40)
    ///     let valueSlot := add(rootSlot, sload(positionSlot))
    ///     let valueInStorage := sload(valueSlot)
    ///     let lazyLength := sload(not(rootSlot))
    /// ```
    uint256 private constant _ENUMERABLE_WORD_SET_SLOT_SEED = 0x18fb5864;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev An enumerable address set in storage.
    struct AddressSet {
        uint256 _spacer;
    }

    /// @dev An enumerable bytes32 set in storage.
    struct Bytes32Set {
        uint256 _spacer;
    }

    /// @dev An enumerable uint256 set in storage.
    struct Uint256Set {
        uint256 _spacer;
    }

    /// @dev An enumerable int256 set in storage.
    struct Int256Set {
        uint256 _spacer;
    }

    /// @dev An enumerable uint8 set in storage. Useful for enums.
    struct Uint8Set {
        uint256 data;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     GETTERS / SETTERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the number of elements in the set.
    function length(AddressSet storage set) internal view returns (uint256 result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let rootPacked := sload(rootSlot)
            let n := shr(160, shl(160, rootPacked))
            result := shr(1, n)
            for {} iszero(or(iszero(shr(96, rootPacked)), n)) {} {
                result := 1
                if iszero(sload(add(rootSlot, result))) { break }
                result := 2
                if iszero(sload(add(rootSlot, result))) { break }
                result := 3
                break
            }
        }
    }

    /// @dev Returns the number of elements in the set.
    function length(Bytes32Set storage set) internal view returns (uint256 result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let n := sload(not(rootSlot))
            result := shr(1, n)
            for {} iszero(n) {} {
                result := 0
                if iszero(sload(add(rootSlot, result))) { break }
                result := 1
                if iszero(sload(add(rootSlot, result))) { break }
                result := 2
                if iszero(sload(add(rootSlot, result))) { break }
                result := 3
                break
            }
        }
    }

    /// @dev Returns the number of elements in the set.
    function length(Uint256Set storage set) internal view returns (uint256 result) {
        result = length(_toBytes32Set(set));
    }

    /// @dev Returns the number of elements in the set.
    function length(Int256Set storage set) internal view returns (uint256 result) {
        result = length(_toBytes32Set(set));
    }

    /// @dev Returns the number of elements in the set.
    function length(Uint8Set storage set) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for { let packed := sload(set.slot) } packed { result := add(1, result) } {
                packed := xor(packed, and(packed, add(1, not(packed))))
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(AddressSet storage set, address value) internal view returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for {} 1 {} {
                if iszero(shr(160, shl(160, rootPacked))) {
                    result := 1
                    if eq(shr(96, rootPacked), value) { break }
                    if eq(shr(96, sload(add(rootSlot, 1))), value) { break }
                    if eq(shr(96, sload(add(rootSlot, 2))), value) { break }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                result := iszero(iszero(sload(keccak256(0x00, 0x40))))
                break
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for {} 1 {} {
                if iszero(sload(not(rootSlot))) {
                    result := 1
                    if eq(sload(rootSlot), value) { break }
                    if eq(sload(add(rootSlot, 1)), value) { break }
                    if eq(sload(add(rootSlot, 2)), value) { break }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                result := iszero(iszero(sload(keccak256(0x00, 0x40))))
                break
            }
        }
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Uint256Set storage set, uint256 value) internal view returns (bool result) {
        result = contains(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Int256Set storage set, int256 value) internal view returns (bool result) {
        result = contains(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Returns whether `value` is in the set.
    function contains(Uint8Set storage set, uint8 value) internal view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(1, shr(and(0xff, value), sload(set.slot)))
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(AddressSet storage set, address value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
                mstore(0x20, rootSlot)
                if iszero(n) {
                    let v0 := shr(96, rootPacked)
                    if iszero(v0) {
                        sstore(rootSlot, shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v0, value) { break }
                    let v1 := shr(96, sload(add(rootSlot, 1)))
                    if iszero(v1) {
                        sstore(add(rootSlot, 1), shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v1, value) { break }
                    let v2 := shr(96, sload(add(rootSlot, 2)))
                    if iszero(v2) {
                        sstore(add(rootSlot, 2), shl(96, value))
                        result := 1
                        break
                    }
                    if eq(v2, value) { break }
                    mstore(0x00, v0)
                    sstore(keccak256(0x00, 0x40), 1)
                    mstore(0x00, v1)
                    sstore(keccak256(0x00, 0x40), 2)
                    mstore(0x00, v2)
                    sstore(keccak256(0x00, 0x40), 3)
                    rootPacked := or(rootPacked, 7)
                    n := 7
                }
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                if iszero(sload(p)) {
                    n := shr(1, n)
                    result := 1
                    sstore(p, add(1, n))
                    if iszero(n) {
                        sstore(rootSlot, or(3, shl(96, value)))
                        break
                    }
                    sstore(add(rootSlot, n), shl(96, value))
                    sstore(rootSlot, add(2, rootPacked))
                    break
                }
                break
            }
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for { let n := sload(not(rootSlot)) } 1 {} {
                mstore(0x20, rootSlot)
                if iszero(n) {
                    let v0 := sload(rootSlot)
                    if iszero(v0) {
                        sstore(rootSlot, value)
                        result := 1
                        break
                    }
                    if eq(v0, value) { break }
                    let v1 := sload(add(rootSlot, 1))
                    if iszero(v1) {
                        sstore(add(rootSlot, 1), value)
                        result := 1
                        break
                    }
                    if eq(v1, value) { break }
                    let v2 := sload(add(rootSlot, 2))
                    if iszero(v2) {
                        sstore(add(rootSlot, 2), value)
                        result := 1
                        break
                    }
                    if eq(v2, value) { break }
                    mstore(0x00, v0)
                    sstore(keccak256(0x00, 0x40), 1)
                    mstore(0x00, v1)
                    sstore(keccak256(0x00, 0x40), 2)
                    mstore(0x00, v2)
                    sstore(keccak256(0x00, 0x40), 3)
                    n := 7
                }
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                if iszero(sload(p)) {
                    n := shr(1, n)
                    sstore(add(rootSlot, n), value)
                    sstore(p, add(1, n))
                    sstore(not(rootSlot), or(1, shl(1, add(1, n))))
                    result := 1
                    break
                }
                break
            }
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Uint256Set storage set, uint256 value) internal returns (bool result) {
        result = add(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Int256Set storage set, int256 value) internal returns (bool result) {
        result = add(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    function add(Uint8Set storage set, uint8 value) internal returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(set.slot)
            let mask := shl(and(0xff, value), 1)
            sstore(set.slot, or(result, mask))
            result := iszero(and(result, mask))
        }
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(AddressSet storage set, address value, uint256 cap)
        internal
        returns (bool result)
    {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(Bytes32Set storage set, bytes32 value, uint256 cap)
        internal
        returns (bool result)
    {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(Uint256Set storage set, uint256 value, uint256 cap)
        internal
        returns (bool result)
    {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(Int256Set storage set, int256 value, uint256 cap) internal returns (bool result) {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Adds `value` to the set. Returns whether `value` was not in the set.
    /// Reverts if the set grows bigger than the custom on-the-fly capacity `cap`.
    function add(Uint8Set storage set, uint8 value, uint256 cap) internal returns (bool result) {
        if (result = add(set, value)) if (length(set) > cap) revert ExceedsCapacity();
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(AddressSet storage set, address value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            value := shr(96, shl(96, value))
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            let rootPacked := sload(rootSlot)
            for { let n := shr(160, shl(160, rootPacked)) } 1 {} {
                if iszero(n) {
                    result := 1
                    if eq(shr(96, rootPacked), value) {
                        sstore(rootSlot, sload(add(rootSlot, 1)))
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(shr(96, sload(add(rootSlot, 1))), value) {
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(shr(96, sload(add(rootSlot, 2))), value) {
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                let position := sload(p)
                if iszero(position) { break }
                n := sub(shr(1, n), 1)
                if iszero(eq(sub(position, 1), n)) {
                    let lastValue := shr(96, sload(add(rootSlot, n)))
                    sstore(add(rootSlot, sub(position, 1)), shl(96, lastValue))
                    mstore(0x00, lastValue)
                    sstore(keccak256(0x00, 0x40), position)
                }
                sstore(rootSlot, or(shl(96, shr(96, sload(rootSlot))), or(shl(1, n), 1)))
                sstore(p, 0)
                result := 1
                break
            }
        }
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            if eq(value, _ZERO_SENTINEL) {
                mstore(0x00, 0xf5a267f1) // `ValueIsZeroSentinel()`.
                revert(0x1c, 0x04)
            }
            if iszero(value) { value := _ZERO_SENTINEL }
            for { let n := sload(not(rootSlot)) } 1 {} {
                if iszero(n) {
                    result := 1
                    if eq(sload(rootSlot), value) {
                        sstore(rootSlot, sload(add(rootSlot, 1)))
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(sload(add(rootSlot, 1)), value) {
                        sstore(add(rootSlot, 1), sload(add(rootSlot, 2)))
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    if eq(sload(add(rootSlot, 2)), value) {
                        sstore(add(rootSlot, 2), 0)
                        break
                    }
                    result := 0
                    break
                }
                mstore(0x20, rootSlot)
                mstore(0x00, value)
                let p := keccak256(0x00, 0x40)
                let position := sload(p)
                if iszero(position) { break }
                n := sub(shr(1, n), 1)
                if iszero(eq(sub(position, 1), n)) {
                    let lastValue := sload(add(rootSlot, n))
                    sstore(add(rootSlot, sub(position, 1)), lastValue)
                    mstore(0x00, lastValue)
                    sstore(keccak256(0x00, 0x40), position)
                }
                sstore(not(rootSlot), or(shl(1, n), 1))
                sstore(p, 0)
                result := 1
                break
            }
        }
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Uint256Set storage set, uint256 value) internal returns (bool result) {
        result = remove(_toBytes32Set(set), bytes32(value));
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Int256Set storage set, int256 value) internal returns (bool result) {
        result = remove(_toBytes32Set(set), bytes32(uint256(value)));
    }

    /// @dev Removes `value` from the set. Returns whether `value` was in the set.
    function remove(Uint8Set storage set, uint8 value) internal returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(set.slot)
            let mask := shl(and(0xff, value), 1)
            sstore(set.slot, and(result, not(mask)))
            result := iszero(iszero(and(result, mask)))
        }
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(AddressSet storage set, address value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(Bytes32Set storage set, bytes32 value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(Uint256Set storage set, uint256 value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(Int256Set storage set, int256 value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Shorthand for `isAdd ? set.add(value, cap) : set.remove(value)`.
    function update(Uint8Set storage set, uint8 value, bool isAdd, uint256 cap)
        internal
        returns (bool)
    {
        return isAdd ? add(set, value, cap) : remove(set, value);
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(AddressSet storage set) internal view returns (address[] memory result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let zs := _ZERO_SENTINEL
            let rootPacked := sload(rootSlot)
            let n := shr(160, shl(160, rootPacked))
            result := mload(0x40)
            let o := add(0x20, result)
            let v := shr(96, rootPacked)
            mstore(o, mul(v, iszero(eq(v, zs))))
            for {} 1 {} {
                if iszero(n) {
                    if v {
                        n := 1
                        v := shr(96, sload(add(rootSlot, n)))
                        if v {
                            n := 2
                            mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
                            v := shr(96, sload(add(rootSlot, n)))
                            if v {
                                n := 3
                                mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
                            }
                        }
                    }
                    break
                }
                n := shr(1, n)
                for { let i := 1 } lt(i, n) { i := add(i, 1) } {
                    v := shr(96, sload(add(rootSlot, i)))
                    mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
                }
                break
            }
            mstore(result, n)
            mstore(0x40, add(o, shl(5, n)))
        }
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            let zs := _ZERO_SENTINEL
            let n := sload(not(rootSlot))
            result := mload(0x40)
            let o := add(0x20, result)
            for {} 1 {} {
                if iszero(n) {
                    let v := sload(rootSlot)
                    if v {
                        n := 1
                        mstore(o, mul(v, iszero(eq(v, zs))))
                        v := sload(add(rootSlot, n))
                        if v {
                            n := 2
                            mstore(add(o, 0x20), mul(v, iszero(eq(v, zs))))
                            v := sload(add(rootSlot, n))
                            if v {
                                n := 3
                                mstore(add(o, 0x40), mul(v, iszero(eq(v, zs))))
                            }
                        }
                    }
                    break
                }
                n := shr(1, n)
                for { let i := 0 } lt(i, n) { i := add(i, 1) } {
                    let v := sload(add(rootSlot, i))
                    mstore(add(o, shl(5, i)), mul(v, iszero(eq(v, zs))))
                }
                break
            }
            mstore(result, n)
            mstore(0x40, add(o, shl(5, n)))
        }
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Uint256Set storage set) internal view returns (uint256[] memory result) {
        result = _toUints(values(_toBytes32Set(set)));
    }

    /// @dev Returns all of the values in the set.
    /// Note: This can consume more gas than the block gas limit for large sets.
    function values(Int256Set storage set) internal view returns (int256[] memory result) {
        result = _toInts(values(_toBytes32Set(set)));
    }

    /// @dev Returns all of the values in the set.
    function values(Uint8Set storage set) internal view returns (uint8[] memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let ptr := add(result, 0x20)
            let o := 0
            for { let packed := sload(set.slot) } packed {} {
                if iszero(and(packed, 0xffff)) {
                    o := add(o, 16)
                    packed := shr(16, packed)
                    continue
                }
                mstore(ptr, o)
                ptr := add(ptr, shl(5, and(packed, 1)))
                o := add(o, 1)
                packed := shr(1, packed)
            }
            mstore(result, shr(5, sub(ptr, add(result, 0x20))))
            mstore(0x40, ptr)
        }
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(AddressSet storage set, uint256 i) internal view returns (address result) {
        bytes32 rootSlot = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            result := shr(96, sload(add(rootSlot, i)))
            result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
        }
        if (i >= length(set)) revert IndexOutOfBounds();
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Bytes32Set storage set, uint256 i) internal view returns (bytes32 result) {
        result = _rootSlot(set);
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(add(result, i))
            result := mul(result, iszero(eq(result, _ZERO_SENTINEL)))
        }
        if (i >= length(set)) revert IndexOutOfBounds();
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Uint256Set storage set, uint256 i) internal view returns (uint256 result) {
        result = uint256(at(_toBytes32Set(set), i));
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Int256Set storage set, uint256 i) internal view returns (int256 result) {
        result = int256(uint256(at(_toBytes32Set(set), i)));
    }

    /// @dev Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds.
    function at(Uint8Set storage set, uint256 i) internal view returns (uint8 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let packed := sload(set.slot)
            for {} 1 {
                mstore(0x00, 0x4e23d035) // `IndexOutOfBounds()`.
                revert(0x1c, 0x04)
            } {
                if iszero(lt(i, 256)) { continue }
                for { let j := 0 } iszero(eq(i, j)) {} {
                    packed := xor(packed, and(packed, add(1, not(packed))))
                    j := add(j, 1)
                }
                if iszero(packed) { continue }
                break
            }
            // Find first set subroutine, optimized for smaller bytecode size.
            let x := and(packed, add(1, not(packed)))
            let r := shl(7, iszero(iszero(shr(128, x))))
            r := or(r, shl(6, iszero(iszero(shr(64, shr(r, x))))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            // For the lower 5 bits of the result, use a De Bruijn lookup.
            // forgefmt: disable-next-item
            result := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),
                0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the root slot.
    function _rootSlot(AddressSet storage s) private pure returns (bytes32 r) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x04, _ENUMERABLE_ADDRESS_SET_SLOT_SEED)
            mstore(0x00, s.slot)
            r := keccak256(0x00, 0x24)
        }
    }

    /// @dev Returns the root slot.
    function _rootSlot(Bytes32Set storage s) private pure returns (bytes32 r) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x04, _ENUMERABLE_WORD_SET_SLOT_SEED)
            mstore(0x00, s.slot)
            r := keccak256(0x00, 0x24)
        }
    }

    /// @dev Casts to a Bytes32Set.
    function _toBytes32Set(Uint256Set storage s) private pure returns (Bytes32Set storage c) {
        /// @solidity memory-safe-assembly
        assembly {
            c.slot := s.slot
        }
    }

    /// @dev Casts to a Bytes32Set.
    function _toBytes32Set(Int256Set storage s) private pure returns (Bytes32Set storage c) {
        /// @solidity memory-safe-assembly
        assembly {
            c.slot := s.slot
        }
    }

    /// @dev Casts to a uint256 array.
    function _toUints(bytes32[] memory a) private pure returns (uint256[] memory c) {
        /// @solidity memory-safe-assembly
        assembly {
            c := a
        }
    }

    /// @dev Casts to a int256 array.
    function _toInts(bytes32[] memory a) private pure returns (int256[] memory c) {
        /// @solidity memory-safe-assembly
        assembly {
            c := a
        }
    }
}

File 11 of 12 : FixedPointMathLib.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
library FixedPointMathLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The operation failed, as the output exceeds the maximum value of uint256.
    error ExpOverflow();

    /// @dev The operation failed, as the output exceeds the maximum value of uint256.
    error FactorialOverflow();

    /// @dev The operation failed, due to an overflow.
    error RPowOverflow();

    /// @dev The mantissa is too big to fit.
    error MantissaOverflow();

    /// @dev The operation failed, due to an multiplication overflow.
    error MulWadFailed();

    /// @dev The operation failed, due to an multiplication overflow.
    error SMulWadFailed();

    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.
    error DivWadFailed();

    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.
    error SDivWadFailed();

    /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero.
    error MulDivFailed();

    /// @dev The division failed, as the denominator is zero.
    error DivFailed();

    /// @dev The full precision multiply-divide operation failed, either due
    /// to the result being larger than 256 bits, or a division by a zero.
    error FullMulDivFailed();

    /// @dev The output is undefined, as the input is less-than-or-equal to zero.
    error LnWadUndefined();

    /// @dev The input outside the acceptable domain.
    error OutOfDomain();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

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

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*              SIMPLIFIED FIXED POINT OPERATIONS             */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `(x * y) / WAD` rounded down.
    function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
            if gt(x, div(not(0), y)) {
                if y {
                    mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            z := div(mul(x, y), WAD)
        }
    }

    /// @dev Equivalent to `(x * y) / WAD` rounded down.
    function sMulWad(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(x, y)
            // Equivalent to `require((x == 0 || z / x == y) && !(x == -1 && y == type(int256).min))`.
            if iszero(gt(or(iszero(x), eq(sdiv(z, x), y)), lt(not(x), eq(y, shl(255, 1))))) {
                mstore(0x00, 0xedcd4dd4) // `SMulWadFailed()`.
                revert(0x1c, 0x04)
            }
            z := sdiv(z, WAD)
        }
    }

    /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks.
    function rawMulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := div(mul(x, y), WAD)
        }
    }

    /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks.
    function rawSMulWad(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := sdiv(mul(x, y), WAD)
        }
    }

    /// @dev Equivalent to `(x * y) / WAD` rounded up.
    function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(x, y)
            // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
            if iszero(eq(div(z, y), x)) {
                if y {
                    mstore(0x00, 0xbac65e5b) // `MulWadFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            z := add(iszero(iszero(mod(z, WAD))), div(z, WAD))
        }
    }

    /// @dev Equivalent to `(x * y) / WAD` rounded up, but without overflow checks.
    function rawMulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded down.
    function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y != 0 && x <= type(uint256).max / WAD)`.
            if iszero(mul(y, lt(x, add(1, div(not(0), WAD))))) {
                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.
                revert(0x1c, 0x04)
            }
            z := div(mul(x, WAD), y)
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded down.
    function sDivWad(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(x, WAD)
            // Equivalent to `require(y != 0 && ((x * WAD) / WAD == x))`.
            if iszero(mul(y, eq(sdiv(z, WAD), x))) {
                mstore(0x00, 0x5c43740d) // `SDivWadFailed()`.
                revert(0x1c, 0x04)
            }
            z := sdiv(z, y)
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks.
    function rawDivWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := div(mul(x, WAD), y)
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks.
    function rawSDivWad(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := sdiv(mul(x, WAD), y)
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded up.
    function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `require(y != 0 && x <= type(uint256).max / WAD)`.
            if iszero(mul(y, lt(x, add(1, div(not(0), WAD))))) {
                mstore(0x00, 0x7c5f487d) // `DivWadFailed()`.
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))
        }
    }

    /// @dev Equivalent to `(x * WAD) / y` rounded up, but without overflow and divide by zero checks.
    function rawDivWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y))
        }
    }

    /// @dev Equivalent to `x` to the power of `y`.
    /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`.
    /// Note: This function is an approximation.
    function powWad(int256 x, int256 y) internal pure returns (int256) {
        // Using `ln(x)` means `x` must be greater than 0.
        return expWad((lnWad(x) * y) / int256(WAD));
    }

    /// @dev Returns `exp(x)`, denominated in `WAD`.
    /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln
    /// Note: This function is an approximation. Monotonically increasing.
    function expWad(int256 x) internal pure returns (int256 r) {
        unchecked {
            // When the result is less than 0.5 we return zero.
            // This happens when `x <= (log(1e-18) * 1e18) ~ -4.15e19`.
            if (x <= -41446531673892822313) return r;

            /// @solidity memory-safe-assembly
            assembly {
                // When the result is greater than `(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 iszero(slt(x, 135305999368893231589)) {
                    mstore(0x00, 0xa37bfec9) // `ExpOverflow()`.
                    revert(0x1c, 0x04)
                }
            }

            // `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)
            );
        }
    }

    /// @dev Returns `ln(x)`, denominated in `WAD`.
    /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln
    /// Note: This function is an approximation. Monotonically increasing.
    function lnWad(int256 x) internal pure returns (int256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // 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.

            // Compute `k = log2(x) - 96`, `r = 159 - k = 255 - log2(x) = 255 ^ log2(x)`.
            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))))
            // We place the check here for more optimal stack operations.
            if iszero(sgt(x, 0)) {
                mstore(0x00, 0x1615e638) // `LnWadUndefined()`.
                revert(0x1c, 0x04)
            }
            // forgefmt: disable-next-item
            r := xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff))

            // Reduce range of x to (1, 2) * 2**96
            // ln(2^k * x) = k * ln(2) + ln(x)
            x := shr(159, shl(r, x))

            // Evaluate using a (8, 8)-term rational approximation.
            // `p` is made monic, we will multiply by a scale factor later.
            // forgefmt: disable-next-item
            let p := sub( // This heavily nested expression is to avoid stack-too-deep for via-ir.
                sar(96, mul(add(43456485725739037958740375743393,
                sar(96, mul(add(24828157081833163892658089445524,
                sar(96, mul(add(3273285459638523848632254066296,
                    x), x))), x))), x)), 11111509109440967052023855526967)
            p := sub(sar(96, mul(p, x)), 45023709667254063763336534515857)
            p := sub(sar(96, mul(p, x)), 14706773417378608786704636184526)
            p := sub(mul(p, x), shl(96, 795164235651350426258249787498))
            // 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.
            let q := add(5573035233440673466300451813936, x)
            q := add(71694874799317883764090561454958, sar(96, mul(x, q)))
            q := add(283447036172924575727196451306956, sar(96, mul(x, q)))
            q := add(401686690394027663651624208769553, sar(96, mul(x, q)))
            q := add(204048457590392012362485061816622, sar(96, mul(x, q)))
            q := add(31853899698501571402653359427138, sar(96, mul(x, q)))
            q := add(909429971244387300277376558375, sar(96, mul(x, q)))

            // `p / q` 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`.

            // The q polynomial is known not to have zeros in the domain.
            // No scaling required because p is already `2**96` too large.
            p := sdiv(p, q)
            // Multiply by the scaling factor: `s * 5**18 * 2**96`, base is now `5**18 * 2**192`.
            p := mul(1677202110996718588342820967067443963516166, p)
            // Add `ln(2) * k * 5**18 * 2**192`.
            // forgefmt: disable-next-item
            p := add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, r)), p)
            // Add `ln(2**96 / 10**18) * 5**18 * 2**192`.
            p := add(600920179829731861736702779321621459595472258049074101567377883020018308, p)
            // Base conversion: mul `2**18 / 2**192`.
            r := sar(174, p)
        }
    }

    /// @dev Returns `W_0(x)`, denominated in `WAD`.
    /// See: https://en.wikipedia.org/wiki/Lambert_W_function
    /// a.k.a. Product log function. This is an approximation of the principal branch.
    /// Note: This function is an approximation. Monotonically increasing.
    function lambertW0Wad(int256 x) internal pure returns (int256 w) {
        // forgefmt: disable-next-item
        unchecked {
            if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`.
            (int256 wad, int256 p) = (int256(WAD), x);
            uint256 c; // Whether we need to avoid catastrophic cancellation.
            uint256 i = 4; // Number of iterations.
            if (w <= 0x1ffffffffffff) {
                if (-0x4000000000000 <= w) {
                    i = 1; // Inputs near zero only take one step to converge.
                } else if (w <= -0x3ffffffffffffff) {
                    i = 32; // Inputs near `-1/e` take very long to converge.
                }
            } else if (uint256(w >> 63) == uint256(0)) {
                /// @solidity memory-safe-assembly
                assembly {
                    // Inline log2 for more performance, since the range is small.
                    let v := shr(49, w)
                    let l := shl(3, lt(0xff, v))
                    l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)),
                        0x0706060506020504060203020504030106050205030304010505030400000000)), 49)
                    w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13))
                    c := gt(l, 60)
                    i := add(2, add(gt(l, 53), c))
                }
            } else {
                int256 ll = lnWad(w = lnWad(w));
                /// @solidity memory-safe-assembly
                assembly {
                    // `w = ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`.
                    w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll))
                    i := add(3, iszero(shr(68, x)))
                    c := iszero(shr(143, x))
                }
                if (c == uint256(0)) {
                    do { // If `x` is big, use Newton's so that intermediate values won't overflow.
                        int256 e = expWad(w);
                        /// @solidity memory-safe-assembly
                        assembly {
                            let t := mul(w, div(e, wad))
                            w := sub(w, sdiv(sub(t, x), div(add(e, t), wad)))
                        }
                        if (p <= w) break;
                        p = w;
                    } while (--i != uint256(0));
                    /// @solidity memory-safe-assembly
                    assembly {
                        w := sub(w, sgt(w, 2))
                    }
                    return w;
                }
            }
            do { // Otherwise, use Halley's for faster convergence.
                int256 e = expWad(w);
                /// @solidity memory-safe-assembly
                assembly {
                    let t := add(w, wad)
                    let s := sub(mul(w, e), mul(x, wad))
                    w := sub(w, sdiv(mul(s, wad), sub(mul(e, t), sdiv(mul(add(t, wad), s), add(t, t)))))
                }
                if (p <= w) break;
                p = w;
            } while (--i != c);
            /// @solidity memory-safe-assembly
            assembly {
                w := sub(w, sgt(w, 2))
            }
            // For certain ranges of `x`, we'll use the quadratic-rate recursive formula of
            // R. Iacono and J.P. Boyd for the last iteration, to avoid catastrophic cancellation.
            if (c == uint256(0)) return w;
            int256 t = w | 1;
            /// @solidity memory-safe-assembly
            assembly {
                x := sdiv(mul(x, wad), t)
            }
            x = (t * (wad + lnWad(x)));
            /// @solidity memory-safe-assembly
            assembly {
                w := sdiv(x, add(wad, t))
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  GENERAL NUMBER UTILITIES                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `a * b == x * y`, with full precision.
    function fullMulEq(uint256 a, uint256 b, uint256 x, uint256 y)
        internal
        pure
        returns (bool result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(eq(mul(a, b), mul(x, y)), eq(mulmod(x, y, not(0)), mulmod(a, b, not(0))))
        }
    }

    /// @dev Calculates `floor(x * y / d)` with full precision.
    /// Throws if result overflows a uint256 or when `d` is zero.
    /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv
    function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // 512-bit multiply `[p1 p0] = x * y`.
            // Compute the product mod `2**256` and mod `2**256 - 1`
            // then use the Chinese Remainder Theorem to reconstruct
            // the 512 bit result. The result is stored in two 256
            // variables such that `product = p1 * 2**256 + p0`.

            // Temporarily use `z` as `p0` to save gas.
            z := mul(x, y) // Lower 256 bits of `x * y`.
            for {} 1 {} {
                // If overflows.
                if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) {
                    let mm := mulmod(x, y, not(0))
                    let p1 := sub(mm, add(z, lt(mm, z))) // Upper 256 bits of `x * y`.

                    /*------------------- 512 by 256 division --------------------*/

                    // Make division exact by subtracting the remainder from `[p1 p0]`.
                    let r := mulmod(x, y, d) // Compute remainder using mulmod.
                    let t := and(d, sub(0, d)) // The least significant bit of `d`. `t >= 1`.
                    // Make sure `z` is less than `2**256`. Also prevents `d == 0`.
                    // Placing the check here seems to give more optimal stack operations.
                    if iszero(gt(d, p1)) {
                        mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
                        revert(0x1c, 0x04)
                    }
                    d := div(d, t) // Divide `d` by `t`, which is a power of two.
                    // Invert `d mod 2**256`
                    // Now that `d` is an odd number, it has an inverse
                    // modulo `2**256` such that `d * inv = 1 mod 2**256`.
                    // Compute the inverse by starting with a seed that is correct
                    // correct for four bits. That is, `d * inv = 1 mod 2**4`.
                    let inv := xor(2, mul(3, d))
                    // Now use Newton-Raphson iteration to improve the precision.
                    // Thanks to Hensel's lifting lemma, this also works in modular
                    // arithmetic, doubling the correct bits in each step.
                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8
                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16
                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32
                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64
                    inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128
                    z :=
                        mul(
                            // Divide [p1 p0] by the factors of two.
                            // Shift in bits from `p1` into `p0`. For this we need
                            // to flip `t` such that it is `2**256 / t`.
                            or(mul(sub(p1, gt(r, z)), add(div(sub(0, t), t), 1)), div(sub(z, r), t)),
                            mul(sub(2, mul(d, inv)), inv) // inverse mod 2**256
                        )
                    break
                }
                z := div(z, d)
                break
            }
        }
    }

    /// @dev Calculates `floor(x * y / d)` with full precision.
    /// Behavior is undefined if `d` is zero or the final result cannot fit in 256 bits.
    /// Performs the full 512 bit calculation regardless.
    function fullMulDivUnchecked(uint256 x, uint256 y, uint256 d)
        internal
        pure
        returns (uint256 z)
    {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(x, y)
            let mm := mulmod(x, y, not(0))
            let p1 := sub(mm, add(z, lt(mm, z)))
            let t := and(d, sub(0, d))
            let r := mulmod(x, y, d)
            d := div(d, t)
            let inv := xor(2, mul(3, d))
            inv := mul(inv, sub(2, mul(d, inv)))
            inv := mul(inv, sub(2, mul(d, inv)))
            inv := mul(inv, sub(2, mul(d, inv)))
            inv := mul(inv, sub(2, mul(d, inv)))
            inv := mul(inv, sub(2, mul(d, inv)))
            z :=
                mul(
                    or(mul(sub(p1, gt(r, z)), add(div(sub(0, t), t), 1)), div(sub(z, r), t)),
                    mul(sub(2, mul(d, inv)), inv)
                )
        }
    }

    /// @dev Calculates `floor(x * y / d)` with full precision, rounded up.
    /// Throws if result overflows a uint256 or when `d` is zero.
    /// Credit to Uniswap-v3-core under MIT license:
    /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/FullMath.sol
    function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        z = fullMulDiv(x, y, d);
        /// @solidity memory-safe-assembly
        assembly {
            if mulmod(x, y, d) {
                z := add(z, 1)
                if iszero(z) {
                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
                    revert(0x1c, 0x04)
                }
            }
        }
    }

    /// @dev Calculates `floor(x * y / 2 ** n)` with full precision.
    /// Throws if result overflows a uint256.
    /// Credit to Philogy under MIT license:
    /// https://github.com/SorellaLabs/angstrom/blob/main/contracts/src/libraries/X128MathLib.sol
    function fullMulDivN(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // Temporarily use `z` as `p0` to save gas.
            z := mul(x, y) // Lower 256 bits of `x * y`. We'll call this `z`.
            for {} 1 {} {
                if iszero(or(iszero(x), eq(div(z, x), y))) {
                    let k := and(n, 0xff) // `n`, cleaned.
                    let mm := mulmod(x, y, not(0))
                    let p1 := sub(mm, add(z, lt(mm, z))) // Upper 256 bits of `x * y`.
                    //         |      p1     |      z     |
                    // Before: | p1_0 ¦ p1_1 | z_0  ¦ z_1 |
                    // Final:  |   0  ¦ p1_0 | p1_1 ¦ z_0 |
                    // Check that final `z` doesn't overflow by checking that p1_0 = 0.
                    if iszero(shr(k, p1)) {
                        z := add(shl(sub(256, k), p1), shr(k, z))
                        break
                    }
                    mstore(0x00, 0xae47f702) // `FullMulDivFailed()`.
                    revert(0x1c, 0x04)
                }
                z := shr(and(n, 0xff), z)
                break
            }
        }
    }

    /// @dev Returns `floor(x * y / d)`.
    /// Reverts if `x * y` overflows, or `d` is zero.
    function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(x, y)
            // Equivalent to `require(d != 0 && (y == 0 || x <= type(uint256).max / y))`.
            if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) {
                mstore(0x00, 0xad251c27) // `MulDivFailed()`.
                revert(0x1c, 0x04)
            }
            z := div(z, d)
        }
    }

    /// @dev Returns `ceil(x * y / d)`.
    /// Reverts if `x * y` overflows, or `d` is zero.
    function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(x, y)
            // Equivalent to `require(d != 0 && (y == 0 || x <= type(uint256).max / y))`.
            if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) {
                mstore(0x00, 0xad251c27) // `MulDivFailed()`.
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(z, d))), div(z, d))
        }
    }

    /// @dev Returns `x`, the modular multiplicative inverse of `a`, such that `(a * x) % n == 1`.
    function invMod(uint256 a, uint256 n) internal pure returns (uint256 x) {
        /// @solidity memory-safe-assembly
        assembly {
            let g := n
            let r := mod(a, n)
            for { let y := 1 } 1 {} {
                let q := div(g, r)
                let t := g
                g := r
                r := sub(t, mul(r, q))
                let u := x
                x := y
                y := sub(u, mul(y, q))
                if iszero(r) { break }
            }
            x := mul(eq(g, 1), add(x, mul(slt(x, 0), n)))
        }
    }

    /// @dev Returns `ceil(x / d)`.
    /// Reverts if `d` is zero.
    function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(d) {
                mstore(0x00, 0x65244e4e) // `DivFailed()`.
                revert(0x1c, 0x04)
            }
            z := add(iszero(iszero(mod(x, d))), div(x, d))
        }
    }

    /// @dev Returns `max(0, x - y)`. Alias for `saturatingSub`.
    function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(gt(x, y), sub(x, y))
        }
    }

    /// @dev Returns `max(0, x - y)`.
    function saturatingSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(gt(x, y), sub(x, y))
        }
    }

    /// @dev Returns `min(2 ** 256 - 1, x + y)`.
    function saturatingAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(sub(0, lt(add(x, y), x)), add(x, y))
        }
    }

    /// @dev Returns `min(2 ** 256 - 1, x * y)`.
    function saturatingMul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(sub(or(iszero(x), eq(div(mul(x, y), x), y)), 1), mul(x, y))
        }
    }

    /// @dev Returns `condition ? x : y`, without branching.
    function ternary(bool condition, uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), iszero(condition)))
        }
    }

    /// @dev Returns `condition ? x : y`, without branching.
    function ternary(bool condition, bytes32 x, bytes32 y) internal pure returns (bytes32 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), iszero(condition)))
        }
    }

    /// @dev Returns `condition ? x : y`, without branching.
    function ternary(bool condition, address x, address y) internal pure returns (address z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), iszero(condition)))
        }
    }

    /// @dev Returns `x != 0 ? x : y`, without branching.
    function coalesce(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(x, mul(y, iszero(x)))
        }
    }

    /// @dev Returns `x != bytes32(0) ? x : y`, without branching.
    function coalesce(bytes32 x, bytes32 y) internal pure returns (bytes32 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(x, mul(y, iszero(x)))
        }
    }

    /// @dev Returns `x != address(0) ? x : y`, without branching.
    function coalesce(address x, address y) internal pure returns (address z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(x, mul(y, iszero(shl(96, x))))
        }
    }

    /// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`.
    /// Reverts if the computation overflows.
    function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mul(b, iszero(y)) // `0 ** 0 = 1`. Otherwise, `0 ** n = 0`.
            if x {
                z := xor(b, mul(xor(b, x), and(y, 1))) // `z = isEven(y) ? scale : x`
                let half := shr(1, b) // Divide `b` by 2.
                // Divide `y` by 2 every iteration.
                for { y := shr(1, y) } y { y := shr(1, y) } {
                    let xx := mul(x, x) // Store x squared.
                    let xxRound := add(xx, half) // Round to the nearest number.
                    // Revert if `xx + half` overflowed, or if `x ** 2` overflows.
                    if or(lt(xxRound, xx), shr(128, x)) {
                        mstore(0x00, 0x49f7642b) // `RPowOverflow()`.
                        revert(0x1c, 0x04)
                    }
                    x := div(xxRound, b) // Set `x` to scaled `xxRound`.
                    // If `y` is odd:
                    if and(y, 1) {
                        let zx := mul(z, x) // Compute `z * x`.
                        let zxRound := add(zx, half) // Round to the nearest number.
                        // If `z * x` overflowed or `zx + half` overflowed:
                        if or(xor(div(zx, x), z), lt(zxRound, zx)) {
                            // Revert if `x` is non-zero.
                            if x {
                                mstore(0x00, 0x49f7642b) // `RPowOverflow()`.
                                revert(0x1c, 0x04)
                            }
                        }
                        z := div(zxRound, b) // Return properly scaled `zxRound`.
                    }
                }
            }
        }
    }

    /// @dev Returns the square root of `x`, rounded down.
    function sqrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`.
            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.

            // Let `y = x / 2**r`. We check `y >= 2**(k + 8)`
            // but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`.
            let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffffff, shr(r, x))))
            z := shl(shr(1, r), 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(shr(r, x), 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
            z := sub(z, lt(div(x, z), z))
        }
    }

    /// @dev Returns the cube root of `x`, rounded down.
    /// Credit to bout3fiddy and pcaversaccio under AGPLv3 license:
    /// https://github.com/pcaversaccio/snekmate/blob/main/src/snekmate/utils/math.vy
    /// Formally verified by xuwinnie:
    /// https://github.com/vectorized/solady/blob/main/audits/xuwinnie-solady-cbrt-proof.pdf
    function cbrt(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            let 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))))
            // Makeshift lookup table to nudge the approximate log2 result.
            z := div(shl(div(r, 3), shl(lt(0xf, shr(r, x)), 0xf)), xor(7, mod(r, 3)))
            // Newton-Raphson's.
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            z := div(add(add(div(x, mul(z, z)), z), z), 3)
            // Round down.
            z := sub(z, lt(div(x, mul(z, z)), z))
        }
    }

    /// @dev Returns the square root of `x`, denominated in `WAD`, rounded down.
    function sqrtWad(uint256 x) internal pure returns (uint256 z) {
        unchecked {
            if (x <= type(uint256).max / 10 ** 18) return sqrt(x * 10 ** 18);
            z = (1 + sqrt(x)) * 10 ** 9;
            z = (fullMulDivUnchecked(x, 10 ** 18, z) + z) >> 1;
        }
        /// @solidity memory-safe-assembly
        assembly {
            z := sub(z, gt(999999999999999999, sub(mulmod(z, z, x), 1))) // Round down.
        }
    }

    /// @dev Returns the cube root of `x`, denominated in `WAD`, rounded down.
    /// Formally verified by xuwinnie:
    /// https://github.com/vectorized/solady/blob/main/audits/xuwinnie-solady-cbrt-proof.pdf
    function cbrtWad(uint256 x) internal pure returns (uint256 z) {
        unchecked {
            if (x <= type(uint256).max / 10 ** 36) return cbrt(x * 10 ** 36);
            z = (1 + cbrt(x)) * 10 ** 12;
            z = (fullMulDivUnchecked(x, 10 ** 36, z * z) + z + z) / 3;
        }
        /// @solidity memory-safe-assembly
        assembly {
            let p := x
            for {} 1 {} {
                if iszero(shr(229, p)) {
                    if iszero(shr(199, p)) {
                        p := mul(p, 100000000000000000) // 10 ** 17.
                        break
                    }
                    p := mul(p, 100000000) // 10 ** 8.
                    break
                }
                if iszero(shr(249, p)) { p := mul(p, 100) }
                break
            }
            let t := mulmod(mul(z, z), z, p)
            z := sub(z, gt(lt(t, shr(1, p)), iszero(t))) // Round down.
        }
    }

    /// @dev Returns the factorial of `x`.
    function factorial(uint256 x) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := 1
            if iszero(lt(x, 58)) {
                mstore(0x00, 0xaba0f2a2) // `FactorialOverflow()`.
                revert(0x1c, 0x04)
            }
            for {} x { x := sub(x, 1) } { z := mul(z, x) }
        }
    }

    /// @dev Returns the log2 of `x`.
    /// Equivalent to computing the index of the most significant bit (MSB) of `x`.
    /// Returns 0 if `x` is zero.
    function log2(uint256 x) internal pure returns (uint256 r) {
        /// @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))))
            // forgefmt: disable-next-item
            r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0x0706060506020504060203020504030106050205030304010505030400000000))
        }
    }

    /// @dev Returns the log2 of `x`, rounded up.
    /// Returns 0 if `x` is zero.
    function log2Up(uint256 x) internal pure returns (uint256 r) {
        r = log2(x);
        /// @solidity memory-safe-assembly
        assembly {
            r := add(r, lt(shl(r, 1), x))
        }
    }

    /// @dev Returns the log10 of `x`.
    /// Returns 0 if `x` is zero.
    function log10(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(lt(x, 100000000000000000000000000000000000000)) {
                x := div(x, 100000000000000000000000000000000000000)
                r := 38
            }
            if iszero(lt(x, 100000000000000000000)) {
                x := div(x, 100000000000000000000)
                r := add(r, 20)
            }
            if iszero(lt(x, 10000000000)) {
                x := div(x, 10000000000)
                r := add(r, 10)
            }
            if iszero(lt(x, 100000)) {
                x := div(x, 100000)
                r := add(r, 5)
            }
            r := add(r, add(gt(x, 9), add(gt(x, 99), add(gt(x, 999), gt(x, 9999)))))
        }
    }

    /// @dev Returns the log10 of `x`, rounded up.
    /// Returns 0 if `x` is zero.
    function log10Up(uint256 x) internal pure returns (uint256 r) {
        r = log10(x);
        /// @solidity memory-safe-assembly
        assembly {
            r := add(r, lt(exp(10, r), x))
        }
    }

    /// @dev Returns the log256 of `x`.
    /// Returns 0 if `x` is zero.
    function log256(uint256 x) internal pure returns (uint256 r) {
        /// @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(shr(3, r), lt(0xff, shr(r, x)))
        }
    }

    /// @dev Returns the log256 of `x`, rounded up.
    /// Returns 0 if `x` is zero.
    function log256Up(uint256 x) internal pure returns (uint256 r) {
        r = log256(x);
        /// @solidity memory-safe-assembly
        assembly {
            r := add(r, lt(shl(shl(3, r), 1), x))
        }
    }

    /// @dev Returns the scientific notation format `mantissa * 10 ** exponent` of `x`.
    /// Useful for compressing prices (e.g. using 25 bit mantissa and 7 bit exponent).
    function sci(uint256 x) internal pure returns (uint256 mantissa, uint256 exponent) {
        /// @solidity memory-safe-assembly
        assembly {
            mantissa := x
            if mantissa {
                if iszero(mod(mantissa, 1000000000000000000000000000000000)) {
                    mantissa := div(mantissa, 1000000000000000000000000000000000)
                    exponent := 33
                }
                if iszero(mod(mantissa, 10000000000000000000)) {
                    mantissa := div(mantissa, 10000000000000000000)
                    exponent := add(exponent, 19)
                }
                if iszero(mod(mantissa, 1000000000000)) {
                    mantissa := div(mantissa, 1000000000000)
                    exponent := add(exponent, 12)
                }
                if iszero(mod(mantissa, 1000000)) {
                    mantissa := div(mantissa, 1000000)
                    exponent := add(exponent, 6)
                }
                if iszero(mod(mantissa, 10000)) {
                    mantissa := div(mantissa, 10000)
                    exponent := add(exponent, 4)
                }
                if iszero(mod(mantissa, 100)) {
                    mantissa := div(mantissa, 100)
                    exponent := add(exponent, 2)
                }
                if iszero(mod(mantissa, 10)) {
                    mantissa := div(mantissa, 10)
                    exponent := add(exponent, 1)
                }
            }
        }
    }

    /// @dev Convenience function for packing `x` into a smaller number using `sci`.
    /// The `mantissa` will be in bits [7..255] (the upper 249 bits).
    /// The `exponent` will be in bits [0..6] (the lower 7 bits).
    /// Use `SafeCastLib` to safely ensure that the `packed` number is small
    /// enough to fit in the desired unsigned integer type:
    /// ```
    ///     uint32 packed = SafeCastLib.toUint32(FixedPointMathLib.packSci(777 ether));
    /// ```
    function packSci(uint256 x) internal pure returns (uint256 packed) {
        (x, packed) = sci(x); // Reuse for `mantissa` and `exponent`.
        /// @solidity memory-safe-assembly
        assembly {
            if shr(249, x) {
                mstore(0x00, 0xce30380c) // `MantissaOverflow()`.
                revert(0x1c, 0x04)
            }
            packed := or(shl(7, x), packed)
        }
    }

    /// @dev Convenience function for unpacking a packed number from `packSci`.
    function unpackSci(uint256 packed) internal pure returns (uint256 unpacked) {
        unchecked {
            unpacked = (packed >> 7) * 10 ** (packed & 0x7f);
        }
    }

    /// @dev Returns the average of `x` and `y`. Rounds towards zero.
    function avg(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = (x & y) + ((x ^ y) >> 1);
        }
    }

    /// @dev Returns the average of `x` and `y`. Rounds towards negative infinity.
    function avg(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = (x >> 1) + (y >> 1) + (x & y & 1);
        }
    }

    /// @dev Returns the absolute value of `x`.
    function abs(int256 x) internal pure returns (uint256 z) {
        unchecked {
            z = (uint256(x) + uint256(x >> 255)) ^ uint256(x >> 255);
        }
    }

    /// @dev Returns the absolute distance between `x` and `y`.
    function dist(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := add(xor(sub(0, gt(x, y)), sub(y, x)), gt(x, y))
        }
    }

    /// @dev Returns the absolute distance between `x` and `y`.
    function dist(int256 x, int256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := add(xor(sub(0, sgt(x, y)), sub(y, x)), sgt(x, y))
        }
    }

    /// @dev Returns the minimum of `x` and `y`.
    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), lt(y, x)))
        }
    }

    /// @dev Returns the minimum of `x` and `y`.
    function min(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), slt(y, x)))
        }
    }

    /// @dev Returns the maximum of `x` and `y`.
    function max(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), gt(y, x)))
        }
    }

    /// @dev Returns the maximum of `x` and `y`.
    function max(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, y), sgt(y, x)))
        }
    }

    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.
    function clamp(uint256 x, uint256 minValue, uint256 maxValue)
        internal
        pure
        returns (uint256 z)
    {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, minValue), gt(minValue, x)))
            z := xor(z, mul(xor(z, maxValue), lt(maxValue, z)))
        }
    }

    /// @dev Returns `x`, bounded to `minValue` and `maxValue`.
    function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := xor(x, mul(xor(x, minValue), sgt(minValue, x)))
            z := xor(z, mul(xor(z, maxValue), slt(maxValue, z)))
        }
    }

    /// @dev Returns greatest common divisor of `x` and `y`.
    function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            for { z := x } y {} {
                let t := y
                y := mod(z, y)
                z := t
            }
        }
    }

    /// @dev Returns `a + (b - a) * (t - begin) / (end - begin)`,
    /// with `t` clamped between `begin` and `end` (inclusive).
    /// Agnostic to the order of (`a`, `b`) and (`end`, `begin`).
    /// If `begins == end`, returns `t <= begin ? a : b`.
    function lerp(uint256 a, uint256 b, uint256 t, uint256 begin, uint256 end)
        internal
        pure
        returns (uint256)
    {
        if (begin > end) (t, begin, end) = (~t, ~begin, ~end);
        if (t <= begin) return a;
        if (t >= end) return b;
        unchecked {
            if (b >= a) return a + fullMulDiv(b - a, t - begin, end - begin);
            return a - fullMulDiv(a - b, t - begin, end - begin);
        }
    }

    /// @dev Returns `a + (b - a) * (t - begin) / (end - begin)`.
    /// with `t` clamped between `begin` and `end` (inclusive).
    /// Agnostic to the order of (`a`, `b`) and (`end`, `begin`).
    /// If `begins == end`, returns `t <= begin ? a : b`.
    function lerp(int256 a, int256 b, int256 t, int256 begin, int256 end)
        internal
        pure
        returns (int256)
    {
        if (begin > end) (t, begin, end) = (~t, ~begin, ~end);
        if (t <= begin) return a;
        if (t >= end) return b;
        // forgefmt: disable-next-item
        unchecked {
            if (b >= a) return int256(uint256(a) + fullMulDiv(uint256(b - a),
                uint256(t - begin), uint256(end - begin)));
            return int256(uint256(a) - fullMulDiv(uint256(a - b),
                uint256(t - begin), uint256(end - begin)));
        }
    }

    /// @dev Returns if `x` is an even number. Some people may need this.
    function isEven(uint256 x) internal pure returns (bool) {
        return x & uint256(1) == uint256(0);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   RAW NUMBER OPERATIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `x + y`, without checking for overflow.
    function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x + y;
        }
    }

    /// @dev Returns `x + y`, without checking for overflow.
    function rawAdd(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x + y;
        }
    }

    /// @dev Returns `x - y`, without checking for underflow.
    function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x - y;
        }
    }

    /// @dev Returns `x - y`, without checking for underflow.
    function rawSub(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x - y;
        }
    }

    /// @dev Returns `x * y`, without checking for overflow.
    function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        unchecked {
            z = x * y;
        }
    }

    /// @dev Returns `x * y`, without checking for overflow.
    function rawMul(int256 x, int256 y) internal pure returns (int256 z) {
        unchecked {
            z = x * y;
        }
    }

    /// @dev Returns `x / y`, returning 0 if `y` is zero.
    function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := div(x, y)
        }
    }

    /// @dev Returns `x / y`, returning 0 if `y` is zero.
    function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := sdiv(x, y)
        }
    }

    /// @dev Returns `x % y`, returning 0 if `y` is zero.
    function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mod(x, y)
        }
    }

    /// @dev Returns `x % y`, returning 0 if `y` is zero.
    function rawSMod(int256 x, int256 y) internal pure returns (int256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := smod(x, y)
        }
    }

    /// @dev Returns `(x + y) % d`, return 0 if `d` if zero.
    function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := addmod(x, y, d)
        }
    }

    /// @dev Returns `(x * y) % d`, return 0 if `d` if zero.
    function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := mulmod(x, y, d)
        }
    }
}

File 12 of 12 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

Settings
{
  "evmVersion": "paris",
  "optimizer": {
    "enabled": true,
    "mode": "3"
  },
  "outputSelection": {
    "*": {
      "*": [
        "abi"
      ]
    }
  },
  "detectMissingLibraries": false,
  "forceEVMLA": false,
  "enableEraVMExtensions": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyAtMaxFacility","type":"error"},{"inputs":[],"name":"AlreadyPurchasedInitialFactory","type":"error"},{"inputs":[],"name":"CantBuyNewFacilityYet","type":"error"},{"inputs":[],"name":"CantModifyStarterFacility","type":"error"},{"inputs":[],"name":"CantModifyStarterMiner","type":"error"},{"inputs":[],"name":"FacilityInadequatePowerOutput","type":"error"},{"inputs":[],"name":"GreatDepression","type":"error"},{"inputs":[],"name":"IncorrectValue","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidFacilityIndex","type":"error"},{"inputs":[],"name":"InvalidFee","type":"error"},{"inputs":[],"name":"InvalidMinerIndex","type":"error"},{"inputs":[],"name":"InvalidPowerOutput","type":"error"},{"inputs":[],"name":"InvalidReferrer","type":"error"},{"inputs":[],"name":"MinerNotInProduction","type":"error"},{"inputs":[],"name":"MiningHasntStarted","type":"error"},{"inputs":[],"name":"NeedToInitializeFacility","type":"error"},{"inputs":[],"name":"NewFacilityNotInProduction","type":"error"},{"inputs":[],"name":"NoRewardsPending","type":"error"},{"inputs":[],"name":"NonExistentFacility","type":"error"},{"inputs":[],"name":"NonExistentMiner","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PlayerDoesNotOwnMiner","type":"error"},{"inputs":[],"name":"StarterMinerAlreadyAcquired","type":"error"},{"inputs":[],"name":"TooPoor","type":"error"},{"inputs":[],"name":"UpgradeFacilityDisabled","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":true,"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"}],"name":"FacilityBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"FacilityCostChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inProduction","type":"bool"}],"name":"FacilityProductionToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"}],"name":"InitialFacilityPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minerId","type":"uint256"}],"name":"MinerBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"MinerCostChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPowerConsumption","type":"uint256"}],"name":"MinerPowerConsumptionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inProduction","type":"bool"}],"name":"MinerProductionToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"MinerSecondaryMarketAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secondHandPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minerId","type":"uint256"}],"name":"MinerSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"}],"name":"MiningStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPowerOutput","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inProduction","type":"bool"}],"name":"NewFacilityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"hashRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inProduction","type":"bool"}],"name":"NewMinerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"playerHashrate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"playerPendingRewards","type":"uint256"}],"name":"PlayerHashrateDecreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"playerHashrate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"playerPendingRewards","type":"uint256"}],"name":"PlayerHashrateIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"inputs":[],"name":"HALVING_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_MINETENDO_PER_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STARTER_FACILITY_INDEX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STARTER_MINER_INDEX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SWAP_ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"acquiredStarterMiner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxMiners","type":"uint256"},{"internalType":"uint256","name":"totalPowerOutput","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"addFacility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"addMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"addSecondaryMarketForMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blocksUntilNextHalving","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnPct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"}],"name":"buyMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"changeFacilityCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"changeMinerCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"newPowerConsumption","type":"uint256"}],"name":"changeMinerPowerConsumption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cumulativeMinetendoPerHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableUpgradeFacility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"facilities","outputs":[{"internalType":"uint256","name":"maxMiners","type":"uint256"},{"internalType":"uint256","name":"totalPowerOutput","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facilityCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinetendoPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"getPlayerMinersPaginated","outputs":[{"components":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"internalType":"struct Miner[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"getReferrals","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"getTotalMiners","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialFacilityPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"initializedStarterFacility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastFacilityUpgradeTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRewardBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"minerSecondHandMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"miners","outputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minetendo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minetoshi","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miningHasStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ownerToFacility","outputs":[{"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"internalType":"uint256","name":"maxMiners","type":"uint256"},{"internalType":"uint256","name":"currMiners","type":"uint256"},{"internalType":"uint256","name":"totalPowerOutput","type":"uint256"},{"internalType":"uint256","name":"currPowerOutput","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerHashrate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"playerMinersId","outputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerMinersOwned","outputs":[{"internalType":"uint256","name":"_spacer","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerMinetendoDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"playerMinetendoPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"purchaseInitialFacility","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referralBonusPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referrals","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"referredUsers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"secondTierReferralBonusPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondTierReferralFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"secondTierReferrals","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerId","type":"uint256"}],"name":"sellMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"burn","type":"uint256"}],"name":"setBurnPct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cooldown","type":"uint256"}],"name":"setCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"setEnableUpgradeFacility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_initialPrice","type":"uint256"}],"name":"setInitialFacilityPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minetendo","type":"address"}],"name":"setMinetendo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minetoshi","type":"address"}],"name":"setMinetoshi","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setSecondTierReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"timeUntilNextFacilityUpgrade","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"toggleFacilityProduction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"toggleMinerProduction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalHashrate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniqueMinerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgradeFacility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"withdrawMinetendo","outputs":[],"stateMutability":"nonpayable","type":"function"}]

9c4d535b0000000000000000000000000000000000000000000000000000000000000000010007050f51b4ba674fb0b4ae3a42be6b3dfccc071d8413d0e05b15ae270f8600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x0001000000000002001100000000000200000000000103550000000100200190000000420000c13d000000600210027000000624022001970000008004000039000000400040043f000000040020008c0000111c0000413d000000000301043b000000e003300270000006330030009c000000770000a13d000006340030009c0000008f0000a13d000006350030009c000000fd0000a13d000006360030009c000001430000213d0000063d0030009c000003c20000a13d0000063e0030009c000007b40000613d0000063f0030009c000006a60000613d000006400030009c0000111c0000c13d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000402100370000000000202043b000006260020009c0000111c0000213d0000002401100370000000000101043b000d00000001001d000000000020043f0000001e01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a0000000d0020006b0000111c0000813d0000000d02000029188c15e20000040f0000000302200210000000000101041a000000000121022f0000062601100197000000ff0020008c00000000010020190000033b0000013d000000c001000039000000400010043f0000000001000416000000000001004b0000111c0000c13d0000000006000411000000000006004b0000004f0000c13d0000063101000041000000c00010043f000000c40000043f00000632010000410000188e00010430000000000100041a0000062502100197000000000262019f000000000020041b00000000020004140000062605100197000006240020009c0000062402008041000000c00120021000000627011001c70000800d0200003900000003030000390000062804000041188c18820000040f00000001002001900000111c0000613d00000629010000410000000c02000039000000000012041b0000062a010000410000000d02000039000000000012041b0000062b010000410000000e02000039000000000012041b0000062c020000410000000f03000039000000000023041b0000002102000039000000000012041b0000000602000039000000000102041a000000010110003a000000e10000c13d000006f501000041000000000010043f0000001101000039000000040010043f000006a8010000410000188e00010430000006680030009c000000a70000213d000006820030009c000001110000213d0000068f0030009c000002210000a13d000006900030009c000004250000a13d000006910030009c000007c40000613d000006920030009c000006de0000613d000006930030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001a01000039000007510000013d0000064f0030009c000000ec0000213d0000065c0030009c000001ce0000a13d0000065d0030009c000003930000a13d0000065e0030009c000006330000613d0000065f0030009c000005c80000613d000006600030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001d01000039000003ad0000013d000006690030009c000001270000213d000006760030009c000002440000a13d000006770030009c000004350000a13d000006780030009c000007d30000613d000006790030009c000006ea0000613d0000067a0030009c0000111c0000c13d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000c00000004001d000d00000003001d000000000030043f0000001a01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000c02000029000000000021041b000000400100043d0000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006e304000041000004f70000013d000000000012041b000000800010043f000000400400043d0000062d0040009c000001500000413d000006f501000041000000000010043f0000004101000039000000040010043f000006a8010000410000188e00010430000006500030009c000001e00000a13d000006510030009c0000039e0000a13d000006520030009c0000063b0000613d000006530030009c000005d80000613d000006540030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d000006ca01000041000000800010043f0000069b010000410000188d0001042e000006430030009c000001ed0000a13d000006440030009c000003b20000a13d000006450030009c000007170000613d000006460030009c000005f70000613d000006470030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001601000039000003cf0000013d000006830030009c0000024f0000a13d000006840030009c000004580000a13d000006850030009c000007e30000613d000006860030009c000006ef0000613d000006870030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001101000039000007510000013d0000066a0030009c000002600000a13d0000066b0030009c000004750000a13d0000066c0030009c000008090000613d0000066d0030009c000007120000613d0000066e0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000200041a00000626032001970000000002000411000000000023004b000007af0000c13d000006af0010009c000004c10000213d0000000e02000039000000000012041b00000000010000190000188d0001042e000006370030009c000003e90000a13d000006380030009c000007bf0000613d000006390030009c000006b10000613d0000063a0030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000e01000039000007550000013d000000c002400039000000400020043f00000060034000390000000202000039000d00000003001d000000000023043500000040034000390000000a02000039000900000003001d00000000002304350000008003400039000000010200008a000a00000003001d00000000002304350000002003400039000800000003001d00000000002304350000000000140435000c00000004001d000000a001400039000b00000001001d0000000000010435000000800100043d000000000010043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000c020000290000000002020433000000000101043b000000000021041b000000080200002900000000020204330000000103100039000000000023041b000000090200002900000000020204330000000203100039000000000023041b0000000d0200002900000000020204330000000303100039000000000023041b0000000a0200002900000000020204330000000403100039000000000023041b0000000501100039000000000201041a000006fc022001970000000b030000290000000003030433000000000003004b000000010220c1bf000000000021041b000000400300043d0000062f0030009c000000e60000213d0000008001300039000000400010043f0000004005300039000000010100008a00000000001504350000002007300039000001f4010000390000000000170435000003e8010000390000000000130435000000600630003900000000000604350000000702000039000000000102041a000000010110003a000000710000613d000000000012041b000000000010043f0000001401000039000000200010043f00000040020000390000000001000019000a00000003001d000c00000005001d000d00000006001d000b00000007001d188c184f0000040f0000000a020000290000000002020433000000000021041b0000000b0200002900000000020204330000000103100039000000000023041b0000000c0200002900000000020204330000000203100039000000000023041b0000000301100039000000000201041a000006fc022001970000000d030000290000000003030433000000000003004b000000010220c1bf000000000021041b0000000701000039000000000101041a000000a00010043f000000800200043d0000014000000443000001600020044300000020020000390000018000200443000001a00010044300000100002004430000000201000039000001200010044300000630010000410000188d0001042e000006630030009c000002b30000213d000006660030009c0000048b0000613d000006670030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000002001000039000007510000013d000006570030009c000002fd0000213d0000065a0030009c000004900000613d0000065b0030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d000006d001000041000000800010043f0000069b010000410000188d0001042e0000064a0030009c000003060000213d0000064d0030009c000004a70000613d0000064e0030009c0000111c0000c13d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000402100370000000000202043b000d00000002001d0000002401100370000000000201043b000000000002004b0000000001000039000000010100c039000c00000002001d000000000012004b0000111c0000c13d000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000006a20100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d02000029000000000012004b0000021e0000413d0000000601000039000000000101041a000000000012004b00000c060000a13d000000400100043d000006c90200004100000bb20000013d000006960030009c000003110000213d000006990030009c000004c50000613d0000069a0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001401000039000000200010043f00000040020000390000000001000019188c184f0000040f0000000302100039000000000202041a0000000203100039000000000303041a0000000104100039000000000404041a000000000101041a000000800010043f000000a00040043f000000c00030043f000000ff002001900000000001000039000000010100c039000000e00010043f000006f9010000410000188d0001042e0000067d0030009c000003270000213d000006800030009c000004f90000613d000006810030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000101000039000004940000013d0000068a0030009c000003420000213d0000068d0030009c0000054a0000613d0000068e0030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000301000039000000000101041a000000000001004b000008260000c13d000006f401000041000000800010043f000006b8010000410000188e00010430000006710030009c000003790000213d000006740030009c000005570000613d000006750030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400400043d000006be0040009c000000e60000213d000000000101043b000000c002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000a00000003001d00000000002304350000000202100039000000000202041a0000004003400039000900000003001d00000000002304350000000302100039000000000202041a0000006003400039000b00000003001d00000000002304350000000402100039000000000202041a0000008003400039000c00000003001d0000000000230435000800000004001d000000a0024000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000d00000002001d00000000001204350000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400300043d000000000101043b000700000001001d0000000d010000290000000001010433000000000001004b00000b460000c13d000006e2010000410000041f0000013d000006640030009c000004960000613d000006650030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d0000000d01000029000000000010043f0000001b01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000c02000039000000000202041a000000000101043b000000000101041a000c00000002001d000b00000001001d000000000012001a000000710000413d000006a40100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d0000000b030000290000000c02300029000000000101043b000b00000001001d000000000012004b00000000010000190000033b0000413d0000000d01000029000000000010043f0000001b01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a0000000c0010002a000000710000413d0000000c011000290000000b0110006c0000033b0000813d000000710000013d000006580030009c000004a20000613d000006590030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000f01000039000007550000013d0000064b0030009c000004b30000613d0000064c0030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d000006c701000041000000800010043f0000069b010000410000188d0001042e000006970030009c0000055e0000613d000006980030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000201043b000000000002004b0000000001000039000000010100c039000d00000002001d000000000012004b0000111c0000c13d188c161d0000040f0000000a01000039000000000201041a000006fc02200197000005ae0000013d0000067e0030009c0000059b0000613d0000067f0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001501000039000000200010043f00000040020000390000000001000019188c184f0000040f188c182a0000040f000000400200043d0000000000120435000006240020009c00000624020080410000004001200210000006a3011001c70000188d0001042e0000068b0030009c000005a00000613d0000068c0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000800000001001d000006260010009c0000111c0000213d0000000401000039000000000101041a000000ff00100190000007cb0000613d0000000901000039000000000101041a000a00000001001d000000000001004b000009160000c13d0000000801000029000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000201043b0000000d01000039000000000101041a000006af0010009c000000710000213d0000000e03000039000000000303041a000006af01100099000000000131004b000000710000413d000000000202041a000003750000613d000006fd03100129000000000023004b000009120000413d00000000022100a9000000400100043d000006af0220012a000007cd0000013d000006720030009c000005b20000613d000006730030009c0000111c0000c13d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d0000000701000039000000000101041a000000000013004b000008b90000a13d000006d701000041000000800010043f000006b8010000410000188e00010430000006610030009c000005dd0000613d000006620030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d000006af01000041000000800010043f0000069b010000410000188d0001042e000006550030009c000005e20000613d000006560030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001c01000039000000200010043f00000040020000390000000001000019188c184f0000040f000004940000013d000006480030009c000006a10000613d000006490030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001801000039000005d30000013d000006410030009c000006c60000613d000006420030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001301000039000000200010043f00000040020000390000000001000019188c184f0000040f0000000502100039000000000202041a0000000403100039000000000303041a0000000304100039000000000404041a0000000205100039000000000505041a0000000106100039000000000606041a000000000101041a000000800010043f000000a00060043f000000c00050043f000000e00040043f000001000030043f000000ff002001900000000001000039000000010100c039000001200010043f000006b9010000410000188d0001042e0000063b0030009c000006d30000613d0000063c0030009c0000111c0000c13d000000840020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000006402100370000000000302043b000000000003004b0000000002000039000000010200c039000d00000003001d000000000023004b0000111c0000c13d0000000402100370000000000502043b0000002402100370000000000302043b0000004401100370000000000401043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000a00000005001d000b00000004001d000c00000003001d0000000701000039000000000101041a000900000001001d000000000010043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400300043d000000000101043b0000000101100039000000000101041a0000000c02000029000000000021004b00000bb80000a13d000006a0010000410000000000130435000006240030009c00000624030080410000004001300210000006a1011001c70000188e00010430000006940030009c000007460000613d000006950030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001501000039000007510000013d0000067b0030009c000007590000613d0000067c0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001701000039000000200010043f00000040020000390000000001000019188c184f0000040f0000000402100039000000000202041a0000000303100039000000000303041a0000000204100039000000000404041a0000000105100039000000000505041a000000000101041a000000800010043f000000a00050043f000000c00040043f000000e00030043f000001000020043f000006e4010000410000188d0001042e000006880030009c000007660000613d000006890030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000001000411188c162d0000040f0000000001000411000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000000001004b000008f30000c13d000000400100043d000006f10200004100000bb20000013d0000066f0030009c000007aa0000613d000006700030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000200041a00000626032001970000000002000411000000000023004b000007af0000c13d000006d30010009c000004c10000813d0000000d02000039000000000012041b00000000010000190000188d0001042e0000000001000416000000000001004b0000111c0000c13d0000000c01000039000007550000013d0000000001000416000000000001004b0000111c0000c13d0000000201000039000000000101041a000006370000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001b01000039000007510000013d0000000001000416000000000001004b0000111c0000c13d0000000401000039000006aa0000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001201000039000007510000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000200041a00000626032001970000000002000411000000000023004b000007af0000c13d000006af0010009c0000086d0000a13d000006d401000041000000800010043f000006b8010000410000188e00010430000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d0000000601000039000000000101041a000000000013004b000005c40000213d000c00000004001d000d00000003001d000000000030043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b00000003011000390000000c02000029000000000021041b000000400100043d0000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006fa040000410000000d050000290000081c0000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001e01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000301041a000000400200043d000c00000002001d000b00000003001d0000000002320436000d00000002001d000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006b1011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000b05000029000000000005004b0000000d0600002900000000020600190000052e0000613d000000000101043b00000000030000190000000002060019000000000401041a0000062604400197000000000242043600000001011000390000000103300039000000000053004b000005270000413d0000000c0300002900000000013200490000001f01100039000006fe021001970000000001320019000000000021004b00000000020000390000000102004039000006aa0010009c000000e60000213d0000000100200190000000e60000c13d000000400010043f00000020020000390000000002210436000000000303043300000000003204350000004002100039000000000003004b00000b3d0000613d00000000040000190000000065060434000006260550019700000000025204360000000104400039000000000034004b000005430000413d00000b3d0000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d188c161d0000040f0000000101000039000005ac0000013d0000000001000416000000000001004b0000111c0000c13d000006cf01000041000000800010043f0000069b010000410000188d0001042e000000640020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000402100370000000000202043b000006260020009c0000111c0000213d0000002403100370000000000303043b000900000003001d0000004401100370000000000101043b000d00000001001d000000000020043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000201043b000006ba01000041000000040010043f000c00000002001d000000000020043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000006fd02100167000000000202041a000000000002004b00000a480000c13d000000000201041a000000000002004b0000000002000039000000010200c03900000a490000613d0000000103100039000000000303041a000000000003004b00000a490000613d0000000201100039000000000101041a000000000001004b0000000302000039000000020200603900000a490000013d0000000001000416000000000001004b0000111c0000c13d0000000301000039000007550000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d188c161d0000040f0000000201000039000000000201041a00000625022001970000000d022001af000000000021041b00000000010000190000188d0001042e000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d0000000601000039000000000101041a000000000013004b000008710000a13d000006fb01000041000000800010043f000006b8010000410000188e00010430000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001901000039000000200010043f00000040020000390000000001000019188c184f0000040f000006aa0000013d0000000001000416000000000001004b0000111c0000c13d0000000801000039000007550000013d0000000001000416000000000001004b0000111c0000c13d0000000d01000039000007550000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d0000000901000039000000000201041a000000000002004b0000000001000019000008880000c13d0000000000140435000006240040009c00000624040080410000004001400210000006a3011001c70000188d0001042e000000240020008c0000111c0000413d0000000001000416000000000001004b0000111c0000c13d0000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000004020000390000000002200367000000000202043b000d00000002001d000000000101043b000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000201043b00000004010000390000000001100367000000000101043b000006bc0010009c000014190000613d000000000001004b0000000d04000029000006bc04006041000006fd03200167000000000303041a000000000003004b000009b40000c13d000000000302041a000000000043004b00000d5f0000613d0000000103200039000000000303041a000000000043004b00000d5f0000613d0000000202200039000000000202041a000000000042004b000009c30000c13d00000d5f0000013d0000000001000416000000000001004b0000111c0000c13d000000000100041a0000062601100197000000800010043f0000069b010000410000188d0001042e000000840020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000006402100370000000000302043b000000000003004b0000000002000039000000010200c039000d00000003001d000000000023004b0000111c0000c13d0000000402100370000000000302043b0000002402100370000000000402043b0000004401100370000000000501043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d0000000602000039000000000102041a000000010110003a000000710000613d000000000012041b0000014002000039000000400020043f000000800010043f000000a00000043f000c00000003001d000000c00030043f000b00000004001d000000e00040043f000a00000005001d000001000050043f0000000d02000029000001200020043f000000000010043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000800200043d000000000021041b0000000102100039000000a00300043d000000000032041b0000000202100039000000c00300043d000000000032041b0000000302100039000000e00300043d000000000032041b0000000402100039000001000300043d000000000032041b0000000501100039000000000301041a000006fc02300197000001200300043d000000000003004b000000010220c1bf000000000021041b0000000601000039000000000501041a000000400100043d00000060021000390000000d03000029000000000032043500000040021000390000000a03000029000000000032043500000020021000390000000b0300002900000000003204350000000c020000290000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006cb011001c70000800d020000390000000203000039000006cc04000041000004f80000013d0000000001000416000000000001004b0000111c0000c13d0000000b01000039000007550000013d0000000001000416000000000001004b0000111c0000c13d0000000a01000039000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f0000069b010000410000188d0001042e000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000601043b000006260060009c0000111c0000213d000000000100041a00000626021001970000000005000411000000000052004b000008210000c13d000000000006004b0000095e0000c13d0000063101000041000000800010043f000000840000043f0000069d010000410000188e00010430000000240020008c0000111c0000413d0000000001000416000000000001004b0000111c0000c13d188c161d0000040f00000004010000390000000001100367000000000101043b0000002102000039000000000012041b00000000010000190000188d0001042e0000000001000416000000000001004b0000111c0000c13d0000000001000412000f00000001001d000e00000000003d0000800501000039000000440300003900000000040004150000000f0440008a000007dd0000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001001000039000007510000013d0000000001000416000000000001004b0000111c0000c13d0000000901000039000007550000013d000000240020008c0000111c0000413d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d0000002101000039000000000101041a0000000002000416000000000012004b000008d10000c13d0000000001000411000000000010043f0000001801000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000ff0010019000000bb00000c13d00000000010004110000000d0010006b00000c340000c13d000000400100043d000006ea0200004100000bb20000013d0000000001000416000000000001004b0000111c0000c13d0000000601000039000007550000013d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000402100370000000000202043b000d00000002001d0000002401100370000000000201043b000000000002004b0000000001000039000000010100c039000c00000002001d000000000012004b0000111c0000c13d000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000006a201000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d02000029000000000012004b000007430000413d0000000701000039000000000101041a000000000012004b00000d3a0000a13d000000400100043d000006c60200004100000bb20000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001f01000039000000200010043f00000040020000390000000001000019188c184f0000040f000000000101041a000000800010043f0000069b010000410000188d0001042e000000240020008c0000111c0000413d0000000001000416000000000001004b0000111c0000c13d188c161d0000040f00000004010000390000000001100367000000000101043b0000000c02000039000000000012041b00000000010000190000188d0001042e000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d000000000200041a00000626032001970000000002000411000000000023004b000007af0000c13d0000000102000039000000000202041a0000000203000039000000000303041a000006c104000041000000800040043f0000000401100370000000000101043b0000062603300197000000840030043f000000a40010043f00000000010004140000062602200197000006240010009c0000062401008041000000c001100210000006f2011001c7188c18820000040f00000060031002700000062403300197000000200030008c000000200a000039000000000a0340190000001f05a0018f0000002006a0019000000080046001bf000007910000613d0000008007000039000000000801034f000000008908043c0000000007970436000000000047004b0000078d0000c13d000000000005004b0000079e0000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f00000000005404350000000100200190000008d50000613d000000800100003900000000020a0019000d0000000a001d188c15fd0000040f0000000d0100002900000080021001bf0000008001000039188c160f0000040f00000000010000190000188d0001042e0000000001000416000000000001004b0000111c0000c13d0000000701000039000007550000013d0000069c01000041000000800010043f000000840020043f0000069d010000410000188e000104300000000001000416000000000001004b0000111c0000c13d0000000a01000039000000000101041a000000ff00100190000008410000c13d000006b701000041000000800010043f000006b8010000410000188e000104300000000001000416000000000001004b0000111c0000c13d0000002101000039000007550000013d0000000001000416000000000001004b0000111c0000c13d0000000401000039000000000101041a000000ff00100190000008550000c13d000000800100003900000000020000190000000000210435000006240010009c00000624010080410000004001100210000006a3011001c70000188d0001042e0000000001000416000000000001004b0000111c0000c13d0000000001000412001100000001001d001000200000003d000080050100003900000044030000390000000004000415000000110440008a0000000504400210000006a202000041188c18640000040f000000800010043f0000069b010000410000188d0001042e0000000001000416000000000001004b0000111c0000c13d000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000006eb010000410000000000100443000000000100041000000004001004430000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800a02000039188c18870000040f0000000100200190000015310000613d0000000202000039000000000202041a0000062604200197000000000301043b0000000001000414000006240010009c0000062401008041000000c001100210000000000003004b000009820000c13d0000000002040019000009850000013d0000069c02000041000000800020043f000000840010043f0000069d010000410000188e000104300000000001000416000000000001004b0000111c0000c13d000000000100041a00000626021001970000000005000411000000000052004b000008210000c13d0000062501100197000000000010041b0000000001000414000006240010009c0000062401008041000000c00110021000000627011001c70000800d02000039000000030300003900000628040000410000000006000019188c18820000040f00000001002001900000111c0000613d00000000010000190000188d0001042e0000069c01000041000000800010043f000000840050043f0000069d010000410000188e00010430000d00000001001d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b000006cf0210012a0000000103200039000006cf023000d100000000033200d9000006cf0030009c000000710000c13d0000000d03000029000006cf3030012a000000000032001a000000710000413d0000000002320019000000000112004b0000033b0000813d000000710000013d0000000001000411000000000010043f0000001801000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000ff001001900000096a0000c13d000000400100043d000006b60200004100000bb20000013d0000000301000039000000000101041a000d00000001001d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d0210006c000000710000413d000006ce0020009c000000710000213d000000400100043d0000062402200197000006cf0220012a000006d00220027f000007cd0000013d0000000f02000039000000000012041b00000000010000190000188d0001042e000c00000004001d000d00000003001d000006a20100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d02000029000000000012004b00000aef0000c13d000000400100043d000006d90200004100000bb20000013d000b00000002001d0000000301000039000000000101041a000c00000001001d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000c0110006c000000710000413d000006ce0010009c000000710000213d000c00000001001d0000000d01000029000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000c020000290000062402200197000006cf0220012a000006d00220027f000000000101043b000000000301041a00000000012300a9000000000003004b000008b60000613d00000000033100d9000000000023004b00000e8b0000c13d0000000b011000fa000000400400043d000005f10000013d000c00000004001d000d00000003001d000006a201000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d02000029000000000012004b00000b910000c13d000000400100043d000006d60200004100000bb20000013d000006e501000041000000800010043f000006b8010000410000188e000104300000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008dc0000c13d000000000005004b000008ed0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000006240020009c00000624020080410000004002200210000000000112019f0000188e00010430000d00000001001d0000000001000411000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000001041b0000000d01000039000000000101041a000000000001004b0000000d040000290000090b0000613d000006fd02100129000000000042004b000009120000413d0000000e02000039000000000202041a000000000002004b000009c60000613d000006fd03200129000000000043004b000009c60000813d000006f301000041000000000010043f000006d2010000410000188e000104300000000301000039000000000101041a0000000802000039000000000302041a000000000213004b000000710000413d000006ce0020009c000000710000213d000c00000003001d000006cf1010012a000900000001001d0000000b01000039000000000101041a000d00000001001d0000062401200197000006cf0110012a000b06d000100287000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000c05000029000000000015004b0000000d07000029000000090400002900000e3c0000813d000006cf0250012a0000000103200039000006cf023000d100000000033200d9000006cf0030009c0000000b08000029000000710000c13d000000000042001a000000710000413d0000000003420019000000000013004b00000000020100190000000002034019000000000452004b000000710000413d000000000008004b000009540000613d00000000058400a900000000068500d9000000000046004b000000710000c13d000000000005004b000009540000613d000006af045000d100000000055400d9000006af0050009c000009550000613d000000710000013d00000000040000190000000a044000fa000000000074001a000000710000413d000d00000074001d000000000013004b000000010880a270000b00000008001d000c00000002001d000009270000013d0000062501100197000000000161019f000000000010041b0000000001000414000006240010009c0000062401008041000000c00110021000000627011001c70000800d02000039000000030300003900000628040000410000081c0000013d0000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000c00000001001d000000000201041a0000000701000039000000000101041a000d00000002001d000000000012004b00000d150000c13d000000400100043d000006b50200004100000bb20000013d00000627011001c700008009020000390000000005000019188c18820000040f000000600310027000000624033001980000098e0000c13d00000001002001900000081f0000c13d000000400100043d000006ee0200004100000bb20000013d0000001f04300039000006ec044001970000003f04400039000006ed04400197000000400500043d0000000004450019000000000054004b00000000060000390000000106004039000006aa0040009c000000e60000213d0000000100600190000000e60000c13d000000400040043f0000001f0430018f0000000006350436000006a9053001980000000003560019000009a60000613d000000000701034f000000007807043c0000000006860436000000000036004b000009a20000c13d000000000004004b000009890000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000130435000009890000013d000000200020043f000000000040043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000000001004b00000d5c0000c13d000000400100043d000006bd0200004100000bb20000013d00000000014100a9000c06af001001320000000c0140006c000000710000413d00000000024200a9000a06af002001320000000a0110006c000b00000001001d000000710000413d0000000101000039000000000101041a000006ad0200004100000000002004430000062601100197000900000001001d00000004001004430000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000400300043d00000024013000390000000b020000290000000000210435000006ef0100004100000000001304350000000001000411000006260110019700000004023000390000000000120435000006240030009c000b00000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000902000029188c18820000040f000000010020019000000ea50000613d0000000b01000029000006aa0010009c000000e60000213d0000000b01000029000000400010043f0000000001000411000000000010043f0000001c01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a0000000102000039000000000202041a000006ad0300004100000000003004430000062602200197000b00000002001d0000000400200443000906260010019c000011100000c13d0000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000400300043d00000024013000390000000c020000290000000000210435000006ef0100004100000000001304350000000001000410000006260110019700000004023000390000000000120435000006240030009c000900000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000b02000029188c18820000040f0000000100200190000011a80000613d0000000901000029000006aa0010009c000000e60000213d0000000901000029000000400010043f0000000001000410000000000010043f0000001f01000039000000200010043f0000000001000414000011460000013d0000000102200270000000090520006c00000b0e0000a13d0000000d0050006c0000000d05008029000006aa0050009c000000e60000213d00000005015002100000003f02100039000006f702200197000000400400043d0000000002240019000000000042004b00000000030000390000000103004039000006aa0020009c000000e60000213d0000000100300190000000e60000c13d000000400020043f000800000004001d0000000002540436000700000002001d000600000005001d000000000005004b00000b150000613d00000000020000190000000705000029000000400300043d000006be0030009c000000e60000213d000000c004300039000000400040043f000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b00000a640000413d000d00000000001d000006ba01000041000000040010043f0000000c01000029000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000d03000029000b00090030002d000000000101043b0000000b01100029000000000101041a000a00000001001d000006ba01000041000000040010043f0000000c01000029000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000201043b000006fd01200167000000000101041a000000000001004b00000aa10000613d000000010110027000000aaf0000013d000000000102041a000000000001004b0000000001000039000000010100c03900000aaf0000613d0000000103200039000000000303041a000000000003004b00000aaf0000613d0000000201200039000000000101041a000000000001004b000000030100003900000002010060390000000b0010006b0000110d0000813d0000000a01000029000006bc0010009c0000000001006019000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000006be0020009c000000080500002900000006060000290000000707000029000000e60000213d000000000101043b000000c003200039000000400030043f000000000301041a00000000033204360000000104100039000000000404041a00000000004304350000000203100039000000000303041a000000400420003900000000003404350000000303100039000000000303041a000000600420003900000000003404350000000403100039000000000303041a00000080042000390000000000340435000000a0032000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000000000013043500000000010504330000000d03000029000000000031004b000010b30000a13d0000000501300210000000000171001900000000002104350000000001050433000000000031004b000010b30000a13d000d00010030003d0000000d0060006b00000a7a0000413d00000b150000013d000000000020043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b00000004011000390000000c02000029000000000021041b000000400100043d0000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006d804000041000004f70000013d000000400200043d000006f60020009c000000e60000213d0000002001200039000000400010043f000800000002001d0000000000020435000000400100043d000000200200003900000000022104360000000803000029000000000303043300000000003204350000004002100039000000000003004b00000b3d0000613d00000000040000190000000808000029000000200880003900000000050804330000000076050434000000000662043600000000070704330000000000760435000000400650003900000000060604330000004007200039000000000067043500000060065000390000000006060433000000600720003900000000006704350000008006500039000000000606043300000080072000390000000000670435000000a0055000390000000005050433000000000005004b0000000005000039000000010500c039000000a0062000390000000000560435000000c0022000390000000104400039000000000034004b00000b200000413d0000000002120049000006240020009c00000624020080410000006002200210000006240010009c00000624010080410000004001100210000000000112019f0000188d0001042e0000000101000039000000000201041a000006a70100004100000000001304350000000401300039000000000403001900000000030004110000000000310435000600000004001d000006240040009c0000062401000041000000000104401900000040011002100000000003000414000006240030009c0000062403008041000000c003300210000000000113019f000006a8011001c70000062602200197000500000002001d188c18870000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000060b000029000000060570002900000b6c0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000b680000c13d000000000006004b00000b790000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000c280000613d0000001f01400039000000600110018f0000000002b10019000000000012004b00000000010000390000000101004039000400000002001d000006aa0020009c000000e60000213d0000000100100190000000e60000c13d0000000401000029000000400010043f000000200030008c0000111c0000413d0000000c01000029000000000101043300000000020b0433000000000012004b00000e8f0000813d000006b30100004100000e9e0000013d000000000020043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b00000002011000390000000c02000029000000000021041b000000400100043d0000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006d504000041000004f70000013d000000400100043d000006e6020000410000000000210435000006240010009c00000624010080410000004001100210000006a1011001c70000188e000104300000062f0030009c000000e60000213d0000008001300039000000400010043f00000060043000390000000d01000029000700000004001d000000000014043500000040043000390000000b01000029000600000004001d00000000001404350000000a01000029000800000003001d0000000001130436000a00000001001d00000000002104350000000901000029000000010110003a000000710000613d0000000702000039000000000012041b000000000010043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000008020000290000000002020433000000000101043b000000000021041b0000000a0200002900000000020204330000000103100039000000000023041b000000060200002900000000020204330000000203100039000000000023041b0000000301100039000000000301041a000006fc0230019700000007030000290000000003030433000000000003004b000000010220c1bf000000000021041b0000000701000039000000000501041a000000400100043d00000040021000390000000d03000029000000000032043500000020021000390000000b0300002900000000003204350000000c020000290000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000069e011001c70000800d0200003900000002030000390000069f04000041000004f80000013d000000000020043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000501100039000000000201041a000006fc022001970000000c03000029000000000232019f000000000021041b000000400100043d0000000000310435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006c804000041000004f70000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000c2f0000c13d000008e00000013d000000000010043f0000001801000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000006fc0220019700000001022001bf000000000021041b0000000d0000006b00000de20000c13d000006a201000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b000d00000001001d000000000010043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000c00000002001d0000062f0020009c000000e60000213d000000000101043b0000000c040000290000008002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000b00000003001d00000000002304350000000202100039000000000202041a0000004003400039000000000023043500000060024000390000000301100039000000000101041a000000ff001001900000000001000039000000010100c03900000000001204350000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000d02000029000000000021041b0000000c0200002900000000020204330000000103100039000000000023041b00000003011000390000000b020000290000000002020433000000000021041b0000001901000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000ff001001900000111e0000c13d0000000001000411000000000010043f0000001901000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000006fc0220019700000001022001bf000000000021041b000006a20100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000010043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000d00000002001d000006be0020009c000000e60000213d000000000101043b0000000d04000029000000c002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000b00000003001d00000000002304350000000202100039000000000202041a0000004003400039000a00000003001d00000000002304350000000302100039000000000202041a0000006003400039000c00000003001d00000000002304350000000402100039000000000202041a0000008003400039000800000003001d0000000000230435000000a0024000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000900000002001d00000000001204350000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000c020000290000000002020433000000000101043b000700000001001d0000000401100039000600000001001d000000000101041a000000000012001a000000710000413d000000000112001900000007020000290000000302200039000000000202041a000000000021004b000013f10000a13d000000400100043d000006e10200004100000bb20000013d0000000001000411000000000010043f0000001b01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000b00000001001d000006a40100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000b0110006c000000710000413d0000000c02000039000000000202041a000000000021004b000010300000813d000000400100043d000006b40200004100000bb20000013d000000000020043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000301100039000000000201041a000006fc022001970000000c03000029000000000232019f000000000021041b000000400100043d0000000000310435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006c504000041000004f70000013d00000004010000390000000001100367000000000101043b000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000d00000002001d000006be0020009c000000e60000213d000000000101043b0000000d05000029000000c002500039000000400020043f000000000201041a00000000032504360000000104100039000000000404041a00000000004304350000000203100039000000000303041a0000004004500039000b00000004001d00000000003404350000000303100039000000000303041a0000006004500039000c00000004001d00000000003404350000000403100039000000000303041a00000080045000390000000000340435000000a0035000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c0390000000000130435000000000020043f0000001a01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000900000001001d0000000101000039000000000101041a000000400400043d000a00000004001d000006a7020000410000000000240435000000040240003900000000030004100000000000320435000006240040009c0000062402000041000000000204401900000040022002100000000003000414000006240030009c0000062403008041000000c003300210000000000323019f0000062602100197000006a8013001c7188c18870000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0b0000290000000a0570002900000dc10000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000dbd0000c13d000000000006004b00000dce0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000e7f0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006aa0010009c000000e60000213d0000000100200190000000e60000c13d000000400010043f000000200030008c0000111c0000413d00000000020b0433000000090020006b000010b90000a13d000006c30200004100000bb20000013d0000001c01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a00000625022001970000000d03000029000000000232019f000000000021041b000000000030043f0000001e01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000c00000002001d000006aa0020009c000000e60000213d0000000c020000290000000102200039000000000021041b000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006b1011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000c01100029000000000201041a00000625022001970000000003000411000000000232019f000000000021041b0000000d01000029000000000010043f0000001c01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000d06260010019c00000c470000613d0000000001000411000000000010043f0000001d01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a00000625022001970000000d022001af000000000021041b00000c470000013d00000008010000290000062601100197000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000c00000001001d0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000b00000001001d0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a0000000d0210006b000000710000413d0000000b012000b90000000b0000006b00000e700000613d0000000b031000fa000000000023004b000000710000c13d000006af0210012a0000000c0020002a000000710000413d0000000d01000039000000000101041a000006af0010009c000000710000213d0000000e03000039000000000303041a000006af01100099000000000131004b000000710000413d0000000c02200029000003720000c13d000003750000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000e860000c13d000008e00000013d000006d101000041000000000010043f000006d2010000410000188e000104300000000b02000029000000000202043300000007030000290000000403300039000600000003001d000000000303041a000000000032001a000000710000413d000000000232001900000007030000290000000303300039000000000303041a000000000032004b00000ec10000a13d000006e10100004100000004020000290000000000120435000006240020009c00000624020080410000004001200210000006a1011001c70000188e0001043000000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b00000ead0000c13d0000062406600197000000000004004b00000ebf0000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000006001600210000008ee0000013d0000000403000029000000440230003900000000001204350000000001000410000006260110019700000024023000390000000000120435000006ab0100004100000000001304350000000001000411000006260110019700000004023000390000000000120435000006240030009c0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006ac011001c70000000502000029188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000040570002900000ee90000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b00000ee50000c13d000000000006004b00000ef60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000010a70000613d0000001f01400039000000600110018f0000000401100029000006aa0010009c000000e60000213d000000400010043f000000200030008c0000111c0000413d00000004010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b0000111c0000c13d0000000c010000290000000001010433000500000001001d0000000f01000039000000000101041a000400000001001d000000000001004b00000f130000613d000000010100008a00000004011000fa000000050010006c000009120000413d0000000101000039000000000101041a000006ad0200004100000000002004430000062601100197000300000001001d00000004001004430000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000040200002900000005012000b9000006af0310012a000000400200043d000006b00100004100000000001204350000000401200039000100000001001d000400000003001d0000000000310435000006240020009c000500000002001d0000062401000041000000000102401900020040001002180000000001000414000006240010009c0000062401008041000000c00110021000000002011001af000006a8011001c70000000302000029188c18820000040f0000000100200190000011c20000613d0000000501000029000006aa0010009c000000e60000213d0000000501000029000000400010043f0000000c0100002900000000010104330004000400100074000000710000413d0000000101000039000000000101041a000006da0200004100000005040000290000000000240435000006c702000041000000010300002900000000002304350000002402400039000000040300002900000000003204350000000002000414000006240020009c0000062402008041000000c00220021000000002032001af0000062602100197000006c2013001c7188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000050570002900000f6a0000613d000000000801034f0000000509000029000000008a08043c0000000009a90436000000000059004b00000f660000c13d000000000006004b00000f770000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f000000000065043500000001002001900000141d0000613d0000001f01400039000000600110018f0000000501100029000006aa0010009c000000e60000213d000000400010043f000000200030008c0000111c0000413d00000005020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000111c0000c13d000006db0010009c000000e60000213d0000000102000039000000000302041a0000000202000039000000000402041a000000e002100039000000400020043f0000008002100039000000040500002900000000005204350000062604400197000000600510003900000000004504350000004004100039000027100600003900000000006404350000002006100039000006ca07000041000000000076043500000626033001970000000000310435000000c0031000390000000000030435000000a0071000390000000000070435000006dc08000041000000400900043d000500000009001d0000000000890435000000000101043300000626011001970000000408900039000000000018043500000000010604330000062601100197000000240690003900000000001604350000000001040433000006dd011001970000004404900039000000000014043500000000010504330000062601100197000000640490003900000000001404350000000001020433000000840290003900000000001204350000000001070433000000a402900039000000000012043500000000010304330000062601100197000000c4029000390000000000120435000006240090009c0000062401000041000000000109401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006de011001c7000006c702000041188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000050b000029000000050570002900000fdc0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000fd80000c13d000000000006004b00000fe90000613d000000000171034f0000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f0000000000150435000000010020019000000ff80000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006aa0010009c000000e60000213d0000000100200190000000e60000c13d000000400010043f000000200030008c0000111c0000413d0000000501000039000000000101041a000400000001001d000500010010003e000000710000613d00000005010000390000000502000029000000000021041b0000000a0100002900000000002104350000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000300000001001d0000000401000029000006df0010009c000014190000613d0000000302000029000006fd01200167000200000001001d000000000101041a000000200020043f000400000001001d000000000001004b000015720000c13d0000000301000029000000000101041a000000000001004b000015320000c13d000000050100002900000003020000290000158b0000013d0000000d01000029000000010110003a000000710000613d000000000010043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000b00000002001d0000062f0020009c000000e60000213d000000000101043b0000000b040000290000008002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000900000003001d00000000002304350000000202100039000000000202041a0000004003400039000a00000003001d000000000023043500000060024000390000000301100039000000000101041a000000ff001001900000000001000039000000010100c0390000000000120435000000400100043d000d00000001001d000011210000613d0000000101000039000000000201041a000006a7010000410000000d040000290000000000140435000000040140003900000000030004110000000000310435000006240040009c0000062401000041000000000104401900000040011002100000000003000414000006240030009c0000062403008041000000c003300210000000000113019f000006a8011001c70000062602200197000800000002001d188c18870000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000d05700029000010800000613d000000000801034f0000000d09000029000000008a08043c0000000009a90436000000000059004b0000107c0000c13d000000000006004b0000108d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f000000000065043500000001002001900000119c0000613d0000001f01400039000000600110018f0000000d02100029000000000012004b00000000010000390000000101004039000700000002001d000006aa0020009c000000e60000213d0000000100100190000000e60000c13d0000000701000029000000400010043f000000200030008c0000111c0000413d0000000a0100002900000000010104330000000d020000290000000002020433000000000012004b000012000000813d000006b301000041000000070200002900000e9f0000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000010ae0000c13d000008e00000013d000006f501000041000000000010043f0000003201000039000000040010043f000006a8010000410000188e000104300000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000202100039000000000302041a000000000003004b000000710000613d000000010330008a000000000032041b0000000401100039000000000201041a0000000c030000290000000003030433000000000232004b000000710000413d000000000021041b0000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000004020000390000000002200367000000000202043b000c00000002001d000000000101043b000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000004020000390000000002200367000000000202043b000000000002004b0000000c02000029000006bc02006041000c00000002001d000000000201043b000a00000002001d000006fd01200167000600000001001d000000000101041a000700000001001d000000000001004b000011cf0000c13d0000000a040000290000000201400039000800000001001d000000000101041a0000000102400039000000000302041a000000000404041a0000000c0040006c000012c00000c13d0000000a04000029000000000034041b000012c20000013d000000400100043d000006f80200004100000bb20000013d0000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b000011240000c13d00000000010000190000188e00010430000000400100043d000006e70200004100000bb20000013d000006a6010000410000000d0200002900000e9f0000013d000000400300043d00000024013000390000000c020000290000000000210435000006ef010000410000000000130435000000040130003900000009020000290000000000210435000006240030009c000800000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000b02000029188c18820000040f0000000100200190000011b50000613d0000000801000029000006aa0010009c000000e60000213d0000000801000029000000400010043f0000000901000029000000000010043f0000001f01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a0000000c0020002a000000710000413d0000000c02200029000000000021041b0000000001000411000000000010043f0000001d01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a0000000102000039000000000202041a000006ad0300004100000000003004430000062602200197000c00000002001d0000000400200443000b06260010019c000013950000c13d0000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000400300043d00000024013000390000000a020000290000000000210435000006ef0100004100000000001304350000000001000410000006260110019700000004023000390000000000120435000006240030009c000b00000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000c02000029188c18820000040f0000000100200190000014290000613d0000000b01000029000006aa0010009c000000e60000213d0000000b01000029000000400010043f0000000001000410000000000010043f0000002001000039000000200010043f0000000001000414000013c30000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000011a30000c13d000008e00000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000011b00000c13d00000eb10000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000011bd0000c13d00000eb10000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000011ca0000c13d00000eb10000013d0000000a01000029000000200010043f0000000c01000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000800000001001d000000000101041a000c00000001001d000000000001004b000012c50000613d0000000701000029000000010110027000070001001000920000000c0010006b000011fb0000613d0000000c010000290000000a0110002900000007030000290000000a02300029000000000202041a000000010110008a000000000021041b000000000020043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000c02000029000000000021041b0000000701000029000000010110021000000001011001bf0000000602000029000012c20000013d0000000703000029000000440230003900000000001204350000000001000410000006260110019700000024023000390000000000120435000006ab0100004100000000001304350000000001000411000006260110019700000004023000390000000000120435000006240030009c0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006ac011001c70000000802000029188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000705700029000012280000613d000000000801034f0000000709000029000000008a08043c0000000009a90436000000000059004b000012240000c13d000000000006004b000012350000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000013e20000613d0000001f01400039000000600110018f0000000701100029000006aa0010009c000000e60000213d000000400010043f000000200030008c0000111c0000413d00000007010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b0000111c0000c13d0000000a010000290000000001010433000d00000001001d0000000f01000039000000000101041a000800000001001d000000000001004b000012520000613d000000010100008a00000008011000fa0000000d0010006c000009120000413d0000000101000039000000000101041a000006ad0200004100000000002004430000062601100197000700000001001d00000004001004430000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d00000008020000290000000d012000b9000006af0110012a000000400300043d000006b002000041000000000023043500000004023000390000000000120435000006240030009c000d00000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006a8011001c70000000702000029188c18820000040f0000000100200190000014520000613d0000000d01000029000006aa0010009c000000e60000213d0000000d01000029000000400010043f0000000c01000029000000000101041a000000010110003a000000710000613d0000000c03000029000000000013041b0000000b0100002900000000010104330000000102300039000000000012041b000000030130003900000009020000290000000002020433000000000021041b0000000001000411000000000010043f0000001b01000039000000200010043f000006a40100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b000d00000001001d0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000d02000029000000000021041b0000000c01000029000000000601041a0000000a010000290000000001010433000000400200043d0000000000120435000006240020009c000006240200804100000040012002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000303000039000006b20400004100000000050004110000081c0000013d0000000c0030006c000013ee0000c13d000000000012041b0000000801000029000000000001041b00000004010000390000000001100367000000000101043b000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000202100039000000000002041b0000000302100039000000000002041b0000000402100039000000000002041b0000000501100039000000000001041b0000000d010000290000000006010433000000400100043d0000000902000029000000000221043600000004030000390000000003300367000000000303043b0000000000320435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d020000390000000303000039000006bf040000410000000005000411188c18820000040f00000001002001900000111c0000613d0000000b010000290000000001010433000d00000001001d0000000001000411188c162d0000040f0000000901000039000000000201041a0000000d0220006c000000710000413d000000000021041b0000000001000411000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a0000000d0220006c000000710000413d000000000021041b0000000001000411000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000d00000001001d0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000400200043d000000200320003900000000001304350000000d010000290000000000120435000006240020009c000006240200804100000040012002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d020000390000000203000039000006c0040000410000000005000411188c18820000040f00000001002001900000111c0000613d000000090000006b0000081f0000613d0000000101000039000000000201041a000000400400043d000d00000004001d000000240140003900000009030000290000000000310435000006c10100004100000000001404350000000001000411000006260110019700000004034000390000000000130435000006240040009c0000062401000041000000000104401900000040011002100000000003000414000006240030009c0000062403008041000000c003300210000000000113019f000006c2011001c70000062602200197188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000d0b0000290000000d05700029000013720000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000136e0000c13d000000000006004b0000137f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000014690000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006aa0010009c000000e60000213d0000000100200190000000e60000c13d000000400010043f000000200030008c0000111c0000413d00000000010b0433000000000001004b0000000002000039000000010200c039000000000021004b0000081f0000613d0000111c0000013d0000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000400300043d00000024013000390000000a020000290000000000210435000006ef01000041000000000013043500000004013000390000000b020000290000000000210435000006240030009c000900000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000c02000029188c18820000040f0000000100200190000014360000613d0000000901000029000006aa0010009c000000e60000213d0000000901000029000000400010043f0000000b01000029000000000010043f0000002001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a0000000a0020002a000000710000413d0000000a02200029000000000021041b000000400100043d0000000d020000290000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000121019f000006b1011001c70000800d020000390000000203000039000006f0040000410000000005000411000004f80000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013e90000c13d000008e00000013d0000000c0010006c000012c30000613d000012c50000013d0000000501000039000000000101041a000500010010003e000000710000613d00000005010000390000000502000029000000000021041b0000000b0100002900000000002104350000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000400000001001d0000000501000029000006bc0010009c000014430000c13d000006e901000041000000000010043f000006d2010000410000188e000104300000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014240000c13d000008e00000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000014310000c13d00000eb10000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b0000143e0000c13d00000eb10000013d0000000402000029000006fd01200167000200000001001d000000000101041a000000200020043f000300000001001d000000000001004b000014ab0000c13d0000000401000029000000000101041a000000000001004b0000145f0000c13d00000005010000290000000402000029000014c40000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b0000145a0000c13d00000eb10000013d000000050010006c000014c50000613d00000004020000290000000102200039000000000302041a000300000003001d000000000003004b000014750000c13d0000000501000029000014c40000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014700000c13d000008e00000013d0000000303000029000000050030006c000014c50000613d00000004020000290000000202200039000000000302041a000100000003001d000000000003004b000014670000613d0000000103000029000000050030006c000014c50000613d000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000102000039000000000021041b0000000301000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000202000039000000000021041b0000000101000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000302000039000000000021041b000300070000003d0000000501000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000000000002004b000014c50000c13d0000000302000029000000010220027000000004032000290000000504000029000000000043041b0000000102200039000000000021041b000000010120021000000001011001bf0000000202000029000000000012041b0000000501000039000000000101041a000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000d020000290000000002020433000000000301043b000000000023041b0000000b0100002900000000010104330000000102300039000000000012041b0000000a0100002900000000010104330000000202300039000000000012041b0000000c0100002900000000010104330000000302300039000000000012041b000000080200002900000000020204330000000404300039000000000024041b0000000502300039000000000302041a000006fc0330019700000009040000290000000004040433000000000004004b000000010330c1bf000000000032041b00000007020000290000000202200039000000000302041a000000010330003a000000710000613d000000000032041b0000000602000029000000000202041a000000000012001a000000710000413d00000000011200190000000602000029000000000012041b0000000501000039000000000101041a000000400300043d00000020023000390000000000120435000d00000003001d0000000000030435000006a20100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000601043b0000000d01000029000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d020000390000000303000039000006e0040000410000000005000411188c18820000040f00000001002001900000111c0000613d0000000a0100002900000000020104330000000001000411188c16f10000040f0000000001000414000006240010009c0000062401008041000000c00110021000000627011001c70000800d020000390000000203000039000006e8040000410000000005000411000004f80000013d000000000001042f000000050010006c0000158c0000613d00000003020000290000000102200039000000000302041a000400000003001d000000000003004b0000153c0000c13d00000005010000290000158b0000013d0000000403000029000000050030006c0000158c0000613d00000003020000290000000202200039000000000302041a000100000003001d000000000003004b0000153a0000613d0000000103000029000000050030006c0000158c0000613d000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000102000039000000000021041b0000000401000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000202000039000000000021041b0000000101000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000302000039000000000021041b000400070000003d0000000501000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000000000002004b0000158c0000c13d0000000402000029000000010220027000000003032000290000000504000029000000000043041b0000000102200039000000000021041b000000010120021000000001011001bf0000000202000029000000000012041b0000000501000039000000000101041a000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000008020000290000000002020433000000000301043b000000000023041b0000000a0100002900000000010104330000000102300039000000000012041b000000090100002900000000010104330000000202300039000000000012041b0000000b0100002900000000020104330000000301300039000000000021041b0000000c0100002900000000010104330000000404300039000000000014041b0000000503300039000000000503041a000006fc045001970000000d050000290000000005050433000000000005004b000000010440c1bf000000000043041b00000007030000290000000203300039000000000403041a000000010440003a000000710000613d000000000043041b0000000603000029000000000303041a000000000023001a000000710000413d00000000022300190000000603000029000000000023041b0000000502000039000000000202041a000000400300043d00000020043000390000000000240435000000000013043500000004010000390000000001100367000000000601043b000006240030009c000006240300804100000040013002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d020000390000000303000039000006e0040000410000000005000411188c18820000040f00000001002001900000111c0000613d000000090100002900000000020104330000000001000411188c16f10000040f00000000010000190000188d0001042e0001000000000002000000000301041a000100000002001d000000000023004b000015f50000a13d000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006b1011001c70000801002000039188c18870000040f0000000100200190000015fb0000613d000000000101043b00000001011000290000000002000019000000000001042d000006f501000041000000000010043f0000003201000039000000040010043f000006a8010000410000188e0001043000000000010000190000188e000104300000001f02200039000006fe022001970000000001120019000000000021004b00000000020000390000000102004039000006aa0010009c000016090000213d0000000100200190000016090000c13d000000400010043f000000000001042d000006f501000041000000000010043f0000004101000039000000040010043f000006a8010000410000188e000104300000000002120049000006ff0020009c0000161b0000213d0000001f0020008c0000161b0000a13d0000000001010433000000000001004b0000000002000039000000010200c039000000000021004b0000161b0000c13d000000000001042d00000000010000190000188e00010430000000000100041a00000626021001970000000001000411000000000012004b000016230000c13d000000000001042d000000400200043d0000069c03000041000000000032043500000004032000390000000000130435000006240020009c00000624020080410000004001200210000006a8011001c70000188e000104300003000000000002000100000001001d0000000901000039000000000101041a000000000001004b00000008020000390000167f0000613d0000000301000039000000000101041a000000000202041a000000000112004b000016e20000413d000006ce0010009c000016e20000213d000300000002001d0000062401100197000006cf0110012a000206d000100287000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000016e80000613d000000000101043b0000000304000029000000000014004b0000168b0000813d000006cf0240012a0000000103200039000006cf023000d100000000033200d9000006cf0030009c0000000207000029000016e20000c13d0000000303000039000000000303041a000006cf3030012a000000000023001a000016e20000413d0000000003230019000000000013004b00000000020100190000000002034019000000000442004b000016e20000413d000000000007004b0000166d0000613d00000000057400a900000000067500d9000000000046004b000016e20000c13d000000000005004b0000166d0000613d000006af045000d100000000055400d9000006af0050009c0000166e0000613d000016e20000013d00000000040000190000000905000039000000000505041a000000000005004b000016e90000613d00000000045400d90000000b05000039000000000505041a000000000045001a000016e20000413d00000000044500190000000b05000039000000000045041b000000000013004b000000010770a270000200000007001d000300000002001d0000163f0000013d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000016e80000613d000000000101043b0000000802000039000000000012041b00000001010000290000062601100197000300000001001d000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000016ef0000613d0000000b02000039000000000202041a000100000002001d000000000101043b000000000101041a000200000001001d0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000016ef0000613d000000000101043b000000000101041a000000010110006b0000000202000029000016e20000413d00000000032100a9000000000002004b000016b80000613d00000000022300d9000000000012004b000016e20000c13d000200000003001d0000000301000029000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000016ef0000613d0000000202000029000006af0220012a000000000101043b000000000301041a000000000023001a000016e20000413d0000000002230019000000000021041b0000000b01000039000000000101041a000200000001001d0000000301000029000000000010043f0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000016ef0000613d000000000101043b0000000202000029000000000021041b000000000001042d000006f501000041000000000010043f0000001101000039000000040010043f000006a8010000410000188e00010430000000000001042f000006f501000041000000000010043f0000001201000039000000040010043f000006a8010000410000188e0001043000000000010000190000188e000104300004000000000002000200000002001d000100000001001d0000000401000039000000000201041a000000ff002001900000171c0000c13d000006fc0220019700000001022001bf000000000021041b000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000018210000613d000000000101043b0000000302000039000000000012041b0000000802000039000000000012041b000000400200043d0000000000120435000006240020009c000006240200804100000040012002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d0200003900000001030000390000070004000041188c18820000040f0000000100200190000018280000613d0000000901000039000000000101041a000000000001004b0000176c0000613d0000000301000039000000000101041a0000000802000039000000000202041a000000000112004b0000181b0000413d000006ce0010009c0000181b0000213d000400000002001d0000062401100197000006cf0110012a000306d000100287000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000018210000613d000000000101043b0000000404000029000000000014004b000017780000813d000006cf0240012a0000000103200039000006cf023000d100000000033200d9000006cf0030009c00000003070000290000181b0000c13d0000000303000039000000000303041a000006cf3030012a000000000023001a0000181b0000413d0000000003230019000000000013004b00000000020100190000000002034019000000000442004b0000181b0000413d000000000007004b0000175a0000613d00000000057400a900000000067500d9000000000046004b0000181b0000c13d000000000005004b0000175a0000613d000006af045000d100000000055400d9000006af0050009c0000175b0000613d0000181b0000013d00000000040000190000000905000039000000000505041a000000000005004b000018220000613d00000000045400d90000000b05000039000000000505041a000000000045001a0000181b0000413d00000000044500190000000b05000039000000000045041b000000000013004b000000010770a270000300000007001d000400000002001d0000172c0000013d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000018210000613d000000000101043b0000000802000039000000000012041b00000001010000290000062601100197000400000001001d000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d0000000b02000039000000000202041a000100000002001d000000000101043b000000000101041a000300000001001d0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b000000000101041a000000010110006b00000003020000290000181b0000413d00000000032100a9000000000002004b000017a50000613d00000000022300d9000000000012004b0000181b0000c13d000300000003001d0000000401000029000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d0000000302000029000006af0220012a000000000101043b000000000301041a000000000023001a0000181b0000413d0000000002230019000000000021041b0000000b01000039000000000101041a000300000001001d0000000401000029000000000010043f0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b0000000302000029000000000021041b0000000901000039000000000101041a000000020010002a0000181b0000413d00000002011000290000000902000039000000000012041b0000000401000029000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b000000000201041a000000020020002a0000181b0000413d0000000202200029000000000021041b0000000401000029000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b000000000101041a000400000001001d0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b000000000101041a000000400200043d0000002003200039000000000013043500000004010000290000000000120435000006240020009c000006240200804100000040012002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d02000039000000020300003900000000050004110000070104000041188c18820000040f0000000100200190000018280000613d000000000001042d000006f501000041000000000010043f0000001101000039000000040010043f000006a8010000410000188e00010430000000000001042f000006f501000041000000000010043f0000001201000039000000040010043f000006a8010000410000188e0001043000000000010000190000188e00010430000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000184c0000613d000000000201043b000006fd01200167000000000101041a000000000001004b0000183d0000613d0000000101100270000000000001042d000000000102041a000000000001004b0000000001000039000000010100c0390000184b0000613d0000000103200039000000000303041a000000000003004b0000184b0000613d0000000201200039000000000101041a000000000001004b00000003010000390000000201006039000000000001042d00000000010000190000188e00010430000000000001042f000006240010009c00000624010080410000004001100210000006240020009c00000624020080410000006002200210000000000112019f0000000002000414000006240020009c0000062402008041000000c002200210000000000112019f00000627011001c70000801002000039188c18870000040f0000000100200190000018620000613d000000000101043b000000000001042d00000000010000190000188e0001043000000000050100190000000000200443000000050030008c000018720000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b0000186a0000413d000006240030009c000006240300804100000060013002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f00000702011001c70000000002050019188c18870000040f0000000100200190000018810000613d000000000101043b000000000001042d000000000001042f00001885002104210000000102000039000000000001042d0000000002000019000000000001042d0000188a002104230000000102000039000000000001042d0000000002000019000000000001042d0000188c000004320000188d0001042e0000188e00010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff02000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0000000000000000000000000000000000000000000000000000000000001518000000000000000000000000000000000000000000000000000470de4df820000000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000ffffffffffffff400200000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f00000002000000000000000000000000000000c00000010000000000000000001e4fbdf7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000c0000000000000000000000000000000000000000000000000000000000000000000000000787a08a500000000000000000000000000000000000000000000000000000000b2678ef000000000000000000000000000000000000000000000000000000000df1e3b7e00000000000000000000000000000000000000000000000000000000ea26fa2c00000000000000000000000000000000000000000000000000000000eef3b2cf00000000000000000000000000000000000000000000000000000000eef3b2d000000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000f5c823ce00000000000000000000000000000000000000000000000000000000ea26fa2d00000000000000000000000000000000000000000000000000000000ec56c7f400000000000000000000000000000000000000000000000000000000e65a2e7d00000000000000000000000000000000000000000000000000000000e65a2e7e00000000000000000000000000000000000000000000000000000000e8ee067000000000000000000000000000000000000000000000000000000000e92820e600000000000000000000000000000000000000000000000000000000df1e3b7f00000000000000000000000000000000000000000000000000000000e0d152af00000000000000000000000000000000000000000000000000000000c8e66bea00000000000000000000000000000000000000000000000000000000d147129500000000000000000000000000000000000000000000000000000000d147129600000000000000000000000000000000000000000000000000000000d9ba62b300000000000000000000000000000000000000000000000000000000dd6a4c6500000000000000000000000000000000000000000000000000000000c8e66beb00000000000000000000000000000000000000000000000000000000ca18117000000000000000000000000000000000000000000000000000000000c51a2bb900000000000000000000000000000000000000000000000000000000c51a2bba00000000000000000000000000000000000000000000000000000000c600589300000000000000000000000000000000000000000000000000000000b2678ef100000000000000000000000000000000000000000000000000000000c2435894000000000000000000000000000000000000000000000000000000008f1f1a260000000000000000000000000000000000000000000000000000000096fd750f000000000000000000000000000000000000000000000000000000009f715f5f000000000000000000000000000000000000000000000000000000009f715f6000000000000000000000000000000000000000000000000000000000a9f8d18100000000000000000000000000000000000000000000000000000000ad5c46480000000000000000000000000000000000000000000000000000000096fd7510000000000000000000000000000000000000000000000000000000009ca423b30000000000000000000000000000000000000000000000000000000094fc19e30000000000000000000000000000000000000000000000000000000094fc19e4000000000000000000000000000000000000000000000000000000009618b31c000000000000000000000000000000000000000000000000000000008f1f1a27000000000000000000000000000000000000000000000000000000008fc593a40000000000000000000000000000000000000000000000000000000084ae2bc5000000000000000000000000000000000000000000000000000000008da5cb5a000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000008dfc3933000000000000000000000000000000000000000000000000000000008e4f8d480000000000000000000000000000000000000000000000000000000084ae2bc60000000000000000000000000000000000000000000000000000000086b3cd26000000000000000000000000000000000000000000000000000000007e08b5b2000000000000000000000000000000000000000000000000000000007e08b5b300000000000000000000000000000000000000000000000000000000811c508900000000000000000000000000000000000000000000000000000000787a08a6000000000000000000000000000000000000000000000000000000007b4af37c0000000000000000000000000000000000000000000000000000000041a0894c000000000000000000000000000000000000000000000000000000005fd9491c000000000000000000000000000000000000000000000000000000006d12ff5100000000000000000000000000000000000000000000000000000000715018a500000000000000000000000000000000000000000000000000000000715018a60000000000000000000000000000000000000000000000000000000072779cba0000000000000000000000000000000000000000000000000000000077f793c7000000000000000000000000000000000000000000000000000000006d12ff5200000000000000000000000000000000000000000000000000000000713494d7000000000000000000000000000000000000000000000000000000006756a1c6000000000000000000000000000000000000000000000000000000006756a1c70000000000000000000000000000000000000000000000000000000069f0ee33000000000000000000000000000000000000000000000000000000005fd9491d0000000000000000000000000000000000000000000000000000000062de3bd1000000000000000000000000000000000000000000000000000000004fc3f4190000000000000000000000000000000000000000000000000000000059058ad00000000000000000000000000000000000000000000000000000000059058ad1000000000000000000000000000000000000000000000000000000005a5ccef0000000000000000000000000000000000000000000000000000000005c7421e3000000000000000000000000000000000000000000000000000000004fc3f41a00000000000000000000000000000000000000000000000000000000542f9e6a0000000000000000000000000000000000000000000000000000000048cd4cb00000000000000000000000000000000000000000000000000000000048cd4cb1000000000000000000000000000000000000000000000000000000004e3e6fe10000000000000000000000000000000000000000000000000000000041a0894d00000000000000000000000000000000000000000000000000000000445e02d8000000000000000000000000000000000000000000000000000000002b3f1957000000000000000000000000000000000000000000000000000000003223c02f000000000000000000000000000000000000000000000000000000003ccfd60a000000000000000000000000000000000000000000000000000000003ccfd60b000000000000000000000000000000000000000000000000000000003e89bb130000000000000000000000000000000000000000000000000000000040f5da9e000000000000000000000000000000000000000000000000000000003223c03000000000000000000000000000000000000000000000000000000000372500ab00000000000000000000000000000000000000000000000000000000304fbfc600000000000000000000000000000000000000000000000000000000304fbfc70000000000000000000000000000000000000000000000000000000031d7a262000000000000000000000000000000000000000000000000000000002b3f1958000000000000000000000000000000000000000000000000000000002fc96ce6000000000000000000000000000000000000000000000000000000001a267cd1000000000000000000000000000000000000000000000000000000001f6a3bb8000000000000000000000000000000000000000000000000000000001f6a3bb900000000000000000000000000000000000000000000000000000000234f3f1b0000000000000000000000000000000000000000000000000000000024b4464e000000000000000000000000000000000000000000000000000000001a267cd2000000000000000000000000000000000000000000000000000000001e57057d00000000000000000000000000000000000000000000000000000000157e204b00000000000000000000000000000000000000000000000000000000157e204c0000000000000000000000000000000000000000000000000000000017820fd0000000000000000000000000000000000000000000000000000000000682c0310000000000000000000000000000000000000000000000000000000010d967590000000000000000000000000000000000000020000000800000000000000000118cdaa700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000080000000000000000002000000000000000000000000000000000000600000000000000000000000007152312bf5cf776256aadaa3e2daf52b5095f4118a657aafae2bd749931e0f98d2a50ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0000000000000000000000000000000000000020000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000047cd2fa60000000000000000000000000000000000000000000000000000000070a0823100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffff23b872dd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000042966c68000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000020000000000000000000000000e2dbc44c627e3876b04b29d12596a77c7d0fa585ccb754b9fcd92e48d813dd77ff0b21e60000000000000000000000000000000000000000000000000000000041fde9ef0000000000000000000000000000000000000000000000000000000072932dd3000000000000000000000000000000000000000000000000000000000c02d44e000000000000000000000000000000000000000000000000000000000e6ce2f100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000080000000000000000000000000000000000000000000000000000000c00000008000000000000000000000000000000000000000000000000000000000000000000000000018fb586402000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000fbb67fda52d4bfb8bf3d9f63cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff3fbb8db292349eecec0f157746522d22a04be58c69c690e5af7d7f15a6a04d4d87e331ada0d0e61e9a4196bf4994f2519193d70a601daff346c4276d591664da9aa9059cbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000515d3e810000000000000000000000000000000000000000000000000000000002000002000000000000000000000000000000440000000000000000000000000bd772fd008a8dd5673c42a4f50f72220b2603eee55113cd6c38ff78d71e644fedd999f8000000000000000000000000000000000000000000000000000000000000000000000000000000007712fa47387542819d4e35a23f8116c90c18767cd0a7ceb410ade2d440d8ed59d6b338fe480f98025101655790e0de736edddabe3b87f109000000000000000000000000000000000000000000000000000000000000000000000000000000003439153eb7af838ad19d56e1571fbd09333c28090200000000000000000000000000000000000080000000000000000000000000e0a2f8482bbba7e119c069eb63409ac33b15fc516cffed25aeabb6a9669e07c242cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd1000000000000000000000000000000000000000000000000000000000545ffff0000000000000000000000000000000000000000000000000000000000054600000000000000000000000000000000000000000000000001a055690d9db8000000000000000000000000000000000000000000000000000000000000ad251c2700000000000000000000000000000000000000040000001c00000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000158d620b300000000000000000000000000000000000000000000000000000000f721e9425607d38abda58b925d2a080b3aefa127d46973d2683875dc87cb9a6bf1fa1762000000000000000000000000000000000000000000000000000000006cb4090800000000000000000000000000000000000000000000000000000000f920b24ea96b3814655944622f9eb86875e3193c5de1a9de018777e6c8705cee4705d68400000000000000000000000000000000000000000000000000000000095ea7b300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1f04e45aaf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffff00000000000000000000000000000000000000e40000000000000000000000000000000000000000000000000000000000000000000000fbb67fda52d4bfb8bee9a3d31ddc75e6f55428f56a99300650dd35074dbe47cffa59e8292fe6f2886ffbfd2f4000000000000000000000000000000000000000000000000000000000aa8a9b980000000000000000000000000000000000000000000000000000000086257f0afab037798cc4548a6d86125f52c92410a1e29aff03d787d49dac20db00000000000000000000000000000000000000a0000000800000000000000000d2ade556000000000000000000000000000000000000000000000000000000008fe6f7d80000000000000000000000000000000000000000000000000000000070e9a55a00000000000000000000000000000000000000000000000000000000e424ed553a53c3a900c875ed34d63043e4dfb799427ee8ae0836b046a603c90e00000000000000000000000000000000000000000000000000000000f5a267f161104228000000000000000000000000000000000000000000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f3900000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000003ffffffe0750b219c0000000000000000000000000000000000000000000000000000000040c10f1900000000000000000000000000000000000000000000000000000000fc30cddea38e2bf4d6ea7d3f9ed3b6ad7f176419f4963bd81318067a4aee73fe0df723dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000080000000000000000000000000000000000000000000000000000000000000000000000000bac65e5b602fe2ca000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe04e23d035000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000800000000000000000e5b88ba483d0be6c345877ef44085c5e1edc7fa963ccb86223d06a681f9306753a6c77df00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdaae9aa758637a0d349f036f099afd70aa88d8ac63fce096321de512ffebc16ca051d58ced8df58040b29d2c939da70a826ae40290f77c9a66b38b8b85315f6502000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd0fc2d7cabdd70d07801fec85ad015d9ddc48efab396fafdd1a20726b1b8b76

Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.