ETH Price: $1,649.67 (+4.99%)

Contract

0x09Ee83D8fA0f3F03f2aefad6a82353c1e5DE5705

Overview

ETH Balance

32.5175 ETH

ETH Value

$53,643.28 (@ $1,649.67/ETH)
Transaction Hash
Method
Block
From
To
Claim Rewards65766762025-04-12 20:52:168 secs ago1744491136IN
0x09Ee83D8...1e5DE5705
0 ETH0.000006390.04525
Purchase Initial...65766742025-04-12 20:52:1410 secs ago1744491134IN
0x09Ee83D8...1e5DE5705
0.0075 ETH0.000006640.04525
Get Free Starter...65766732025-04-12 20:52:1311 secs ago1744491133IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005360.04525
Claim Rewards65766722025-04-12 20:52:1212 secs ago1744491132IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005640.04525
Claim Rewards65766682025-04-12 20:52:0816 secs ago1744491128IN
0x09Ee83D8...1e5DE5705
0 ETH0.000007120.04525
Claim Rewards65766662025-04-12 20:52:0618 secs ago1744491126IN
0x09Ee83D8...1e5DE5705
0 ETH0.000006770.04525
Get Free Starter...65766652025-04-12 20:52:0519 secs ago1744491125IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005360.04525
Claim Rewards65766642025-04-12 20:52:0420 secs ago1744491124IN
0x09Ee83D8...1e5DE5705
0 ETH0.000006120.04525
Claim Rewards65766612025-04-12 20:52:0123 secs ago1744491121IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005760.04525
Claim Rewards65766612025-04-12 20:52:0123 secs ago1744491121IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005720.04525
Claim Rewards65766582025-04-12 20:51:5826 secs ago1744491118IN
0x09Ee83D8...1e5DE5705
0 ETH0.00000640.04525
Claim Rewards65766572025-04-12 20:51:5727 secs ago1744491117IN
0x09Ee83D8...1e5DE5705
0 ETH0.000004440.04525
Get Free Starter...65766492025-04-12 20:51:4935 secs ago1744491109IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005360.04525
Claim Rewards65766492025-04-12 20:51:4935 secs ago1744491109IN
0x09Ee83D8...1e5DE5705
0 ETH0.000006690.04525
Claim Rewards65766472025-04-12 20:51:4737 secs ago1744491107IN
0x09Ee83D8...1e5DE5705
0 ETH0.000007330.04525
Purchase Initial...65766442025-04-12 20:51:4440 secs ago1744491104IN
0x09Ee83D8...1e5DE5705
0.0075 ETH0.000008470.04525
Claim Rewards65766432025-04-12 20:51:4341 secs ago1744491103IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005640.04525
Claim Rewards65766422025-04-12 20:51:4242 secs ago1744491102IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005730.04525
Claim Rewards65766422025-04-12 20:51:4242 secs ago1744491102IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005640.04525
Purchase Initial...65766412025-04-12 20:51:4143 secs ago1744491101IN
0x09Ee83D8...1e5DE5705
0.0075 ETH0.000008060.04525
Claim Rewards65766392025-04-12 20:51:3945 secs ago1744491099IN
0x09Ee83D8...1e5DE5705
0 ETH0.000006420.04525
Purchase Initial...65766392025-04-12 20:51:3945 secs ago1744491099IN
0x09Ee83D8...1e5DE5705
0.0075 ETH0.000006340.04525
Get Free Starter...65766372025-04-12 20:51:3747 secs ago1744491097IN
0x09Ee83D8...1e5DE5705
0 ETH0.000005360.04525
Claim Rewards65766302025-04-12 20:51:3054 secs ago1744491090IN
0x09Ee83D8...1e5DE5705
0 ETH0.000006650.04525
Claim Rewards65766302025-04-12 20:51:3054 secs ago1744491090IN
0x09Ee83D8...1e5DE5705
0 ETH0.000006690.04525
View all transactions

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
65766742025-04-12 20:52:1410 secs ago1744491134
0x09Ee83D8...1e5DE5705
0.0075 ETH
65766442025-04-12 20:51:4440 secs ago1744491104
0x09Ee83D8...1e5DE5705
0.0075 ETH
65766412025-04-12 20:51:4143 secs ago1744491101
0x09Ee83D8...1e5DE5705
0.0075 ETH
65766392025-04-12 20:51:3945 secs ago1744491099
0x09Ee83D8...1e5DE5705
0.0075 ETH
65766142025-04-12 20:51:141 min ago1744491074
0x09Ee83D8...1e5DE5705
0.0075 ETH
65765802025-04-12 20:50:401 min ago1744491040
0x09Ee83D8...1e5DE5705
0.0075 ETH
65765572025-04-12 20:50:172 mins ago1744491017
0x09Ee83D8...1e5DE5705
0.0075 ETH
65765202025-04-12 20:49:402 mins ago1744490980
0x09Ee83D8...1e5DE5705
0.0075 ETH
65764682025-04-12 20:48:483 mins ago1744490928
0x09Ee83D8...1e5DE5705
0.0075 ETH
65764562025-04-12 20:48:363 mins ago1744490916
0x09Ee83D8...1e5DE5705
0.0075 ETH
65764282025-04-12 20:48:084 mins ago1744490888
0x09Ee83D8...1e5DE5705
0.0075 ETH
65763752025-04-12 20:47:155 mins ago1744490835
0x09Ee83D8...1e5DE5705
0.0075 ETH
65763492025-04-12 20:46:495 mins ago1744490809
0x09Ee83D8...1e5DE5705
0.0075 ETH
65762942025-04-12 20:45:546 mins ago1744490754
0x09Ee83D8...1e5DE5705
0.0075 ETH
65762622025-04-12 20:45:147 mins ago1744490714
0x09Ee83D8...1e5DE5705
0.0075 ETH
65762562025-04-12 20:45:087 mins ago1744490708
0x09Ee83D8...1e5DE5705
0.0075 ETH
65762302025-04-12 20:44:427 mins ago1744490682
0x09Ee83D8...1e5DE5705
0.0075 ETH
65762112025-04-12 20:44:238 mins ago1744490663
0x09Ee83D8...1e5DE5705
0.0075 ETH
65761902025-04-12 20:44:028 mins ago1744490642
0x09Ee83D8...1e5DE5705
0.0075 ETH
65761812025-04-12 20:43:538 mins ago1744490633
0x09Ee83D8...1e5DE5705
0.0075 ETH
65761652025-04-12 20:43:378 mins ago1744490617
0x09Ee83D8...1e5DE5705
0.0075 ETH
65761632025-04-12 20:43:358 mins ago1744490615
0x09Ee83D8...1e5DE5705
0.0075 ETH
65760572025-04-12 20:41:4910 mins ago1744490509
0x09Ee83D8...1e5DE5705
0.0075 ETH
65760432025-04-12 20:41:3510 mins ago1744490495
0x09Ee83D8...1e5DE5705
0.0075 ETH
65760402025-04-12 20:41:3210 mins ago1744490492
0x09Ee83D8...1e5DE5705
0.0075 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Main

Compiler Version
v0.8.26+commit.8a97fa7a

ZkSolc Version
v1.5.11

Optimization Enabled:
Yes with Mode 3

Other Settings:
cancun EvmVersion
File 1 of 11 : Main.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {Ownable} from "@openzeppelin/access/Ownable.sol";
import {EnumerableSetLib} from "solady/utils/EnumerableSetLib.sol";
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";

import {IBigcoin} from "./interfaces/IBigcoin.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";

// Bigcoin main program
contract Main is Ownable {
    using EnumerableSetLib for EnumerableSetLib.Uint256Set;

    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    //            STORAGE
    // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    /// @dev Bigcoin token address.
    address public bigcoin;

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

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

    /// @dev Tracks bigcoin per single hash.
    uint256 public cumulativeBigcoinPerHash;

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

    /// @dev Initial referral fee is 2.5%.
    uint256 public referralFee = 0.025e18;

    /// @dev Initial burn is 75%.
    uint256 public burnPct = 0.75e18;

    /// @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 playerBigcoinDebt;

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

    /// @dev Tracks each miners coords for a player
    mapping(address => mapping(uint256 => mapping(uint256 => bool))) public playerOccupiedCoords;

    mapping(address => uint256) public lastFacilityUpgradeTimestamp;

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

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

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

    /// @dev Purchasing initial facility price in ETH.
    uint256 public initialFacilityPrice = 0.005 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 4,200,000 blocks, roughly 50 days
    uint256 public constant HALVING_INTERVAL = 4_200_000;

    /// @dev Initial bigcoin per block
    uint256 public constant INITIAL_BIGCOIN_PER_BLOCK = 2.5e18; // 2.5 Bigcoin 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,
            type(uint256).max,
            type(uint256).max,
            100,
            1,
            type(uint256).max, // this is the free starter miner, people cannot buy it
            false
        );

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

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

        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;
        facility.x = newFacility.x;
        facility.y = newFacility.y;

        emit Events.InitialFacilityPurchased(msg.sender);
    }

    /**
     * @dev All new players can redeem 1 free miner.
     *
     * Players are not required to redeem a free miner.
     */
    function getFreeStarterMiner(uint256 x, uint256 y) external {
        if (acquiredStarterMiner[msg.sender]) {
            revert Errors.StarterMinerAlreadyAcquired();
        }

        acquiredStarterMiner[msg.sender] = true;

        Miner memory miner = miners[STARTER_MINER_INDEX];
        Facility storage facility = ownerToFacility[msg.sender];

        if (_isInvalidCoordinates(x, y, facility.x, facility.y)) {
            revert Errors.InvalidMinerCoordinates();
        }

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

        miner.x = x;
        miner.y = y;
        miner.id = ++universalMinerId;
        playerOccupiedCoords[msg.sender][x][y] = true;

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

        // increase facility miners
        facility.currMiners++;

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

        // emit Events.FreeMinerRedeemed(msg.sender);
        emit Events.MinerBought(msg.sender, STARTER_MINER_INDEX, 0, universalMinerId, x, y);

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

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

        if (_isInvalidCoordinates(x, y, facility.x, facility.y)) {
            revert Errors.InvalidMinerCoordinates();
        }

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

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

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

        // transfer correct amt of bigcoin
        IBigcoin(bigcoin).transferFrom(msg.sender, address(this), miner.cost);

        // burn
        IBigcoin(bigcoin).burn(FixedPointMathLib.mulWad(miner.cost, burnPct));

        miner.x = x;
        miner.y = y;
        miner.id = ++universalMinerId;
        playerOccupiedCoords[msg.sender][x][y] = true;

        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, x, y);

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

    /**
     * @dev Sell miners, if there's a secondary market, player will get bigcoin in return.
     *
     * Players will sell miners in the case they run out of spots in their facility to put new miners.
     */
    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 there's not enough bigcoin in this contract to pay out, revert
        if (secondHandPrice > IBigcoin(bigcoin).balanceOf(address(this))) {
            revert Errors.GreatDepression();
        }

        Facility storage facility = ownerToFacility[msg.sender];

        // decrease facility miners
        facility.currMiners--;

        // decrease power consumption from factory
        facility.currPowerOutput -= miner.powerConsumption;

        playerMinersOwned[msg.sender].remove(minerId);
        delete playerMinersId[minerId];
        playerOccupiedCoords[msg.sender][miner.x][miner.y] = false;

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

        _decreaseHashrate(msg.sender, miner.hashrate);

        if (secondHandPrice > 0) {
            IBigcoin(bigcoin).transfer(msg.sender, secondHandPrice);
        }
    }

    /**
     * @dev Purchase larger or more power output facility.
     *
     * Players must linearly climb the facilities.
     */
    function buyNewFacility() external {
        // 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 (IBigcoin(bigcoin).balanceOf(msg.sender) < newFacility.cost) {
            revert Errors.TooPoor();
        }

        IBigcoin(bigcoin).transferFrom(msg.sender, address(this), newFacility.cost);

        // burn
        IBigcoin(bigcoin).burn(FixedPointMathLib.mulWad(newFacility.cost, burnPct));

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

        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;

        // referral bonus
        uint256 referralBonus = FixedPointMathLib.mulWad(rewards, referralFee);
        uint256 finalRewards = rewards - referralBonus;

        IBigcoin(bigcoin).mint(msg.sender, finalRewards);

        address referrer = referrals[msg.sender];
        if (referrer != address(0)) {
            IBigcoin(bigcoin).mint(referrer, referralBonus);
            referralBonusPaid[referrer] += referralBonus;
        } else {
            // else mint referral fee to this contract
            IBigcoin(bigcoin).mint(address(this), referralBonus);
            referralBonusPaid[address(this)] += referralBonus;
        }

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

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

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

        // if we have not updated rewards and a halvening occurs, we must add the different
        // bigcoin emissions per halvening
        uint256 currentBlock = lastRewardBlock;
        uint256 lastBigcoinPerBlock =
            INITIAL_BIGCOIN_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
            cumulativeBigcoinPerHash +=
                ((lastBigcoinPerBlock * (endBlock - currentBlock) * REWARDS_PRECISION) / totalHashrate);

            // move to next segment
            currentBlock = endBlock;

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

        lastRewardBlock = block.number;
    }

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

        playerPendingRewards[player] +=
            (playerHashrate[player] * (cumulativeBigcoinPerHash - playerBigcoinDebt[player])) / REWARDS_PRECISION;

        playerBigcoinDebt[player] = cumulativeBigcoinPerHash;
    }

    /**
     * @dev Increase players hashrate.
     */
    function _increaseHashrate(address player, uint256 hashrate) internal {
        // only start rewarding bigcoin per block when the first miner is added
        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]);
    }

    /**
     * @dev checks the miners x,y coords are within bounds and there isn't an existent miner at that position.
     */
    function _isInvalidCoordinates(uint256 desiredX, uint256 desiredY, uint256 facilityX, uint256 facilityY)
        internal
        view
        returns (bool)
    {
        if (desiredX >= facilityX || desiredY >= facilityY) {
            return true;
        }

        return playerOccupiedCoords[msg.sender][desiredX][desiredY];
    }

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

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

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

        return INITIAL_BIGCOIN_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);
        }

        uint256 currentBlock = lastRewardBlock;
        uint256 lastBigcoinPerBlock =
            INITIAL_BIGCOIN_PER_BLOCK / (2 ** ((lastRewardBlock - startBlock) / HALVING_INTERVAL));

        uint256 simulatedCumulativeBigcoinPerHash = cumulativeBigcoinPerHash;

        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) {
                simulatedCumulativeBigcoinPerHash +=
                    ((lastBigcoinPerBlock * (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) {
                lastBigcoinPerBlock /= 2;
            }
        }

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

    /**
     * @dev Get current bigcoin a player mines per block.
     */
    function playerBigcoinPerBlock(address player) external view returns (uint256) {
        if (totalHashrate == 0) {
            return 0; // Prevent division by zero
        }

        uint256 currBigcoinPerBlock =
            INITIAL_BIGCOIN_PER_BLOCK / (2 ** ((block.number - startBlock) / HALVING_INTERVAL));

        return FixedPointMathLib.mulDiv(playerHashrate[player], currBigcoinPerBlock, 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;
    }

    /**
     * @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, 0, 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,
        uint256 x,
        uint256 y
    ) external onlyOwner {
        if (x * y != maxMiners) {
            revert Errors.FacilityDimensionsInvalid();
        }

        if (facilities[facilityCount].x > x || facilities[facilityCount].y > y) {
            revert Errors.FacilityDimensionsInvalid();
        }

        if (facilities[facilityCount].totalPowerOutput > totalPowerOutput) {
            revert Errors.InvalidPowerOutput();
        }

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

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

    /**
     * @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 setBigcoin(address _bigcoin) external onlyOwner {
        bigcoin = _bigcoin;
    }

    function setBigtoshi(address _bigtoshi) external onlyOwner {
        bigtoshi = _bigtoshi;
    }

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

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

        referralFee = fee;
    }

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

        burnPct = burn;
    }

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

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

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

    function withdrawBigcoin(uint256 amt) external onlyOwner {
        IBigcoin(bigcoin).transfer(bigtoshi, 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);
    }
}

File 2 of 11 : 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 3 of 11 : 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 4 of 11 : 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/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 5 of 11 : IBigcoin.sol
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.19;

interface IBigcoin {
    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);
}

File 6 of 11 : Miner.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

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

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

/**
 * @dev Current player's facility.
 */
struct Facility {
    uint256 facilityIndex;
    uint256 maxMiners; // x * y
    uint256 currMiners;
    uint256 totalPowerOutput;
    uint256 currPowerOutput;
    uint256 x; // number of x quadrants
    uint256 y; // number of y qudrants
}

File 8 of 11 : NewFacility.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

/**
 * @dev Facilities that can be purchased in game.
 */
struct NewFacility {
    uint256 maxMiners;
    uint256 totalPowerOutput;
    uint256 cost;
    bool inProduction;
    uint256 x; // number of x quadrants
    uint256 y; // number of y qudrants
}

File 9 of 11 : Errors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

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 FacilityDimensionsInvalid();
    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();
}

File 10 of 11 : Events.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

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, uint256 x, uint256 y
    );

    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,
        uint256 x,
        uint256 y
    );

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

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

File 11 of 11 : 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
{
  "viaIR": false,
  "codegen": "yul",
  "remappings": [
    "@openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "solady/=lib/solady/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "evmVersion": "cancun",
  "outputSelection": {
    "*": {
      "*": [
        "abi"
      ]
    }
  },
  "optimizer": {
    "enabled": true,
    "mode": "3",
    "fallback_to_optimizing_for_size": false,
    "disable_system_request_memoization": true
  },
  "metadata": {},
  "libraries": {},
  "enableEraVMExtensions": false,
  "forceEVMLA": false
}

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":"FacilityDimensionsInvalid","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":"InvalidMinerCoordinates","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":"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"},{"indexed":false,"internalType":"uint256","name":"x","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"y","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":"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"},{"indexed":false,"internalType":"uint256","name":"x","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"y","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"},{"indexed":false,"internalType":"uint256","name":"x","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"y","type":"uint256"}],"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_BIGCOIN_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":[{"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"},{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"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":"bigcoin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bigtoshi","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","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"},{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"buyMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyNewFacility","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":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cumulativeBigcoinPerHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"},{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facilityCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBigcoinPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"getFreeStarterMiner","outputs":[],"stateMutability":"nonpayable","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":"x","type":"uint256"},{"internalType":"uint256","name":"y","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":[],"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":"x","type":"uint256"},{"internalType":"uint256","name":"y","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":"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"},{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","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":"playerBigcoinDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"playerBigcoinPerBlock","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":"x","type":"uint256"},{"internalType":"uint256","name":"y","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"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"playerOccupiedCoords","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":"uint256","name":"minerId","type":"uint256"}],"name":"sellMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bigcoin","type":"address"}],"name":"setBigcoin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bigtoshi","type":"address"}],"name":"setBigtoshi","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":"uint256","name":"_initialPrice","type":"uint256"}],"name":"setInitialFacilityPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setReferralFee","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":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"withdrawBigcoin","outputs":[],"stateMutability":"nonpayable","type":"function"}]

9c4d535b0000000000000000000000000000000000000000000000000000000000000000010006e1c8168773598c4871d2cb6bfd7749522704aa9a639d44893da0b9389200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x00010000000000020016000000000002000000000001035500000001002001900000003c0000c13d000000600210027000000614022001970000008003000039000000400030043f000000040020008c000015b80000413d000000000301043b000000e003300270000006210030009c0000006f0000a13d000006220030009c0000009e0000a13d000006230030009c000000db0000a13d000006240030009c000001e60000a13d000006250030009c000003e20000a13d000006260030009c000009400000613d000006270030009c000009750000613d000006280030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000601043b000006160060009c000015b80000213d000000000100041a00000616021001970000000005000411000000000052004b0000097f0000c13d000000000006004b000000440000613d0000061501100197000000000161019f000000000010041b0000000001000414000006140010009c0000061401008041000000c00110021000000617011001c70000800d0200003900000003030000390000061804000041184d18430000040f000000010020019000000b2a0000c13d000015b80000013d000000c001000039000000400010043f0000000001000416000000000001004b000015b80000c13d0000000006000411000000000006004b000000490000c13d0000068301000041000000000010043f000000040000043f00000682010000410000184f00010430000000000100041a0000061502100197000000000262019f000000000020041b00000000020004140000061605100197000006140020009c0000061402008041000000c00120021000000617011001c70000800d0200003900000003030000390000061804000041184d18430000040f0000000100200190000015b80000613d00000619010000410000000b02000039000000000012041b0000061a010000410000000c02000039000000000012041b0000061b010000410000000d02000039000000000012041b0000061c010000410000001e02000039000000000012041b0000000602000039000000000102041a000000010110003a000000d00000c13d000006d601000041000000000010043f0000001101000039000000040010043f00000682010000410000184f00010430000006520030009c000000ba0000213d0000066a0030009c000000f70000213d000006760030009c000001f60000213d0000067c0030009c0000032e0000213d0000067f0030009c000005d10000613d000006800030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000000000010043f0000001201000039000000200010043f00000040020000390000000001000019184d18100000040f0000000502100039000000000202041a0000000403100039000000000303041a0000000304100039000000000404041a0000000205100039000000000505041a0000000106100039000000000606041a000000000101041a000000800010043f000000a00060043f000000c00050043f000000ff004001900000000001000039000000010100c039000000e00010043f000001000030043f000001200020043f000006d7010000410000184e0001042e0000063b0030009c000000e80000213d000006470030009c000001c90000213d0000064d0030009c000002cb0000213d000006500030009c000004e00000613d000006510030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000000000200041a00000616032001970000000002000411000000000023004b0000097a0000c13d000006aa0010009c000001c50000813d0000000c02000039000000000012041b00000000010000190000184e0001042e000006530030009c000001090000213d0000065f0030009c000002080000213d000006650030009c0000033f0000213d000006680030009c000006100000613d000006690030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000000f01000039000007d70000013d000000000012041b000000800010043f000000400400043d0000061d0040009c000001160000413d000006d601000041000000000010043f0000004101000039000000040010043f00000682010000410000184f00010430000006300030009c000001b10000213d000006360030009c0000024f0000213d000006390030009c0000040b0000613d0000063a0030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000801000039000007db0000013d0000063c0030009c000001db0000213d000006420030009c000002d40000213d000006450030009c000004e50000613d000006460030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000069b01000041000000800010043f00000684010000410000184e0001042e0000066b0030009c000002130000213d000006710030009c000003550000213d000006740030009c000006340000613d000006750030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000000000010043f0000001801000039000007d70000013d000006540030009c000002330000213d0000065a0030009c000003710000213d0000065d0030009c000006400000613d0000065e0030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000901000039000007db0000013d0000010002400039000000400020043f000000a0034000390000000102000039001200000003001d000000000023043500000080034000390000006402000039001000000003001d0000000000230435000000c003400039000000010200008a001100000003001d00000000002304350000006003400039000d00000003001d00000000002304350000004003400039000c00000003001d00000000002304350000002003400039000b00000003001d00000000002304350000000000140435000e00000004001d000000e001400039000f00000001001d0000000000010435000000800100043d000000000010043f0000001101000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d0000000e020000290000000002020433000000000101043b000000000021041b0000000b0200002900000000020204330000000103100039000000000023041b0000000c0200002900000000020204330000000203100039000000000023041b0000000d0200002900000000020204330000000303100039000000000023041b000000100200002900000000020204330000000403100039000000000023041b000000120200002900000000020204330000000503100039000000000023041b000000110200002900000000020204330000000603100039000000000023041b0000000701100039000000000201041a000006d9022001970000000f030000290000000003030433000000000003004b000000010220c1bf000000000021041b000000400200043d0000061f0020009c000000d50000213d000000c001200039000000400010043f000000a00320003900000002010000390000000000130435000000800520003900000000001504350000004007200039000000010100008a000000000017043500000020092000390000001c01000039000000000019043500000004010000390000000000120435000000600820003900000000000804350000000706000039000000000106041a000000010110003a000000690000613d000000000016041b000000000010043f0000001201000039000000200010043f000e00000002001d00000040020000390000000001000019001200000003001d001100000005001d000f00000007001d001000000008001d000d00000009001d184d18100000040f0000000e020000290000000002020433000000000021041b0000000d0200002900000000020204330000000103100039000000000023041b0000000f0200002900000000020204330000000203100039000000000023041b0000000302100039000000000302041a000006d90330019700000010040000290000000004040433000000000004004b000000010330c1bf000000000032041b000000110200002900000000020204330000000403100039000000000023041b000000050110003900000012020000290000000002020433000000000021041b0000000701000039000000000101041a000000a00010043f000000800200043d0000014000000443000001600020044300000020020000390000018000200443000001a00010044300000100002004430000000201000039000001200010044300000620010000410000184e0001042e000006310030009c000002970000213d000006340030009c0000047c0000613d000006350030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000000000200041a00000616032001970000000002000411000000000023004b0000097a0000c13d0000069b0010009c000009a30000a13d000006ab01000041000000000010043f0000068c010000410000184f00010430000006480030009c000002e40000213d0000064b0030009c000005260000613d0000064c0030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001a01000039000007d70000013d0000063d0030009c000002ed0000213d000006400030009c0000052b0000613d000006410030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000401000039000004d90000013d0000062b0030009c000003010000213d0000062e0030009c0000059a0000613d0000062f0030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000000000010043f00000014010000390000030e0000013d000006770030009c0000037a0000213d0000067a0030009c0000064b0000613d0000067b0030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001d01000039000007d70000013d000006600030009c0000038a0000213d000006630030009c000006880000613d000006640030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000301000039000007db0000013d0000066c0030009c000003b30000213d0000066f0030009c0000071a0000613d000006700030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000001000411184d16100000040f0000000001000411000000000010043f0000000f01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000000001004b000009fd0000c13d000006ca01000041000000000010043f0000068c010000410000184f00010430000006550030009c000003d80000213d000006580030009c000007300000613d000006590030009c000015b80000c13d000000440020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000616021001970000000001000411000000000012004b0000093b0000c13d0000000601000039000000000101041a000000000013004b00000aaa0000a13d000006b101000041000000000010043f0000068c010000410000184f00010430000006370030009c000004ab0000613d000006380030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d000000000200041a00000616032001970000000002000411000000000023004b0000097a0000c13d0000000102000039000000000202041a0000000203000039000000000303041a0000069404000041000000800040043f0000000401100370000000000101043b0000061603300197000000840030043f000000a40010043f00000000010004140000061602200197000006140010009c0000061401008041000000c0011002100000069e011001c7184d18430000040f000000800900003900000060031002700000061403300197000000200030008c000000200a000039000000000a0340190000001f05a0018f0000002006a0019000000080046001bf0000027e0000613d000000000701034f000000007807043c0000000009890436000000000049004b0000027a0000c13d000000000005004b0000028b0000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f00000000005404350000000100200190000009a70000613d000000800100003900000000020a001900120000000a001d184d15e50000040f000000120100002900000080021001bf0000008001000039184d15f70000040f00000000010000190000184e0001042e000006320030009c000004ca0000613d000006330030009c000015b80000c13d000000440020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000402100370000000000202043b001200000002001d0000002401100370000000000201043b000000000002004b0000000001000039000000010100c039001100000002001d000000000012004b000015b80000c13d000000000100041a00000616021001970000000001000411000000000012004b0000093b0000c13d0000068501000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006140010009c0000061401008041000000c00110021000000697011001c70000800502000039184d18480000040f0000000100200190000012c40000613d000000000101043b0000001202000029000000000012004b000002c70000413d0000000701000039000000000101041a000000000012004b00000d5a0000a13d0000069a01000041000000000010043f0000068c010000410000184f000104300000064e0030009c000005300000613d0000064f0030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000601000039000007db0000013d000006430030009c000005470000613d000006440030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001701000039000004d50000013d000006490030009c0000054f0000613d0000064a0030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000c01000039000007db0000013d0000063e0030009c000005950000613d0000063f0030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001b01000039000000200010043f00000040020000390000000001000019184d18100000040f000003e00000013d0000062c0030009c000005c40000613d0000062d0030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000000000010043f0000001101000039000000200010043f00000040020000390000000001000019184d18100000040f0000000702100039000000000202041a0000000603100039000000000303041a0000000504100039000000000404041a0000000405100039000000000505041a0000000306100039000000000606041a0000000207100039000000000707041a0000000108100039000000000808041a000000000101041a000000800010043f000000a00080043f000000c00070043f000000e00060043f000001000050043f000001200040043f000001400030043f000000ff002001900000000001000039000000010100c039000001600010043f00000687010000410000184e0001042e0000067d0030009c000007370000613d0000067e0030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b001200000001001d000006160010009c000015b80000213d184d16050000040f00000002010000390000034f0000013d000006660030009c0000073e0000613d000006670030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b001200000001001d000006160010009c000015b80000213d184d16050000040f0000000101000039000000000201041a000006150220019700000012022001af000000000021041b00000000010000190000184e0001042e000006720030009c0000078f0000613d000006730030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000001000411000000000010043f0000001601000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000ff0010019000000a930000c13d000006d101000041000000000010043f0000068c010000410000184f000104300000065b0030009c0000079a0000613d0000065c0030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000101000039000003e00000013d000006780030009c000007cc0000613d000006790030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001301000039000007d70000013d000006610030009c000007df0000613d000006620030009c000015b80000c13d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001501000039000000200010043f00000040020000390000000001000019184d18100000040f0000000602100039000000000202041a0000000503100039000000000303041a0000000404100039000000000404041a0000000305100039000000000505041a0000000206100039000000000606041a0000000107100039000000000707041a000000000101041a000000800010043f000000a00070043f000000c00060043f000000e00050043f000001000040043f000001200030043f000001400020043f000006b3010000410000184e0001042e0000066d0030009c000007ec0000613d0000066e0030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d000000000100041a00000616021001970000000001000411000000000012004b0000093b0000c13d000006bf010000410000000000100443000000000100041000000004001004430000000001000414000006140010009c0000061401008041000000c001100210000006b7011001c70000800a02000039184d18480000040f0000000100200190000012c40000613d0000000202000039000000000202041a0000061604200197000000000301043b0000000001000414000006140010009c0000061401008041000000c001100210000000000003004b00000b210000c13d000000000204001900000b240000013d000006560030009c000009250000613d000006570030009c000015b80000c13d0000000001000416000000000001004b000015b80000c13d0000000201000039000000000101041a0000054b0000013d000006290030009c000009500000613d0000062a0030009c000015b80000c13d000000440020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000402100370000000000202043b000006160020009c000015b80000213d0000002401100370000000000101043b001200000001001d000000000020043f0000001c01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000000120020006b000015b80000813d0000001202000029184d15ca0000040f0000000302200210000000000101041a000000000121022f0000061601100197000000ff0020008c00000000010020190000096e0000013d000000840020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000004402100370000000000202043b001100000002001d0000002402100370000000000202043b001200000002001d0000000402100370000000000202043b001000000002001d0000006401100370000000000201043b000000000002004b0000000001000039000000010100c039000f00000002001d000000000012004b000015b80000c13d000000000100041a00000616021001970000000001000411000000000012004b0000093b0000c13d0000000602000039000000000102041a000000010110003a000000690000613d000000000012041b0000018002000039000000400020043f000000800010043f000000a00000043f000000c00000043f000000e00000043f0000001002000029000001000020043f0000001202000029000001200020043f0000001102000029000001400020043f0000000f02000029000001600020043f000000000010043f0000001101000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000800200043d000000000021041b0000000102100039000000a00300043d000000000032041b0000000202100039000000c00300043d000000000032041b0000000302100039000000e00300043d000000000032041b0000000402100039000001000300043d000000000032041b0000000502100039000001200300043d000000000032041b0000000602100039000001400300043d000000000032041b0000000701100039000000000301041a000006d902300197000001600300043d000000000003004b000000010220c1bf000000000021041b0000000601000039000000000501041a000000400100043d00000060021000390000000f03000029000000000032043500000040021000390000001103000029000000000032043500000020021000390000001203000029000000000032043500000010020000290000000000210435000006140010009c000006140100804100000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000691011001c70000800d020000390000000203000039000006a404000041000007c80000013d000000440020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000402100370000000000202043b001200000002001d0000002401100370000000000201043b000000000002004b0000000001000039000000010100c039001100000002001d000000000012004b000015b80000c13d000000000100041a00000616021001970000000001000411000000000012004b0000093b0000c13d000006850100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006140010009c0000061401008041000000c00110021000000697011001c70000800502000039184d18480000040f0000000100200190000012c40000613d000000000101043b0000001202000029000000000012004b000004a70000413d0000000601000039000000000101041a000000000012004b00000cbb0000a13d0000069d01000041000000000010043f0000068c010000410000184f000104300000000001000416000000000001004b000015b80000c13d0000000401000039000000000101041a000000ff00100190000007280000613d0000000301000039000000000101041a001200000001001d0000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000012c40000613d000000000101043b000000120210006c000000690000413d000006a10020009c000000690000213d000000400100043d0000061402200197000006a20220012a000006a30220027f0000072a0000013d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001601000039000000200010043f00000040020000390000000001000019184d18100000040f000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f00000684010000410000184e0001042e0000000001000416000000000001004b000015b80000c13d0000000701000039000007db0000013d000000c40020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000004402100370000000000202043b001000000002001d0000002402100370000000000202043b001100000002001d0000000402100370000000000202043b001200000002001d0000006402100370000000000302043b000000000003004b0000000002000039000000010200c039000f00000003001d000000000023004b000015b80000c13d000000a402100370000000000402043b0000008401100370000000000301043b000000000100041a00000616021001970000000001000411000000000012004b0000093b0000c13d00000000013400a9000000000003004b0000050a0000613d00000000023100d9000000000042004b000000690000c13d000e00000004001d000000120010006c000005220000c13d000d00000003001d0000000701000039000000000101041a000c00000001001d000000000010043f0000001201000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000401100039000000000101041a0000000d0010006c00000d7c0000a13d000006a801000041000000000010043f0000068c010000410000184f000104300000000001000416000000000001004b000015b80000c13d0000000b01000039000007db0000013d0000000001000416000000000001004b000015b80000c13d0000000a01000039000007db0000013d0000000001000416000000000001004b000015b80000c13d000000000100041a00000616021001970000000005000411000000000052004b0000097f0000c13d0000061501100197000000000010041b0000000001000414000006140010009c0000061401008041000000c00110021000000617011001c70000800d02000039000000030300003900000618040000410000000006000019184d18430000040f000000010020019000000b2a0000c13d000015b80000013d0000000001000416000000000001004b000015b80000c13d000000000100041a0000061601100197000000800010043f00000684010000410000184e0001042e000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b001200000001001d000006160010009c000015b80000213d0000001201000029000000000010043f0000001a01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d0000000b02000039000000000202041a000000000101043b000000000101041a001100000002001d001000000001001d000000000012001a000000690000413d000006a90100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000012c40000613d00000010030000290000001102300029000000000101043b001000000001001d000000000012004b00000000010000190000096e0000413d0000001201000029000000000010043f0000001a01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000110010002a000000690000413d0000001101100029000000100110006c0000096e0000813d000000690000013d0000000001000416000000000001004b000015b80000c13d0000000d01000039000007db0000013d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b001200000001001d0000000001000411000000000010043f0000001301000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000068802000041000000040020043f000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000689011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b00000012030000290000068a0030009c00000ac20000c13d000006c401000041000000000010043f000006c5010000410000184f00010430000000240020008c000015b80000413d0000000001000416000000000001004b000015b80000c13d184d16050000040f00000004010000390000000001100367000000000101043b0000001e02000039000000000012041b00000000010000190000184e0001042e000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b001200000001001d000006160010009c000015b80000213d0000000901000039000000000101041a000000000001004b000007280000613d001000000001001d0000000301000039000000000101041a001100000001001d0000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000012c40000613d000000000101043b000000110110006c000000690000413d000006a10010009c000000690000213d001100000001001d0000001201000029000000000010043f0000000e01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d00000011020000290000061402200197000006a20220012a000006a30220027f000000000101043b000000000301041a00000000012300a9000000000003004b0000060d0000613d00000000033100d9000000000023004b00000eec0000c13d00000010021000fa000000400100043d0000072a0000013d000000240020008c000015b80000413d0000000401100370000000000101043b001200000001001d000006160010009c000015b80000213d0000001e01000039000000000101041a0000000002000416000000000012004b0000099f0000c13d0000000001000411000000000010043f0000001601000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000ff0010019000000b5a0000c13d0000000001000411000000120010006b00000cdd0000c13d000006be01000041000000000010043f0000068c010000410000184f00010430000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000000e01000039000007d70000013d0000000001000416000000000001004b000015b80000c13d0000000001000412001600000001001d001500200000003d000080050100003900000044030000390000000004000415000000160440008a0000094a0000013d000000640020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000402100370000000000202043b000006160020009c000015b80000213d0000004403100370000000000303043b001200000003001d0000002401100370000000000101043b000e00000001001d000000000020043f0000001301000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000201043b0000068801000041000000040010043f001100000002001d000000000020043f0000000001000414000006140010009c0000061401008041000000c00110021000000689011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000006da02100167000000000202041a000000000002004b00000bfd0000c13d000000000201041a000000000002004b0000000002000039000000010200c03900000bfe0000613d0000000103100039000000000303041a000000000003004b00000bfe0000613d0000000201100039000000000101041a000000000001004b0000000302000039000000020200603900000bfe0000013d000000640020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000004402100370000000000202043b001100000002001d0000002402100370000000000202043b001200000002001d0000000401100370000000000101043b001000000001001d000000000010043f0000001101000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000400400043d0000068d0040009c000000d50000213d000000000101043b0000010002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000a00000003001d00000000002304350000000202100039000000000202041a0000004003400039000c00000003001d00000000002304350000000302100039000000000202041a0000006003400039000b00000003001d00000000002304350000000402100039000000000202041a0000008003400039000900000003001d00000000002304350000000502100039000000000202041a000000a003400039000d00000003001d00000000002304350000000602100039000000000202041a000000c003400039000e00000003001d0000000000230435000800000004001d000000e0024000390000000701100039000000000101041a000000ff001001900000000001000039000000010100c039000f00000002001d00000000001204350000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000301043b0000000501300039000000000101041a000000120010006b00000b560000813d0000000601300039000000000101041a000000110010006b00000b560000813d000700000003001d0000000001000411000000000010043f0000001901000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001202000029000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001102000029000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000ff0010019000000b560000c13d0000000f010000290000000001010433000000000001004b000010380000c13d000006ba01000041000000000010043f0000068c010000410000184f00010430000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000d00000001001d000006160010009c000015b80000213d0000000401000039000000000101041a000000ff00100190000009c50000c13d000000800100003900000000020000190000000000210435000006140010009c0000061401008041000000400110021000000686011001c70000184e0001042e0000000001000416000000000001004b000015b80000c13d000006a201000041000000800010043f00000684010000410000184e0001042e0000000001000416000000000001004b000015b80000c13d000006a301000041000000800010043f00000684010000410000184e0001042e000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001c01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000301041a000000400200043d001100000002001d001000000003001d0000000002320436001200000002001d000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000698011001c70000801002000039184d18480000040f0000000100200190000015b80000613d0000001005000029000000000005004b00000012060000290000000002060019000007730000613d000000000101043b00000000030000190000000002060019000000000401041a0000061604400197000000000242043600000001011000390000000103300039000000000053004b0000076c0000413d000000110300002900000000013200490000001f01100039000006db021001970000000001320019000000000021004b00000000020000390000000102004039000006900010009c000000d50000213d0000000100200190000000d50000c13d000000400010043f00000020020000390000000002210436000000000303043300000000003204350000004002100039000000000003004b00000c6d0000613d00000000040000190000000065060434000006160550019700000000025204360000000104400039000000000034004b000007880000413d00000c6d0000013d0000000001000416000000000001004b000015b80000c13d0000000301000039000000000101041a000000000001004b000009840000c13d000006d201000041000000000010043f0000068c010000410000184f00010430000000440020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000616021001970000000001000411000000000012004b0000093b0000c13d001100000004001d001200000003001d000000000030043f0000001801000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001102000029000000000021041b000000400100043d0000000000210435000006140010009c000006140100804100000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000698011001c70000800d020000390000000203000039000006b2040000410000001205000029184d18430000040f000000010020019000000b2a0000c13d000015b80000013d000000240020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000000401100370000000000101043b000006160010009c000015b80000213d000000000010043f0000001001000039000000200010043f00000040020000390000000001000019184d18100000040f000000000101041a000000800010043f00000684010000410000184e0001042e000000240020008c000015b80000413d0000000001000416000000000001004b000015b80000c13d184d16050000040f00000004010000390000000001100367000000000101043b0000000b02000039000000000012041b00000000010000190000184e0001042e000000440020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000002402100370000000000202043b001100000002001d0000000401100370000000000101043b001200000001001d0000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000ff00100190000009e00000c13d0000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000006d90220019700000001022001bf000000000021041b000006850100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006140010009c0000061401008041000000c00110021000000697011001c70000800502000039184d18480000040f0000000100200190000012c40000613d000000000101043b001000000001001d000000000010043f0000001101000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000400200043d000f00000002001d0000068d0020009c000000d50000213d000000000101043b0000000f040000290000010002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000b00000003001d00000000002304350000000202100039000000000202041a0000004003400039000d00000003001d00000000002304350000000302100039000000000202041a0000006003400039000c00000003001d00000000002304350000000402100039000000000202041a0000008003400039000a00000003001d00000000002304350000000502100039000000000202041a000000a003400039000e00000003001d00000000002304350000000602100039000000000202041a000000c003400039000800000003001d0000000000230435000000e0024000390000000701100039000000000101041a000000ff001001900000000001000039000000010100c039000900000002001d00000000001204350000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000700000001001d0000000501100039000000000101041a000000120010006b00000b560000813d00000007010000290000000601100039000000000101041a000000110010006b00000b560000813d0000000001000411000000000010043f0000001901000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001202000029000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001102000029000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000ff0010019000000b560000c13d0000000e01000029000000000101043300000007020000290000000402200039000600000002001d000000000202041a000000000021001a000000690000413d000000000121001900000007020000290000000302200039000000000202041a000000000021004b000011aa0000213d00000012010000290000000d02000029000000000012043500000011010000290000000c0200002900000000001204350000000501000039000000000101041a000000010110003a000000690000613d0000000502000039000000000012041b0000000b0200002900000000001204350000000001000411000000000010043f0000001901000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001202000029000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001102000029000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000006d90220019700000001022001bf000000000021041b0000000001000411000000000010043f0000001301000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d0000000502000039000000000202041a000500000002001d000000000101043b0000068802000041000000040020043f000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000689011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000400000001001d00000005010000290000068a0010009c000005c00000613d0000000402000029000006da01200167000200000001001d000000000301041a000000200020043f000000050000006b00000005010000290000068a01006041000500000001001d000300000003001d000000000003004b000014780000c13d0000000401000029000000000101041a000000000001004b0000142b0000c13d00000005010000290000000402000029000014910000013d000000440020008c000015b80000413d0000000002000416000000000002004b000015b80000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000616021001970000000001000411000000000012004b0000093b0000c13d0000000701000039000000000101041a000000000013004b000009e40000a13d000006ae01000041000000000010043f0000068c010000410000184f000104300000068102000041000000000020043f000000040010043f00000682010000410000184f000104300000000001000416000000000001004b000015b80000c13d0000000001000412001400000001001d001300000000003d000080050100003900000044030000390000000004000415000000140440008a00000005044002100000068502000041184d18250000040f000000800010043f00000684010000410000184e0001042e0000000001000416000000000001004b000015b80000c13d0000000001020019184d15ba0000040f001100000002001d001200000003001d0000061601100197000000000010043f0000001901000039000000200010043f00000040020000390000000001000019184d18100000040f0000001102000029000000000020043f000000200010043f00000000010000190000004002000039184d18100000040f0000001202000029000000000020043f000000200010043f00000000010000190000004002000039184d18100000040f000000000101041a000000ff001001900000000001000039000000010100c039000000400200043d0000000000120435000006140020009c0000061402008041000000400120021000000686011001c70000184e0001042e0000000001000416000000000001004b000015b80000c13d0000001e01000039000007db0000013d0000068101000041000000000010043f000000040020043f00000682010000410000184f000104300000068101000041000000000010043f000000040050043f00000682010000410000184f00010430001200000001001d0000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000012c40000613d000000000101043b000006a20210012a0000000103200039000006a2023000d100000000033200d9000006a20030009c000000690000c13d0000001203000029000006a23030012a000000000032001a000000690000413d0000000002320019000000000112004b0000096e0000813d000000690000013d000006bb01000041000000000010043f0000068c010000410000184f000104300000000d02000039000000000012041b00000000010000190000184e0001042e0000001f0530018f0000068f06300198000000400200043d0000000004620019000009b20000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000009ae0000c13d000000000005004b000009bf0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000006140020009c00000614020080410000004002200210000000000112019f0000184f000104300000000901000039000000000101041a000f00000001001d000000000001004b00000ad90000c13d0000000d01000029000000000010043f0000000f01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000c02000039000000000202041a0000069b0020009c000000690000213d000000000101041a00000eb80000c13d000000000200001900000ec00000013d000006c301000041000000000010043f0000068c010000410000184f00010430001100000004001d001200000003001d0000068501000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006140010009c0000061401008041000000c00110021000000697011001c70000800502000039184d18480000040f0000000100200190000012c40000613d000000000101043b0000001202000029000000000012004b00000c190000c13d000006ad01000041000000000010043f0000068c010000410000184f00010430001200000001001d0000000001000411000000000010043f0000000f01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000001041b0000000c01000039000000000101041a000000000001004b000000120300002900000a150000613d000006da02100129000000000032004b00000ebc0000413d00000000013100a90010069b00100132000000100130006c001100000001001d000000690000413d0000000101000039000000000101041a000006b60200004100000000002004430000061601100197000f00000001001d00000004001004430000000001000414000006140010009c0000061401008041000000c001100210000006b7011001c70000800202000039184d18480000040f0000000100200190000012c40000613d000000000101043b000000000001004b000015b80000613d000000400300043d000000240130003900000011020000290000000000210435000006c80100004100000000001304350000000001000411000006160110019700000004023000390000000000120435000006140030009c001100000003001d0000061401000041000000000103401900000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000695011001c70000000f02000029184d18430000040f000000010020019000000ec40000613d0000001101000029000006900010009c000000d50000213d0000001101000029000000400010043f0000000001000411000000000010043f0000001b01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a0000000102000039000000000202041a000006b60300004100000000003004430000061602200197001100000002001d0000000400200443000f06160010019c000010fe0000c13d0000000001000414000006140010009c0000061401008041000000c001100210000006b7011001c70000800202000039184d18480000040f0000000100200190000012c40000613d000000000101043b000000000001004b000015b80000613d000000400300043d000000240130003900000010020000290000000000210435000006c80100004100000000001304350000000001000410000006160110019700000004023000390000000000120435000006140030009c000f00000003001d0000061401000041000000000103401900000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000695011001c70000001102000029184d18430000040f0000000100200190000011ba0000613d0000000f01000029000006900010009c000000d50000213d0000000f01000029000000400010043f0000000001000410000000000010043f0000001d01000039000000200010043f00000000010004140000112c0000013d0000001501000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b001100000001001d000000000201041a0000000701000039000000000101041a001200000002001d000000000012004b00000c760000c13d000006d001000041000000000010043f0000068c010000410000184f00010430001100000004001d001200000003001d000006850100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006140010009c0000061401008041000000c00110021000000697011001c70000800502000039184d18480000040f0000000100200190000012c40000613d000000000101043b0000001202000029000000000012004b00000c9c0000c13d000006b001000041000000000010043f0000068c010000410000184f00010430000006da02100167000000000003004b00000000040300190000068a04006041000000000202041a000000000002004b001100000004001d00000b5e0000c13d000000000201041a000000000042004b00000b6e0000613d0000000102100039000000000202041a000000110020006c00000b6e0000613d0000000201100039000000000101041a000000110010006c00000b6e0000613d0000068b01000041000000000010043f0000068c010000410000184f000104300000000301000039000000000101041a0000000802000039000000000302041a000000000213004b000000690000413d000006a10020009c000000690000213d001100000003001d000006a21010012a000e00000001001d0000000a01000039000000000101041a001200000001001d0000061401200197000006a20110012a001006a3001002870000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000012c40000613d000000000101043b0000001105000029000000000015004b00000012070000290000000e0400002900000e760000813d000006a20250012a0000000103200039000006a2023000d100000000033200d9000006a20030009c0000001008000029000000690000c13d000000000042001a000000690000413d0000000003420019000000000013004b00000000020100190000000002034019000000000452004b000000690000413d000000000008004b00000b170000613d00000000058400a900000000068500d9000000000046004b000000690000c13d000000000005004b00000b170000613d0000069b045000d100000000055400d90000069b0050009c00000b180000613d000000690000013d00000000040000190000000f044000fa000000000074001a000000690000413d001200000074001d000000000013004b000000010880a270001000000008001d001100000002001d00000aea0000013d00000617011001c700008009020000390000000005000019184d18430000040f0000006003100270000006140330019800000b2c0000c13d000000010020019000000b520000613d00000000010000190000184e0001042e0000001f04300039000006c0044001970000003f04400039000006c104400197000000400500043d0000000004450019000000000054004b00000000060000390000000106004039000006900040009c000000d50000213d0000000100600190000000d50000c13d000000400040043f0000001f0430018f00000000063504360000068f05300198000000000356001900000b440000613d000000000701034f000000007807043c0000000006860436000000000036004b00000b400000c13d000000000004004b00000b280000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000013043500000b280000013d000006c201000041000000000010043f0000068c010000410000184f00010430000006c701000041000000000010043f0000068c010000410000184f00010430000006bc01000041000000000010043f0000068c010000410000184f00010430000000200010043f000000000040043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000000001004b000000120300002900000ad50000613d000000000030043f0000001401000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000400200043d001000000002001d0000068d0020009c000000d50000213d000000000201043b00000010050000290000010001500039000000400010043f000000000102041a00000000031504360000000104200039000000000404041a00000000004304350000000203200039000000000303041a0000004004500039000e00000004001d00000000003404350000000303200039000000000303041a0000006004500039000d00000004001d00000000003404350000000403200039000000000303041a0000008004500039000c00000004001d00000000003404350000000503200039000000000303041a000000a004500039000f00000004001d00000000003404350000000603200039000000000303041a000000c0045000390000000000340435000000e0035000390000000702200039000000000202041a000000ff002001900000000002000039000000010200c0390000000000230435000000000010043f0000001801000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000a00000001001d0000000101000039000000000101041a000000400400043d000b00000004001d0000068e020000410000000000240435000000040240003900000000030004100000000000320435000006140040009c0000061402000041000000000204401900000040022002100000000003000414000006140030009c0000061403008041000000c003300210000000000323019f000006160210019700000682013001c7184d18480000040f00000060031002700000061403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000b0b0000290000000b0570002900000bda0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000bd60000c13d000000000006004b00000be70000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000ee00000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006900010009c000000d50000213d0000000100200190000000d50000c13d000000400010043f000000200030008c000015b80000413d00000000010b04330000000a0010006b0000114b0000a13d0000069601000041000000000010043f0000068c010000410000184f0001043000000001022002700000000e0520006c00000c380000a13d000000120050006c0000001205008029000006900050009c000000d50000213d00000005015002100000003f02100039000006d402200197000000400400043d0000000002240019000000000042004b00000000030000390000000103004039000006900020009c000000d50000213d0000000100300190000000d50000c13d000000400020043f000d00000004001d0000000002540436000c00000002001d000b00000005001d000000000005004b00000ddd0000c13d0000000d0300002900000c3e0000013d000000000020043f0000001201000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b00000002011000390000001102000029000000000021041b000000400100043d0000000000210435000006140010009c000006140100804100000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000698011001c70000800d020000390000000203000039000006ac04000041000007c70000013d000000400300043d000006d30030009c000000d50000213d0000002001300039000000400010043f0000000000030435000000400100043d000000200200003900000000022104360000000008030019000000000303043300000000003204350000004002100039000000000003004b00000c6d0000613d0000000004000019000000200880003900000000050804330000000076050434000000000662043600000000070704330000000000760435000000400650003900000000060604330000004007200039000000000067043500000060065000390000000006060433000000600720003900000000006704350000008006500039000000000606043300000080072000390000000000670435000000a0065000390000000006060433000000a0072000390000000000670435000000c0065000390000000006060433000000c0072000390000000000670435000000e0055000390000000005050433000000000005004b0000000005000039000000010500c039000000e006200039000000000056043500000100022000390000000104400039000000000034004b00000c480000413d0000000002120049000006140020009c00000614020080410000006002200210000006140010009c00000614010080410000004001100210000000000112019f0000184e0001042e0000000001000411000000000010043f0000001a01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a001000000001001d000006a90100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000012c40000613d000000000101043b000000100110006c000000690000413d0000000b02000039000000000202041a000000000021004b00000ef00000813d000006cf01000041000000000010043f0000068c010000410000184f00010430000000000020043f0000001101000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b00000006011000390000001102000029000000000021041b000000400100043d0000000000210435000006140010009c000006140100804100000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000698011001c70000800d020000390000000203000039000006af04000041000007c70000013d000000000020043f0000001101000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000701100039000000000201041a000006d9022001970000001103000029000000000232019f000000000021041b000000400100043d0000000000310435000006140010009c000006140100804100000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000698011001c70000800d0200003900000002030000390000069c04000041000007c70000013d000000000010043f0000001601000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000006d90220019700000001022001bf000000000021041b000000120000006b00000da40000c13d0000068501000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006140010009c0000061401008041000000c00110021000000697011001c70000800502000039184d18480000040f0000000100200190000012c40000613d000000000101043b001200000001001d000000000010043f0000001201000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000400200043d001100000002001d0000061f0020009c000000d50000213d000000000101043b0000001104000029000000c002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a001000000003001d00000000002304350000000202100039000000000202041a000000400340003900000000002304350000000302100039000000000202041a000000ff002001900000000002000039000000010200c039000000600340003900000000002304350000000402100039000000000202041a0000008003400039000e00000003001d0000000000230435000000a0024000390000000501100039000000000101041a000f00000002001d00000000001204350000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001202000029000000000021041b000000110200002900000000020204330000000103100039000000000023041b000000100200002900000000020204330000000303100039000000000023041b0000000e0200002900000000020204330000000503100039000000000023041b00000006011000390000000f020000290000000002020433000000000021041b0000000001000414000006140010009c0000061401008041000000c00110021000000617011001c70000800d020000390000000203000039000006bd040000410000000005000411000007c80000013d000000000020043f0000001201000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000301100039000000000201041a000006d9022001970000001103000029000000000232019f000000000021041b000000400100043d0000000000310435000006140010009c000006140100804100000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000698011001c70000800d0200003900000002030000390000069904000041000007c70000013d0000000c01000029000000000010043f0000001201000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000501100039000000000101041a0000000e0010006c000005220000213d0000000c01000029000000000010043f0000001201000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000101100039000000000101041a000000110010006c000010850000a13d000006a701000041000000000010043f0000068c010000410000184f000104300000000001000411000000000010043f0000001b01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a00000615022001970000001203000029000000000232019f000000000021041b000000000030043f0000001c01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a001200000002001d000006900020009c000000d50000213d00000012020000290000000102200039000000000021041b000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000698011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001201100029000000000201041a00000615022001970000000003000411000000000232019f000000000021041b00000cf00000013d00000000020000190000000c05000029000000400300043d0000068d0030009c000000d50000213d0000010004300039000000400040043f000000e0043000390000000000040435000000c0043000390000000000040435000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b00000ddf0000413d001200000000001d0000068801000041000000040010043f0000001101000029000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000689011001c70000801002000039184d18480000040f0000000100200190000015b80000613d00000012030000290010000e0030002d000000000101043b0000001001100029000000000101041a000f00000001001d0000068801000041000000040010043f0000001101000029000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000689011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000201043b000006da01200167000000000101041a000000000001004b00000e200000613d000000010110027000000e2e0000013d000000000102041a000000000001004b0000000001000039000000010100c03900000e2e0000613d0000000103200039000000000303041a000000000003004b00000e2e0000613d0000000201200039000000000101041a000000000001004b00000003010000390000000201006039000000100010006b000011940000813d0000000f010000290000068a0010009c0000000001006019000000000010043f0000001401000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000400200043d0000068d0020009c0000000d050000290000000b060000290000000c07000029000000d50000213d000000000101043b0000010003200039000000400030043f000000000301041a00000000033204360000000104100039000000000404041a00000000004304350000000203100039000000000303041a000000400420003900000000003404350000000303100039000000000303041a000000600420003900000000003404350000000403100039000000000303041a000000800420003900000000003404350000000503100039000000000303041a000000a00420003900000000003404350000000603100039000000000303041a000000c0042000390000000000340435000000e0032000390000000701100039000000000101041a000000ff001001900000000001000039000000010100c039000000000013043500000000010504330000001203000029000000000031004b000010f80000a13d0000000501300210000000000171001900000000002104350000000001050433000000000031004b000010f80000a13d001200010030003d000000120060006b00000df90000413d00000c170000013d0000000d010000290000061601100197001100000001001d000000000010043f0000000f01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a001000000001001d0000001101000029000000000010043f0000000e01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000f00000001001d0000001101000029000000000010043f0000001001000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000120210006b000000690000413d0000000f012000b90000000f0000006b00000eaf0000613d0000000f031000fa000000000023004b000000690000c13d0000069b0110012a000000100010002a000000690000413d0000000c02000039000000000202041a0000069b0020009c000000690000213d0000001001100029000009de0000613d0000069b02200099000006da03200129000000000013004b00000ec00000813d000006cc01000041000000000010043f000006c5010000410000184f0001043000000000021200a9000000400100043d0000069b0220012a0000072a0000013d00000060061002700000001f0460018f0000068f05600198000000400200043d000000000352001900000ed00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b00000ecc0000c13d0000061406600197000000000004004b00000ede0000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000006001600210000009c00000013d0000001f0530018f0000068f06300198000000400200043d0000000004620019000009b20000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000ee70000c13d000009b20000013d000006d801000041000000000010043f000006c5010000410000184f000104300000001201000029000000010110003a000000690000613d000000000010043f0000001201000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000400200043d001200000002001d0000061f0020009c000000d50000213d000000000101043b0000001204000029000000c002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000f00000003001d00000000002304350000000202100039000000000202041a0000004003400039001000000003001d00000000002304350000000302100039000000000202041a000000ff0020019000000060024000390000000003000039000000010300c03900000000003204350000000402100039000000000202041a0000008003400039000d00000003001d0000000000230435000000a0024000390000000501100039000000000101041a000e00000002001d0000000000120435000011980000613d0000000101000039000000000201041a000000400400043d000c00000004001d0000068e010000410000000000140435000000040140003900000000030004110000000000310435000006140040009c0000061401000041000000000104401900000040011002100000000003000414000006140030009c0000061403008041000000c003300210000000000113019f00000682011001c70000061602200197000b00000002001d184d18480000040f00000060031002700000061403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000c0b0000290000000c0570002900000f4a0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000f460000c13d000000000006004b00000f570000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000011ae0000613d0000001f01400039000000600110018f0000000002b10019000000000012004b00000000010000390000000101004039000a00000002001d000006900020009c000000d50000213d0000000100100190000000d50000c13d0000000a01000029000000400010043f000000200030008c000015b80000413d0000001001000029000000000101043300000000020b0433000000000012004b000010810000413d0000000a03000029000000440230003900000000001204350000000001000410000006160110019700000024023000390000000000120435000006b40100004100000000001304350000000001000411000006160110019700000004023000390000000000120435000006140030009c0000061401000041000000000103401900000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f000006b5011001c70000000b02000029184d18430000040f00000060031002700000061403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0570002900000f950000613d000000000801034f0000000a09000029000000008a08043c0000000009a90436000000000059004b00000f910000c13d000000000006004b00000fa20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000013020000613d0000001f01400039000000600110018f0000000a01100029000006900010009c000000d50000213d000000400010043f000000200030008c000015b80000413d0000000a010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b000015b80000c13d00000010010000290000000001010433000c00000001001d0000000101000039000000000101041a0000000d02000039000000000202041a000b00000002001d000000000002004b00000fc10000613d000000010200008a0000000b022000fa0000000c0020006c00000ebc0000413d0000061602100197000006b6010000410000000000100443000a00000002001d00000004002004430000000001000414000006140010009c0000061401008041000000c001100210000006b7011001c70000800202000039184d18480000040f0000000100200190000012c40000613d000000000101043b000000000001004b000015b80000613d0000000b020000290000000c012000b90000069b0110012a000000400300043d000006b802000041000000000023043500000004023000390000000000120435000006140030009c000c00000003001d0000061401000041000000000103401900000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000682011001c70000000a02000029184d18430000040f0000000100200190000014350000613d0000000c01000029000006900010009c000000d50000213d0000000c01000029000000400010043f0000001101000029000000000101041a000000010110003a000000690000613d0000001103000029000000000013041b000000120100002900000000010104330000000102300039000000000012041b0000000f0100002900000000010104330000000302300039000000000012041b0000000d0100002900000000010104330000000502300039000000000012041b00000006013000390000000e020000290000000002020433000000000021041b0000000001000411000000000010043f0000001a01000039000000200010043f000006a90100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000012c40000613d000000000101043b001200000001001d0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001202000029000000000021041b0000001101000029000000000601041a00000010010000290000000001010433000000400200043d0000000000120435000006140020009c000006140200804100000040012002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000698011001c70000800d020000390000000303000039000006cd040000410000000005000411184d18430000040f000000010020019000000b2a0000c13d000015b80000013d0000000101000039000000000201041a000000400400043d000600000004001d0000068e010000410000000000140435000000040140003900000000030004110000000000310435000006140040009c0000061401000041000000000104401900000040011002100000000003000414000006140030009c0000061403008041000000c003300210000000000113019f00000682011001c70000061602200197000500000002001d184d18480000040f00000060031002700000061403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000060b00002900000006057000290000105e0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000105a0000c13d000000000006004b0000106b0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000010ec0000613d0000001f01400039000000600110018f0000000002b10019000000000012004b00000000010000390000000101004039000400000002001d000006900020009c000000d50000213d0000000100100190000000d50000c13d0000000401000029000000400010043f000000200030008c000015b80000413d0000000e01000029000000000101043300000000020b0433000000000012004b0000119c0000813d000006ce01000041000000000010043f0000068c010000410000184f00010430000000400100043d000b00000001001d0000061f0010009c000000d50000213d0000000b03000029000000c001300039000000400010043f000000a0023000390000000e01000029000a00000002001d000000000012043500000080023000390000000d01000029000900000002001d000000000012043500000060023000390000000f01000029000800000002001d000000000012043500000040023000390000001001000029000700000002001d0000000000120435000000120100002900000000021304360000001101000029001200000002001d00000000001204350000000c01000029000000010110003a000000690000613d0000000702000039000000000012041b000000000010043f0000001201000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d0000000b020000290000000002020433000000000101043b000000000021041b000000120200002900000000020204330000000103100039000000000023041b000000070200002900000000020204330000000203100039000000000023041b0000000302100039000000000402041a000006d90340019700000008040000290000000004040433000000000004004b000000010330c1bf000000000032041b000000090200002900000000020204330000000403100039000000000023041b00000005011000390000000a020000290000000002020433000000000021041b0000000701000039000000000501041a000000400100043d00000080021000390000000e03000029000000000032043500000060021000390000000d03000029000000000032043500000040021000390000000f03000029000000000032043500000020021000390000001003000029000000000032043500000011020000290000000000210435000006140010009c000006140100804100000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f000006a5011001c70000800d020000390000000203000039000006a604000041000007c80000013d0000001f0530018f0000068f06300198000000400200043d0000000004620019000009b20000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000010f30000c13d000009b20000013d000006d601000041000000000010043f0000003201000039000000040010043f00000682010000410000184f000104300000000001000414000006140010009c0000061401008041000000c001100210000006b7011001c70000800202000039184d18480000040f0000000100200190000012c40000613d000000000101043b000000000001004b000015b80000613d000000400300043d000000240130003900000010020000290000000000210435000006c801000041000000000013043500000004013000390000000f020000290000000000210435000006140030009c000e00000003001d0000061401000041000000000103401900000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000695011001c70000001102000029184d18430000040f0000000100200190000011c70000613d0000000e01000029000006900010009c000000d50000213d0000000e01000029000000400010043f0000000f01000029000000000010043f0000001d01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000000100020002a000000690000413d0000001002200029000000000021041b000000400100043d00000012020000290000000000210435000006140010009c000006140100804100000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000698011001c70000800d020000390000000203000039000006c9040000410000000005000411000007c80000013d0000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000202100039000000000302041a000000000003004b000000690000613d000000010330008a000000000032041b0000000401100039000000000201041a0000000f030000290000000003030433000000000232004b000000690000413d000000000021041b0000000001000411000000000010043f0000001301000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000068802000041000000040020043f000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000689011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000201043b000f00000002001d000006da01200167000800000001001d000000000101041a000900000001001d000000000001004b000012d10000c13d0000000f040000290000000201400039000b00000001001d000000000101041a0000000102400039000000000302041a000000000404041a000000110040006c0000130e0000c13d0000000f04000029000000000034041b000013100000013d000006d501000041000000000010043f0000068c010000410000184f00010430000006cb01000041000000000010043f0000068c010000410000184f000104300000000d02000029000000000202043300000007030000290000000403300039000600000003001d000000000303041a000000000032001a000000690000413d000000000232001900000007030000290000000303300039000000000303041a000000000032004b000011d40000a13d000006c601000041000000000010043f0000068c010000410000184f000104300000001f0530018f0000068f06300198000000400200043d0000000004620019000009b20000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000011b50000c13d000009b20000013d00000060061002700000001f0460018f0000068f05600198000000400200043d000000000352001900000ed00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000011c20000c13d00000ed00000013d00000060061002700000001f0460018f0000068f05600198000000400200043d000000000352001900000ed00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000011cf0000c13d00000ed00000013d0000000403000029000000440230003900000000001204350000000001000410000006160110019700000024023000390000000000120435000006b40100004100000000001304350000000001000411000006160110019700000004023000390000000000120435000006140030009c0000061401000041000000000103401900000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f000006b5011001c70000000502000029184d18430000040f00000060031002700000061403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000405700029000011fc0000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b000011f80000c13d000000000006004b000012090000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000012c50000613d0000001f01400039000000600110018f0000000401100029000006900010009c000000d50000213d000000400010043f000000200030008c000015b80000413d00000004010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b000015b80000c13d0000000e010000290000000001010433000500000001001d0000000101000039000000000101041a0000000d02000039000000000202041a000400000002001d000000000002004b000012280000613d000000010200008a00000004022000fa000000050020006c00000ebc0000413d0000061602100197000006b6010000410000000000100443000300000002001d00000004002004430000000001000414000006140010009c0000061401008041000000c001100210000006b7011001c70000800202000039184d18480000040f0000000100200190000012c40000613d000000000101043b000000000001004b000015b80000613d000000040200002900000005012000b90000069b0110012a000000400300043d000006b802000041000000000023043500000004023000390000000000120435000006140030009c000500000003001d0000061401000041000000000103401900000040011002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000682011001c70000000302000029184d18430000040f00000001002001900000141e0000613d0000000501000029000006900010009c000000d50000213d0000000501000029000000400010043f00000012010000290000000c02000029000000000012043500000011010000290000000b0200002900000000001204350000000501000039000000000101041a000000010110003a000000690000613d0000000502000039000000000012041b0000000a0200002900000000001204350000000001000411000000000010043f0000001901000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001202000029000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001102000029000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000006d90220019700000001022001bf000000000021041b0000000001000411000000000010043f0000001301000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d0000000502000039000000000202041a000500000002001d000000000101043b0000068802000041000000040020043f000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000689011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000400000001001d00000005010000290000068a0010009c000005c00000613d0000000402000029000006da01200167000200000001001d000000000301041a000000200020043f000000050000006b00000005010000290000068a01006041000500000001001d000300000003001d000000000003004b000015400000c13d0000000401000029000000000101041a000000000001004b000015000000c13d00000005010000290000000402000029000015590000013d000000000001042f0000001f0530018f0000068f06300198000000400200043d0000000004620019000009b20000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000012cc0000c13d000009b20000013d0000000f01000029000000200010043f0000001101000029000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000b00000001001d000000000101041a001100000001001d000000000001004b000013130000613d000000090100002900000001011002700009000100100092000000110010006b000012fd0000613d00000011010000290000000f0110002900000009030000290000000f02300029000000000202041a000000010110008a000000000021041b000000000020043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000001102000029000000000021041b0000000901000029000000010110021000000001011001bf0000000802000029000013100000013d0000001f0530018f0000068f06300198000000400200043d0000000004620019000009b20000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013090000c13d000009b20000013d000000110030006c0000141b0000c13d000000000012041b0000000b01000029000000000001041b0000001201000029000000000010043f0000001401000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000202100039000000000002041b0000000302100039000000000002041b0000000402100039000000000002041b0000000502100039000000000002041b0000000602100039000000000002041b0000000701100039000000000001041b0000000001000411000000000010043f0000001901000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000e020000290000000002020433000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000d020000290000000002020433000000000020043f000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000006d902200197000000000021041b000000100100002900000000060104330000000e0100002900000000010104330000000d020000290000000002020433000000400300043d00000060043000390000000000240435000000400230003900000000001204350000002001300039000000120200002900000000002104350000000a010000290000000000130435000006140030009c000006140300804100000040013002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000691011001c70000800d02000039000000030300003900000692040000410000000005000411184d18430000040f0000000100200190000015b80000613d0000000c010000290000000001010433001200000001001d0000000001000411184d16100000040f0000000901000039000000000201041a000000120220006c000000690000413d000000000021041b0000000001000411000000000010043f0000000e01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000000120220006c000000690000413d000000000021041b0000000001000411000000000010043f0000000e01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a001200000001001d0000000001000411000000000010043f0000000f01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000101041a000000400200043d0000002003200039000000000013043500000012010000290000000000120435000006140020009c000006140200804100000040012002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f0000061e011001c70000800d02000039000000020300003900000693040000410000000005000411184d18430000040f0000000100200190000015b80000613d0000000a0000006b00000b2a0000613d0000000101000039000000000201041a000000400400043d001200000004001d00000024014000390000000a030000290000000000310435000006940100004100000000001404350000000001000411000006160110019700000004034000390000000000130435000006140040009c0000061401000041000000000104401900000040011002100000000003000414000006140030009c0000061403008041000000c003300210000000000113019f00000695011001c70000061602200197184d18430000040f00000060031002700000061403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000120b0000290000001205700029000013f80000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000013f40000c13d000000000006004b000014050000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000014f40000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006900010009c000000d50000213d0000000100200190000000d50000c13d000000400010043f000000200030008c000015b80000413d00000000010b0433000000000001004b0000000002000039000000010200c039000000000021004b00000b2a0000613d000015b80000013d000000110010006c000013110000613d000013130000013d00000060061002700000001f0460018f0000068f05600198000000400200043d000000000352001900000ed00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000014260000c13d00000ed00000013d000000050010006c000014920000613d00000004020000290000000102200039000000000302041a000300000003001d000000000003004b000014420000c13d0000000501000029000014910000013d00000060061002700000001f0460018f0000068f05600198000000400200043d000000000352001900000ed00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b0000143d0000c13d00000ed00000013d0000000303000029000000050030006c000014920000613d00000004020000290000000202200039000000000302041a000100000003001d000000000003004b000014330000613d0000000103000029000000050030006c000014920000613d000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000102000039000000000021041b0000000301000029000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000202000039000000000021041b0000000101000029000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000302000039000000000021041b000300070000003d0000000501000029000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000000000002004b000014920000c13d0000000302000029000000010220027000000004032000290000000504000029000000000043041b0000000102200039000000000021041b000000010120021000000001011001bf0000000202000029000000000012041b0000000501000039000000000101041a000000000010043f0000001401000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d0000000f020000290000000002020433000000000301043b000000000023041b0000000b0100002900000000010104330000000102300039000000000012041b0000000d0100002900000000010104330000000202300039000000000012041b0000000c0100002900000000010104330000000302300039000000000012041b0000000a0100002900000000010104330000000402300039000000000012041b0000000e0100002900000000010104330000000502300039000000000012041b000000080200002900000000020204330000000604300039000000000024041b0000000702300039000000000302041a000006d90330019700000009040000290000000004040433000000000004004b000000010330c1bf000000000032041b00000007020000290000000202200039000000000302041a000000010330003a000000690000613d000000000032041b0000000602000029000000000202041a000000000012001a000000690000413d00000000011200190000000602000029000000000012041b0000000501000039000000000101041a000000400200043d000000600320003900000011040000290000000000430435000000400320003900000012040000290000000000430435000000200320003900000000001304350000000000020435000006140020009c000006140200804100000040012002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000691011001c70000800d020000390000000303000039000006b90400004100000000050004110000001006000029184d18430000040f0000000100200190000015b80000613d0000000a0100002900000000020104330000000001000411184d16d40000040f00000000010000190000184e0001042e0000001f0530018f0000068f06300198000000400200043d0000000004620019000009b20000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014fb0000c13d000009b20000013d000000050010006c0000155a0000613d00000004020000290000000102200039000000000302041a000300000003001d000000000003004b0000150a0000c13d0000000501000029000015590000013d0000000303000029000000050030006c0000155a0000613d00000004020000290000000202200039000000000302041a000100000003001d000000000003004b000015080000613d0000000103000029000000050030006c0000155a0000613d000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000102000039000000000021041b0000000301000029000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000202000039000000000021041b0000000101000029000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b0000000302000039000000000021041b000300070000003d0000000501000029000000000010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d000000000101043b000000000201041a000000000002004b0000155a0000c13d0000000302000029000000010220027000000004032000290000000504000029000000000043041b0000000102200039000000000021041b000000010120021000000001011001bf0000000202000029000000000012041b0000000501000039000000000101041a000000000010043f0000001401000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000015b80000613d00000008020000290000000002020433000000000301043b000000000023041b0000000a0100002900000000010104330000000102300039000000000012041b0000000c0100002900000000010104330000000202300039000000000012041b0000000b0100002900000000010104330000000302300039000000000012041b000000090100002900000000010104330000000402300039000000000012041b0000000d0100002900000000020104330000000501300039000000000021041b0000000e0100002900000000010104330000000604300039000000000014041b0000000703300039000000000403041a000006d9044001970000000f050000290000000005050433000000000005004b000000010440c1bf000000000043041b00000007030000290000000203300039000000000403041a000000010440003a000000690000613d000000000043041b0000000603000029000000000303041a000000000023001a000000690000413d00000000022300190000000603000029000000000023041b0000000502000039000000000202041a000000400300043d000000600430003900000011050000290000000000540435000000400430003900000012050000290000000000540435000000200430003900000000002404350000000000130435000006140030009c000006140300804100000040013002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000691011001c70000800d020000390000000303000039000006b90400004100000000050004110000001006000029184d18430000040f0000000100200190000015b80000613d0000000901000029000014ef0000013d00000000010000190000184f00010430000006dc0010009c000015c80000213d000000630010008c000015c80000a13d00000000030003670000000401300370000000000101043b000006160010009c000015c80000213d0000002402300370000000000202043b0000004403300370000000000303043b000000000001042d00000000010000190000184f000104300001000000000002000000000301041a000100000002001d000000000023004b000015dd0000a13d000000000010043f0000000001000414000006140010009c0000061401008041000000c00110021000000698011001c70000801002000039184d18480000040f0000000100200190000015e30000613d000000000101043b00000001011000290000000002000019000000000001042d000006d601000041000000000010043f0000003201000039000000040010043f00000682010000410000184f0001043000000000010000190000184f000104300000001f02200039000006db022001970000000001120019000000000021004b00000000020000390000000102004039000006900010009c000015f10000213d0000000100200190000015f10000c13d000000400010043f000000000001042d000006d601000041000000000010043f0000004101000039000000040010043f00000682010000410000184f000104300000000002120049000006dc0020009c000016030000213d0000001f0020008c000016030000a13d0000000001010433000000000001004b0000000002000039000000010200c039000000000021004b000016030000c13d000000000001042d00000000010000190000184f00010430000000000100041a00000616021001970000000001000411000000000012004b0000160b0000c13d000000000001042d0000068102000041000000000020043f000000040010043f00000682010000410000184f000104300003000000000002000100000001001d0000000901000039000000000101041a000000000001004b0000000802000039000016620000613d0000000301000039000000000101041a000000000202041a000000000112004b000016c50000413d000006a10010009c000016c50000213d000300000002001d0000061401100197000006a20110012a000206a3001002870000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000016cb0000613d000000000101043b0000000304000029000000000014004b0000166e0000813d000006a20240012a0000000103200039000006a2023000d100000000033200d9000006a20030009c0000000207000029000016c50000c13d0000000303000039000000000303041a000006a23030012a000000000023001a000016c50000413d0000000003230019000000000013004b00000000020100190000000002034019000000000442004b000016c50000413d000000000007004b000016500000613d00000000057400a900000000067500d9000000000046004b000016c50000c13d000000000005004b000016500000613d0000069b045000d100000000055400d90000069b0050009c000016510000613d000016c50000013d00000000040000190000000905000039000000000505041a000000000005004b000016cc0000613d00000000045400d90000000a05000039000000000505041a000000000045001a000016c50000413d00000000044500190000000a05000039000000000045041b000000000013004b000000010770a270000200000007001d000300000002001d000016220000013d0000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000016cb0000613d000000000101043b0000000802000039000000000012041b00000001010000290000061601100197000300000001001d000000000010043f0000000e01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000016d20000613d0000000a02000039000000000202041a000100000002001d000000000101043b000000000101041a000200000001001d0000001001000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000016d20000613d000000000101043b000000000101041a000000010110006b0000000202000029000016c50000413d00000000032100a9000000000002004b0000169b0000613d00000000022300d9000000000012004b000016c50000c13d000200000003001d0000000301000029000000000010043f0000000f01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000016d20000613d00000002020000290000069b0220012a000000000101043b000000000301041a000000000023001a000016c50000413d0000000002230019000000000021041b0000000a01000039000000000101041a000200000001001d0000000301000029000000000010043f0000001001000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f0000000100200190000016d20000613d000000000101043b0000000202000029000000000021041b000000000001042d000006d601000041000000000010043f0000001101000039000000040010043f00000682010000410000184f00010430000000000001042f000006d601000041000000000010043f0000001201000039000000040010043f00000682010000410000184f0001043000000000010000190000184f000104300004000000000002000200000002001d000100000001001d0000000401000039000000000201041a000000ff00200190000016ff0000c13d000006d90220019700000001022001bf000000000021041b0000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000018060000613d000000000101043b0000000302000039000000000012041b0000000802000039000000000012041b000000400200043d0000000000120435000006140020009c000006140200804100000040012002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000698011001c70000800d020000390000000103000039000006dd04000041184d18430000040f00000001002001900000180d0000613d0000000901000039000000000101041a000000000001004b0000174f0000613d0000000301000039000000000101041a0000000802000039000000000202041a000000000112004b000018000000413d000006a10010009c000018000000213d000400000002001d0000061401100197000006a20110012a000306a3001002870000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000018060000613d000000000101043b0000000404000029000000000014004b0000175b0000813d000006a20240012a0000000103200039000006a2023000d100000000033200d9000006a20030009c0000000307000029000018000000c13d0000000303000039000000000303041a000006a23030012a000000000023001a000018000000413d0000000003230019000000000013004b00000000020100190000000002034019000000000442004b000018000000413d000000000007004b0000173d0000613d00000000057400a900000000067500d9000000000046004b000018000000c13d000000000005004b0000173d0000613d0000069b045000d100000000055400d90000069b0050009c0000173e0000613d000018000000013d00000000040000190000000905000039000000000505041a000000000005004b000018070000613d00000000045400d90000000a05000039000000000505041a000000000045001a000018000000413d00000000044500190000000a05000039000000000045041b000000000013004b000000010770a270000300000007001d000400000002001d0000170f0000013d0000069f0100004100000000001004430000000001000414000006140010009c0000061401008041000000c001100210000006a0011001c70000800b02000039184d18480000040f0000000100200190000018060000613d000000000101043b0000000802000039000000000012041b00000001010000290000061601100197000400000001001d000000000010043f0000000e01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f00000001002001900000180d0000613d0000000a02000039000000000202041a000100000002001d000000000101043b000000000101041a000300000001001d0000001001000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f00000001002001900000180d0000613d000000000101043b000000000101041a000000010110006b0000000302000029000018000000413d00000000032100a9000000000002004b000017880000613d00000000022300d9000000000012004b000018000000c13d000300000003001d0000000401000029000000000010043f0000000f01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f00000001002001900000180d0000613d00000003020000290000069b0220012a000000000101043b000000000301041a000000000023001a000018000000413d0000000002230019000000000021041b0000000a01000039000000000101041a000300000001001d0000000401000029000000000010043f0000001001000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f00000001002001900000180d0000613d000000000101043b0000000302000029000000000021041b0000000901000039000000000101041a000000020010002a000018000000413d00000002011000290000000902000039000000000012041b0000000401000029000000000010043f0000000e01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f00000001002001900000180d0000613d000000000101043b000000000201041a000000020020002a000018000000413d0000000202200029000000000021041b0000000401000029000000000010043f0000000e01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f00000001002001900000180d0000613d000000000101043b000000000101041a000300000001001d0000000401000029000000000010043f0000000f01000039000000200010043f0000000001000414000006140010009c0000061401008041000000c0011002100000061e011001c70000801002000039184d18480000040f00000001002001900000180d0000613d000000000101043b000000000101041a000000400200043d0000002003200039000000000013043500000003010000290000000000120435000006140020009c000006140200804100000040012002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f0000061e011001c70000800d0200003900000002030000390000000005000411000006de04000041184d18430000040f00000001002001900000180d0000613d000000000001042d000006d601000041000000000010043f0000001101000039000000040010043f00000682010000410000184f00010430000000000001042f000006d601000041000000000010043f0000001201000039000000040010043f00000682010000410000184f0001043000000000010000190000184f00010430000000000001042f000006140010009c00000614010080410000004001100210000006140020009c00000614020080410000006002200210000000000112019f0000000002000414000006140020009c0000061402008041000000c002200210000000000112019f00000617011001c70000801002000039184d18480000040f0000000100200190000018230000613d000000000101043b000000000001042d00000000010000190000184f0001043000000000050100190000000000200443000000050030008c000018330000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b0000182b0000413d000006140030009c000006140300804100000060013002100000000002000414000006140020009c0000061402008041000000c002200210000000000112019f000006df011001c70000000002050019184d18480000040f0000000100200190000018420000613d000000000101043b000000000001042d000000000001042f00001846002104210000000102000039000000000001042d0000000002000019000000000001042d0000184b002104230000000102000039000000000001042d0000000002000019000000000001042d0000184d000004320000184e0001042e0000184f0001043000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff02000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e000000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000058d15e176280000000000000000000000000000000000000000000000000000a688906bd8b00000000000000000000000000000000000000000000000000000011c37937e08000000000000000000000000000000000000000000000000000ffffffffffffff000200000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff3f00000002000000000000000000000000000000c0000001000000000000000000000000000000000000000000000000000000000000000000000000006d12ff51000000000000000000000000000000000000000000000000000000009f715f5f00000000000000000000000000000000000000000000000000000000d9ba62b200000000000000000000000000000000000000000000000000000000e2b15d8b00000000000000000000000000000000000000000000000000000000ea26fa2c00000000000000000000000000000000000000000000000000000000ea26fa2d00000000000000000000000000000000000000000000000000000000eef3b2d000000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000e2b15d8c00000000000000000000000000000000000000000000000000000000e92820e600000000000000000000000000000000000000000000000000000000df1e3b7e00000000000000000000000000000000000000000000000000000000df1e3b7f00000000000000000000000000000000000000000000000000000000e0d152af00000000000000000000000000000000000000000000000000000000d9ba62b300000000000000000000000000000000000000000000000000000000dd6a4c6500000000000000000000000000000000000000000000000000000000c243589300000000000000000000000000000000000000000000000000000000ca18116f00000000000000000000000000000000000000000000000000000000ca18117000000000000000000000000000000000000000000000000000000000d147129600000000000000000000000000000000000000000000000000000000c243589400000000000000000000000000000000000000000000000000000000c51a2bba00000000000000000000000000000000000000000000000000000000adadbd2600000000000000000000000000000000000000000000000000000000adadbd2700000000000000000000000000000000000000000000000000000000bbfcddd5000000000000000000000000000000000000000000000000000000009f715f6000000000000000000000000000000000000000000000000000000000a9f8d181000000000000000000000000000000000000000000000000000000008685e3f1000000000000000000000000000000000000000000000000000000009292ae9a000000000000000000000000000000000000000000000000000000009618b31b000000000000000000000000000000000000000000000000000000009618b31c000000000000000000000000000000000000000000000000000000009ca423b3000000000000000000000000000000000000000000000000000000009292ae9b0000000000000000000000000000000000000000000000000000000094fc19e4000000000000000000000000000000000000000000000000000000008da5cb5a000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000008dfc3933000000000000000000000000000000000000000000000000000000008685e3f20000000000000000000000000000000000000000000000000000000086b3cd2600000000000000000000000000000000000000000000000000000000787a08a500000000000000000000000000000000000000000000000000000000811c508800000000000000000000000000000000000000000000000000000000811c50890000000000000000000000000000000000000000000000000000000084ae2bc600000000000000000000000000000000000000000000000000000000787a08a6000000000000000000000000000000000000000000000000000000007e08b5b300000000000000000000000000000000000000000000000000000000715018a500000000000000000000000000000000000000000000000000000000715018a60000000000000000000000000000000000000000000000000000000072779cba000000000000000000000000000000000000000000000000000000006d12ff5200000000000000000000000000000000000000000000000000000000713494d7000000000000000000000000000000000000000000000000000000003e89bb120000000000000000000000000000000000000000000000000000000059058ad0000000000000000000000000000000000000000000000000000000005fd9491c0000000000000000000000000000000000000000000000000000000069f0ee320000000000000000000000000000000000000000000000000000000069f0ee33000000000000000000000000000000000000000000000000000000006ba4f47f000000000000000000000000000000000000000000000000000000005fd9491d000000000000000000000000000000000000000000000000000000006756a1c7000000000000000000000000000000000000000000000000000000005c7421e2000000000000000000000000000000000000000000000000000000005c7421e3000000000000000000000000000000000000000000000000000000005d4954110000000000000000000000000000000000000000000000000000000059058ad1000000000000000000000000000000000000000000000000000000005a5ccef000000000000000000000000000000000000000000000000000000000476e2e65000000000000000000000000000000000000000000000000000000004fc3f419000000000000000000000000000000000000000000000000000000004fc3f41a00000000000000000000000000000000000000000000000000000000542f9e6a00000000000000000000000000000000000000000000000000000000476e2e660000000000000000000000000000000000000000000000000000000048cd4cb10000000000000000000000000000000000000000000000000000000041a0894c0000000000000000000000000000000000000000000000000000000041a0894d00000000000000000000000000000000000000000000000000000000444d51ad000000000000000000000000000000000000000000000000000000003e89bb130000000000000000000000000000000000000000000000000000000040f5da9e00000000000000000000000000000000000000000000000000000000234f3f1a0000000000000000000000000000000000000000000000000000000031d7a261000000000000000000000000000000000000000000000000000000003a8ee01d000000000000000000000000000000000000000000000000000000003a8ee01e000000000000000000000000000000000000000000000000000000003ccfd60b0000000000000000000000000000000000000000000000000000000031d7a26200000000000000000000000000000000000000000000000000000000372500ab000000000000000000000000000000000000000000000000000000002fc96ce5000000000000000000000000000000000000000000000000000000002fc96ce60000000000000000000000000000000000000000000000000000000030775a9400000000000000000000000000000000000000000000000000000000234f3f1b0000000000000000000000000000000000000000000000000000000024b4464e00000000000000000000000000000000000000000000000000000000157e204b000000000000000000000000000000000000000000000000000000001bce7820000000000000000000000000000000000000000000000000000000001bce7821000000000000000000000000000000000000000000000000000000001e57057d00000000000000000000000000000000000000000000000000000000157e204c000000000000000000000000000000000000000000000000000000001a267cd20000000000000000000000000000000000000000000000000000000011d988bb0000000000000000000000000000000000000000000000000000000011d988bc00000000000000000000000000000000000000000000000000000000155dd47a00000000000000000000000000000000000000000000000000000000032fca010000000000000000000000000000000000000000000000000000000010d96759118cdaa70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000001e4fbdf7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000800000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001000000008000000000000000000000000000000000000000000000000000000000000000000000000018fb586402000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000fbb67fda52d4bfb8bf3d9f63cb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffeff70a082310000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffff0200000000000000000000000000000000000080000000000000000000000000952aa29dabfc45e8c9bba19903b0a8bb9031c952db14a06ad48af137e5835b07e331ada0d0e61e9a4196bf4994f2519193d70a601daff346c4276d591664da9aa9059cbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000515d3e8100000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000004400000000000000000000000002000000000000000000000000000000000000200000000000000000000000000bd772fd008a8dd5673c42a4f50f72220b2603eee55113cd6c38ff78d71e644fedd999f8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000d0a7ceb410ade2d440d8ed59d6b338fe480f98025101655790e0de736edddabe3b87f10900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000080000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd102000002000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000040163fff000000000000000000000000000000000000000000000000000000000040164000000000000000000000000000000000000000000000000022b1c8c1227a0000e0a2f8482bbba7e119c069eb63409ac33b15fc516cffed25aeabb6a9669e07c202000000000000000000000000000000000000a00000000000000000000000006ae4a0e17ec15e82a1af6ff99411c44193a38f27f15c3ddd30b0f09ab1c5fd2cd2a50ed000000000000000000000000000000000000000000000000000000000472ea01c00000000000000000000000000000000000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d955391320000000000000000000000000000000000000000000000000de0b6b3a764000158d620b300000000000000000000000000000000000000000000000000000000f721e9425607d38abda58b925d2a080b3aefa127d46973d2683875dc87cb9a6bf1fa1762000000000000000000000000000000000000000000000000000000006cb4090800000000000000000000000000000000000000000000000000000000f920b24ea96b3814655944622f9eb86875e3193c5de1a9de018777e6c8705cee4705d684000000000000000000000000000000000000000000000000000000003a6c77df0000000000000000000000000000000000000000000000000000000086257f0afab037798cc4548a6d86125f52c92410a1e29aff03d787d49dac20db00000000000000000000000000000000000000e000000080000000000000000023b872dd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000042966c680000000000000000000000000000000000000000000000000000000070a5d2d3258adcf9978a193a4dd8fa309ae83a9f1046a0a5ea99a133bf34f9a5aa8a9b9800000000000000000000000000000000000000000000000000000000d2ade556000000000000000000000000000000000000000000000000000000008fe6f7d800000000000000000000000000000000000000000000000000000000e424ed553a53c3a900c875ed34d63043e4dfb799427ee8ae0836b046a603c90e61104228000000000000000000000000000000000000000000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f3900000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000003ffffffe0750b219c0000000000000000000000000000000000000000000000000000000070e9a55a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000f5a267f100000000000000000000000000000000000000040000001c0000000000000000fbfd2f4000000000000000000000000000000000000000000000000000000000a800e0ac0000000000000000000000000000000000000000000000000000000040c10f1900000000000000000000000000000000000000000000000000000000fc30cddea38e2bf4d6ea7d3f9ed3b6ad7f176419f4963bd81318067a4aee73fe0df723dc0000000000000000000000000000000000000000000000000000000047cd2fa60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bac65e5be2dbc44c627e3876b04b29d12596a77c7d0fa585ccb754b9fcd92e48d813dd77ff0b21e60000000000000000000000000000000000000000000000000000000041fde9ef0000000000000000000000000000000000000000000000000000000072932dd3000000000000000000000000000000000000000000000000000000000c02d44e00000000000000000000000000000000000000000000000000000000602fe2ca00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe04e23d035000000000000000000000000000000000000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000080000000000000000000000000000000000000000000000000000000000000000000000000ad251c27ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdaae9aa758637a0d349f036f099afd70aa88d8ac63fce096321de512ffebc16ca051d58ced8df58040b29d2c939da70a826ae40290f77c9a66b38b8b85315f6502000002000000000000000000000000000000000000000000000000000000000d4e1c9cf47b66892ca11d09723f471006f66f0bed215fb3245f280e013046b2

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.