More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 28,274 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Rewards | 6674280 | 20 secs ago | IN | 0 ETH | 0.00000613 | ||||
Claim Rewards | 6674271 | 29 secs ago | IN | 0 ETH | 0.00000665 | ||||
Claim Rewards | 6674259 | 41 secs ago | IN | 0 ETH | 0.00000444 | ||||
Buy Miner | 6674259 | 41 secs ago | IN | 0 ETH | 0.00001084 | ||||
Claim Rewards | 6674258 | 42 secs ago | IN | 0 ETH | 0.00000641 | ||||
Claim Rewards | 6674235 | 1 min ago | IN | 0 ETH | 0.00000616 | ||||
Buy Miner | 6674228 | 1 min ago | IN | 0 ETH | 0.00001105 | ||||
Claim Rewards | 6674212 | 1 min ago | IN | 0 ETH | 0.00000695 | ||||
Claim Rewards | 6674209 | 1 min ago | IN | 0 ETH | 0.00000616 | ||||
Claim Rewards | 6674198 | 1 min ago | IN | 0 ETH | 0.00000432 | ||||
Claim Rewards | 6674195 | 1 min ago | IN | 0 ETH | 0.00000666 | ||||
Claim Rewards | 6674194 | 1 min ago | IN | 0 ETH | 0.00000667 | ||||
Claim Rewards | 6674182 | 1 min ago | IN | 0 ETH | 0.00000616 | ||||
Claim Rewards | 6674155 | 2 mins ago | IN | 0 ETH | 0.00000613 | ||||
Claim Rewards | 6674140 | 2 mins ago | IN | 0 ETH | 0.00000695 | ||||
Claim Rewards | 6674129 | 2 mins ago | IN | 0 ETH | 0.00000448 | ||||
Claim Rewards | 6674126 | 2 mins ago | IN | 0 ETH | 0.00000616 | ||||
Claim Rewards | 6674122 | 2 mins ago | IN | 0 ETH | 0.00000696 | ||||
Claim Rewards | 6674105 | 3 mins ago | IN | 0 ETH | 0.00000616 | ||||
Claim Rewards | 6674092 | 3 mins ago | IN | 0 ETH | 0.00000695 | ||||
Claim Rewards | 6674088 | 3 mins ago | IN | 0 ETH | 0.00000665 | ||||
Claim Rewards | 6674075 | 3 mins ago | IN | 0 ETH | 0.00000616 | ||||
Claim Rewards | 6674071 | 3 mins ago | IN | 0 ETH | 0.00000605 | ||||
Claim Rewards | 6674058 | 4 mins ago | IN | 0 ETH | 0.00000604 | ||||
Claim Rewards | 6674050 | 4 mins ago | IN | 0 ETH | 0.00000599 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6673508 | 13 mins ago | 0.015 ETH | ||||
6671997 | 39 mins ago | 0.015 ETH | ||||
6671212 | 53 mins ago | 0.015 ETH | ||||
6669557 | 1 hr ago | 0.015 ETH | ||||
6669116 | 1 hr ago | 0.015 ETH | ||||
6669109 | 1 hr ago | 0.015 ETH | ||||
6668716 | 1 hr ago | 0.015 ETH | ||||
6668651 | 1 hr ago | 0.015 ETH | ||||
6668542 | 1 hr ago | 0.015 ETH | ||||
6668397 | 1 hr ago | 0.015 ETH | ||||
6667930 | 1 hr ago | 0.015 ETH | ||||
6667720 | 1 hr ago | 0.015 ETH | ||||
6667016 | 2 hrs ago | 0.015 ETH | ||||
6665373 | 2 hrs ago | 0.015 ETH | ||||
6665226 | 2 hrs ago | 0.015 ETH | ||||
6664844 | 2 hrs ago | 0.015 ETH | ||||
6664086 | 2 hrs ago | 0.015 ETH | ||||
6663960 | 2 hrs ago | 0.015 ETH | ||||
6663398 | 3 hrs ago | 0.015 ETH | ||||
6663257 | 3 hrs ago | 0.015 ETH | ||||
6662968 | 3 hrs ago | 0.015 ETH | ||||
6662854 | 3 hrs ago | 0.015 ETH | ||||
6662650 | 3 hrs ago | 0.015 ETH | ||||
6662252 | 3 hrs ago | 0.015 ETH | ||||
6658996 | 4 hrs ago | 0.015 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
Main
Compiler Version
v0.8.24+commit.e11b9ed9
ZkSolc Version
v1.5.12
Optimization Enabled:
Yes with Mode 3
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {EnumerableSetLib} from "solady/src/utils/EnumerableSetLib.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; import {IMinetendo} from "./interfaces/IMinetendo.sol"; import {IV3SwapRouter} from "./interfaces/ISwapRouter.sol"; import {Miner} from "./types/Miner.sol"; import {Facility} from "./types/Facility.sol"; import {NewFacility} from "./types/NewFacility.sol"; import {Errors} from "./libraries/Errors.sol"; import {Events} from "./libraries/Events.sol"; contract Main is Ownable { using EnumerableSetLib for EnumerableSetLib.Uint256Set; address public constant SWAP_ROUTER = 0x7712FA47387542819d4E35A23f8116C90C18767C; address public constant WETH = 0x3439153EB7AF838Ad19d56E1571FBD09333C2809; address public minetendo; /// @dev minetoshi fee recipient. address public minetoshi; /// @dev Mining start block. uint256 public startBlock; bool public miningHasStarted; // every miner has an id uint256 universalMinerId; /// @dev Total unique miners. uint256 public uniqueMinerCount; /// @dev Total facilities. uint256 public facilityCount; /// @dev Tracks last time we updated rewards. uint256 public lastRewardBlock; /// @dev Total network hashrate. uint256 public totalHashrate; bool public enableUpgradeFacility; /// @dev Tracks Minetendo per single hash. uint256 public cumulativeMinetendoPerHash; /// @dev Initial cooldown time is 24H. uint256 public cooldown = 24 hours; /// @dev Initial tier 1 referral fee is 2%. uint256 public referralFee = 0.02e18; /// @dev Initial tier 2 referral fee is 1%. uint256 public secondTierReferralFee = 0.01e18; /// @dev Initial burn is 80%. uint256 public burnPct = 0.8e18; /// @dev Players total hashrate. mapping(address => uint256) public playerHashrate; /// @dev Players pending rewards. mapping(address => uint256) public playerPendingRewards; /// @dev Players debt (updated after rewards are updated for a player). mapping(address => uint256) public playerMinetendoDebt; /// @dev Tracks different miners and its stats. mapping(uint256 => Miner) public miners; /// @dev Tracks different facilities and its stats. mapping(uint256 => NewFacility) public facilities; /// @dev Tracks how many of each miner a player has. Only tracks Id. mapping(address => EnumerableSetLib.Uint256Set) public playerMinersOwned; /// @dev Maps minerId to the actual miner struct mapping(uint256 => Miner) public playerMinersId; /// @dev Tracks players facility stats. mapping(address => Facility) public ownerToFacility; /// @dev Tracks new players initializing in the game. mapping(address => bool) public initializedStarterFacility; /// @dev Tracks if a player has acquired a free miner. mapping(address => bool) public acquiredStarterMiner; /// @dev Tracks if a there's a secondary market for a certain miner. mapping(uint256 => uint256) public minerSecondHandMarket; mapping(address => uint256) public lastFacilityUpgradeTimestamp; /// @dev Tracks direct referrals (tier 1). mapping(address => address) public referrals; /// @dev Tracks indirect referrals (tier 2) by storing the referrer of my referrer. mapping(address => address) public secondTierReferrals; /// @dev Tracks referred users. mapping(address => address[]) public referredUsers; /// @dev Track how much each referrer got paid from direct referrals. mapping(address => uint256) public referralBonusPaid; /// @dev Track how much each referrer got paid from indirect referrals. mapping(address => uint256) public secondTierReferralBonusPaid; /// @dev Purchasing initial facility price in ETH. uint256 public initialFacilityPrice = 0.01 ether; /// @dev start miner and facility index (these will never change since every player starts with same facility). uint256 public immutable STARTER_MINER_INDEX; uint256 public immutable STARTER_FACILITY_INDEX; /// @dev Halvening every 345,600 blocks, roughly 04 days uint256 public constant HALVING_INTERVAL = 345_600; /// @dev Initial Minetendo per block uint256 public constant INITIAL_MINETENDO_PER_BLOCK = 30e18; // 30 Minetendo per block uint256 public constant REWARDS_PRECISION = 1e18; // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // CONSTRUCTOR // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ constructor() Ownable(msg.sender) { STARTER_MINER_INDEX = ++uniqueMinerCount; // add starter free miner miners[STARTER_MINER_INDEX] = Miner( STARTER_MINER_INDEX, type(uint256).max, 10, 2, type(uint256).max, // this is the free starter miner, people cannot buy it false ); // add starter facility facilities[++facilityCount] = NewFacility( 1000, 500, type(uint256).max, // starter facility, people cannot buy it false ); STARTER_FACILITY_INDEX = facilityCount; } // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // USER FUNCTIONS // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ /** * @dev All new players must purchase an initial facility with ETH. * * Players can only purchase new facilities after acquiring initial Facility. */ function purchaseInitialFacility(address referrer) external payable { if (msg.value != initialFacilityPrice) { revert Errors.IncorrectValue(); } if (initializedStarterFacility[msg.sender]) { revert Errors.AlreadyPurchasedInitialFactory(); } if (referrer == msg.sender) { revert Errors.InvalidReferrer(); } initializedStarterFacility[msg.sender] = true; if (referrer != address(0)) { referrals[msg.sender] = referrer; referredUsers[referrer].push(msg.sender); // Set second tier referral (referrer's referrer) address secondTierReferrer = referrals[referrer]; if (secondTierReferrer != address(0)) { secondTierReferrals[msg.sender] = secondTierReferrer; } } NewFacility memory newFacility = facilities[STARTER_FACILITY_INDEX]; Facility storage facility = ownerToFacility[msg.sender]; // initialize players starter facility facility.facilityIndex = STARTER_FACILITY_INDEX; facility.maxMiners = newFacility.maxMiners; facility.totalPowerOutput = newFacility.totalPowerOutput; _getFreeStarterMiner(msg.sender); emit Events.InitialFacilityPurchased(msg.sender); } /** * @dev Purchase new miners using Minetendo. */ function buyMiner(uint256 minerIndex) external { // check user has enough funds for miner and facility allows it Miner memory miner = miners[minerIndex]; Facility storage facility = ownerToFacility[msg.sender]; // this case will cover if an index too large is passed in if (!miner.inProduction) revert Errors.MinerNotInProduction(); if (IMinetendo(minetendo).balanceOf(msg.sender) < miner.cost) { revert Errors.TooPoor(); } if ( facility.currPowerOutput + miner.powerConsumption > facility.totalPowerOutput ) { revert Errors.FacilityInadequatePowerOutput(); } // transfer correct amt of Minetendo IMinetendo(minetendo).transferFrom( msg.sender, address(this), miner.cost ); uint256 amountToBurn = FixedPointMathLib.mulWad(miner.cost, burnPct); // burn IMinetendo(minetendo).burn(amountToBurn); uint256 amountToETH = miner.cost - amountToBurn; // swap MINE to ETH _swapMINEtoETH(amountToETH); miner.id = ++universalMinerId; playerMinersOwned[msg.sender].add(universalMinerId); playerMinersId[universalMinerId] = miner; // increase facility miners facility.currMiners++; // increase power consumption from factory facility.currPowerOutput += miner.powerConsumption; emit Events.MinerBought( msg.sender, minerIndex, miner.cost, universalMinerId ); _increaseHashrate(msg.sender, miner.hashrate); } function sellMiner(uint256 minerId) external { if (!playerMinersOwned[msg.sender].contains(minerId)) { revert Errors.PlayerDoesNotOwnMiner(); } Miner memory miner = playerMinersId[minerId]; uint256 secondHandPrice = minerSecondHandMarket[miner.minerIndex]; if (secondHandPrice > IMinetendo(minetendo).balanceOf(address(this))) { revert Errors.GreatDepression(); } Facility storage facility = ownerToFacility[msg.sender]; facility.currMiners--; facility.currPowerOutput -= miner.powerConsumption; playerMinersOwned[msg.sender].remove(minerId); delete playerMinersId[minerId]; emit Events.MinerSold( msg.sender, miner.minerIndex, secondHandPrice, minerId ); _decreaseHashrate(msg.sender, miner.hashrate); if (secondHandPrice > 0) { IMinetendo(minetendo).transfer(msg.sender, secondHandPrice); } } /** * @dev Purchase larger or more power output facility. * * Players must linearly climb the facilities. */ function upgradeFacility() external { if (!enableUpgradeFacility) { revert Errors.UpgradeFacilityDisabled(); } // need to purchase initial facility first if (!initializedStarterFacility[msg.sender]) { revert Errors.NeedToInitializeFacility(); } Facility storage currFacility = ownerToFacility[msg.sender]; uint256 currFacilityIndex = currFacility.facilityIndex; if (currFacilityIndex == facilityCount) { revert Errors.AlreadyAtMaxFacility(); } // 24H cooldown between each facility upgrade if ( block.timestamp - lastFacilityUpgradeTimestamp[msg.sender] < cooldown ) { revert Errors.CantBuyNewFacilityYet(); } NewFacility memory newFacility = facilities[currFacilityIndex + 1]; if (!newFacility.inProduction) { revert Errors.NewFacilityNotInProduction(); } if (IMinetendo(minetendo).balanceOf(msg.sender) < newFacility.cost) { revert Errors.TooPoor(); } IMinetendo(minetendo).transferFrom( msg.sender, address(this), newFacility.cost ); uint256 amountToBurn = FixedPointMathLib.mulWad( newFacility.cost, burnPct ); // burn IMinetendo(minetendo).burn(amountToBurn); currFacility.facilityIndex++; currFacility.maxMiners = newFacility.maxMiners; currFacility.totalPowerOutput = newFacility.totalPowerOutput; lastFacilityUpgradeTimestamp[msg.sender] = block.timestamp; emit Events.FacilityBought( msg.sender, currFacility.facilityIndex, newFacility.cost ); } /** * @dev Claim rewards for player. */ function claimRewards() external { _updateRewards(msg.sender); uint256 rewards = playerPendingRewards[msg.sender]; if (rewards == 0) { revert Errors.NoRewardsPending(); } playerPendingRewards[msg.sender] = 0; // Calculate tier 1 and tier 2 referral bonuses uint256 tier1Bonus = FixedPointMathLib.mulWad(rewards, referralFee); uint256 tier2Bonus = FixedPointMathLib.mulWad( rewards, secondTierReferralFee ); uint256 finalRewards = rewards - tier1Bonus - tier2Bonus; // Mint rewards to player IMinetendo(minetendo).mint(msg.sender, finalRewards); // Handle tier 1 referral address tier1Referrer = referrals[msg.sender]; if (tier1Referrer != address(0)) { IMinetendo(minetendo).mint(tier1Referrer, tier1Bonus); referralBonusPaid[tier1Referrer] += tier1Bonus; } else { IMinetendo(minetendo).mint(address(this), tier1Bonus); referralBonusPaid[address(this)] += tier1Bonus; } // Handle tier 2 referral address tier2Referrer = secondTierReferrals[msg.sender]; if (tier2Referrer != address(0)) { IMinetendo(minetendo).mint(tier2Referrer, tier2Bonus); secondTierReferralBonusPaid[tier2Referrer] += tier2Bonus; } else { // No referrers at all, mint to contract IMinetendo(minetendo).mint(address(this), tier2Bonus); secondTierReferralBonusPaid[address(this)] += tier2Bonus; } emit Events.RewardsClaimed(msg.sender, rewards); } // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // INTERNAL FUNCTIONS // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ function _getFreeStarterMiner(address user) internal { if (acquiredStarterMiner[user]) { revert Errors.StarterMinerAlreadyAcquired(); } acquiredStarterMiner[user] = true; Miner memory miner = miners[STARTER_MINER_INDEX]; Facility storage facility = ownerToFacility[user]; if ( facility.currPowerOutput + miner.powerConsumption > facility.totalPowerOutput ) { revert Errors.FacilityInadequatePowerOutput(); } miner.id = ++universalMinerId; playerMinersOwned[user].add(universalMinerId); playerMinersId[universalMinerId] = miner; // increase facility miners facility.currMiners++; // increase power consumption from factory facility.currPowerOutput += miner.powerConsumption; // emit Events.FreeMinerRedeemed(user); emit Events.MinerBought(user, STARTER_MINER_INDEX, 0, universalMinerId); _increaseHashrate(user, miner.hashrate); } /** * @dev Update global cumulative rewards before game state changes. */ function _updateCumulativeRewards() internal { if (totalHashrate == 0) { lastRewardBlock = block.number; return; } uint256 currentBlock = lastRewardBlock; uint256 lastMinetendoPerBlock = INITIAL_MINETENDO_PER_BLOCK / (2 ** ((lastRewardBlock - startBlock) / HALVING_INTERVAL)); while (currentBlock < block.number) { uint256 nextHalvingBlock = (startBlock % HALVING_INTERVAL) + ((currentBlock / HALVING_INTERVAL) + 1) * HALVING_INTERVAL; uint256 endBlock = (nextHalvingBlock < block.number) ? nextHalvingBlock : block.number; // apply correct emission rate for this segment cumulativeMinetendoPerHash += ((lastMinetendoPerBlock * (endBlock - currentBlock) * REWARDS_PRECISION) / totalHashrate); // move to next segment currentBlock = endBlock; // if a halving has happened, apply the new rate if (currentBlock == nextHalvingBlock) { lastMinetendoPerBlock /= 2; } } lastRewardBlock = block.number; } function _updateRewards(address player) internal { _updateCumulativeRewards(); playerPendingRewards[player] += (playerHashrate[player] * (cumulativeMinetendoPerHash - playerMinetendoDebt[player])) / REWARDS_PRECISION; playerMinetendoDebt[player] = cumulativeMinetendoPerHash; } /** * @dev Increase players hashrate. */ function _increaseHashrate(address player, uint256 hashrate) internal { if (!miningHasStarted) { miningHasStarted = true; startBlock = block.number; lastRewardBlock = block.number; emit Events.MiningStarted(startBlock); } // update rewards and global state before modifying players state _updateRewards(player); totalHashrate += hashrate; playerHashrate[player] += hashrate; emit Events.PlayerHashrateIncreased( msg.sender, playerHashrate[player], playerPendingRewards[player] ); } /** * @dev Decrease players hashrate. */ function _decreaseHashrate(address player, uint256 hashrate) internal { // update rewards and global state before modifying players state _updateRewards(player); totalHashrate -= hashrate; playerHashrate[player] -= hashrate; emit Events.PlayerHashrateDecreased( msg.sender, playerHashrate[player], playerPendingRewards[player] ); } function _swapMINEtoETH(uint256 _amount) internal { IMinetendo(minetendo).approve(SWAP_ROUTER, _amount); try IV3SwapRouter(SWAP_ROUTER).exactInputSingle( IV3SwapRouter.ExactInputSingleParams({ tokenIn: minetendo, tokenOut: WETH, fee: 10000, recipient: minetoshi, amountIn: _amount, amountOutMinimum: 0, sqrtPriceLimitX96: 0 }) ) {} catch {} } // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // VIEW FUNCTIONS // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ /** * @dev Get the current mining emission rate based on halvings */ function getMinetendoPerBlock() public view returns (uint256) { if (!miningHasStarted) { return 0; } uint256 halvingsSinceStart = (block.number - startBlock) / HALVING_INTERVAL; return INITIAL_MINETENDO_PER_BLOCK / (2 ** halvingsSinceStart); } /** * @dev Get current pending rewards for player. */ function pendingRewards(address player) external view returns (uint256) { // below is basically the same logic as _updateCumulativeRewards() but doesnt change state if (!miningHasStarted) { return 0; } if (totalHashrate == 0) { return FixedPointMathLib.mulWad( playerPendingRewards[player], 1e18 - referralFee - secondTierReferralFee ); } uint256 currentBlock = lastRewardBlock; uint256 lastMinetendoPerBlock = INITIAL_MINETENDO_PER_BLOCK / (2 ** ((lastRewardBlock - startBlock) / HALVING_INTERVAL)); uint256 simulatedCumulativeMinetendoPerHash = cumulativeMinetendoPerHash; while (currentBlock < block.number) { uint256 nextHalvingBlock = (startBlock % HALVING_INTERVAL) + ((currentBlock / HALVING_INTERVAL) + 1) * HALVING_INTERVAL; uint256 endBlock = (nextHalvingBlock < block.number) ? nextHalvingBlock : block.number; // simulate rewards accumulation if (totalHashrate > 0) { simulatedCumulativeMinetendoPerHash += ((lastMinetendoPerBlock * (endBlock - currentBlock) * REWARDS_PRECISION) / totalHashrate); } // move to next segment currentBlock = endBlock; // if we reached a halving point, apply the new emission rate if (currentBlock == nextHalvingBlock) { lastMinetendoPerBlock /= 2; } } return FixedPointMathLib.mulWad( playerPendingRewards[player] + ((playerHashrate[player] * (simulatedCumulativeMinetendoPerHash - playerMinetendoDebt[player])) / REWARDS_PRECISION), 1e18 - referralFee - secondTierReferralFee ); } function playerMinetendoPerBlock( address player ) external view returns (uint256) { if (totalHashrate == 0) { return 0; // Prevent division by zero } uint256 currMinetendoPerBlock = INITIAL_MINETENDO_PER_BLOCK / (2 ** ((block.number - startBlock) / HALVING_INTERVAL)); return FixedPointMathLib.mulDiv( playerHashrate[player], currMinetendoPerBlock, totalHashrate ); } /** * @dev Get blocks till next halvening. */ function blocksUntilNextHalving() external view returns (uint256) { if (startBlock == 0) revert Errors.MiningHasntStarted(); uint256 nextHalvingBlock = (startBlock % HALVING_INTERVAL) + ((block.number / HALVING_INTERVAL) + 1) * HALVING_INTERVAL; return nextHalvingBlock - block.number; } /** * @dev Get next available facility upgrade time. */ function timeUntilNextFacilityUpgrade( address player ) external view returns (uint256) { if (lastFacilityUpgradeTimestamp[player] + cooldown < block.timestamp) { return 0; } return (lastFacilityUpgradeTimestamp[player] + cooldown) - block.timestamp; } /** * @dev Get all miners for a player. */ function getPlayerMinersPaginated( address player, uint256 startIndex, uint256 size ) external view returns (Miner[] memory) { EnumerableSetLib.Uint256Set storage set = playerMinersOwned[player]; uint256 length = set.length(); // Return empty array if start index is beyond array bounds if (startIndex >= length) { return new Miner[](0); } // Calculate how many items we can actually return uint256 remaining = length - startIndex; uint256 returnSize = size > remaining ? remaining : size; Miner[] memory playerMiners = new Miner[](returnSize); for (uint256 i = 0; i < returnSize; i++) { playerMiners[i] = playerMinersId[set.at(startIndex + i)]; } return playerMiners; } function getTotalMiners(address player) external view returns (uint256) { return playerMinersOwned[player].length(); } /** * @dev Get all referred users. */ function getReferrals( address referrer ) external view returns (address[] memory) { return referredUsers[referrer]; } // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // OWNER FUNCTIONS // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ /** * @dev Add new miner to game. */ function addMiner( uint256 hashrate, uint256 powerConsumption, uint256 cost, bool inProduction ) external onlyOwner { // must increment first cause compiler evaluates function arg before evaluating the assignment ++uniqueMinerCount; miners[uniqueMinerCount] = Miner( uniqueMinerCount, 0, hashrate, powerConsumption, cost, inProduction ); emit Events.NewMinerAdded( uniqueMinerCount, hashrate, powerConsumption, cost, inProduction ); } /** * @dev Allows or prevents miner from being purchased. * * Miners cannot be removed, only toggled off from purchased. */ function toggleMinerProduction( uint256 minerIndex, bool inProduction ) external onlyOwner { if (minerIndex < STARTER_MINER_INDEX || minerIndex > uniqueMinerCount) { revert Errors.InvalidMinerIndex(); } Miner storage miner = miners[minerIndex]; miner.inProduction = inProduction; emit Events.MinerProductionToggled(minerIndex, inProduction); } /** * @dev Add new facility to game. */ function addFacility( uint256 maxMiners, uint256 totalPowerOutput, uint256 cost, bool inProduction ) external onlyOwner { if (facilities[facilityCount].totalPowerOutput > totalPowerOutput) { revert Errors.InvalidPowerOutput(); } facilities[++facilityCount] = NewFacility( maxMiners, totalPowerOutput, cost, inProduction ); emit Events.NewFacilityAdded( facilityCount, totalPowerOutput, cost, inProduction ); } /** * @dev Allows or prevents new facilities from being purchased. * * New facilities cannot be removed, only toggled off from purchased. */ function toggleFacilityProduction( uint256 facilityIndex, bool inProduction ) external onlyOwner { if ( facilityIndex < STARTER_FACILITY_INDEX || facilityIndex > facilityCount ) { revert Errors.InvalidFacilityIndex(); } NewFacility storage facility = facilities[facilityIndex]; facility.inProduction = inProduction; emit Events.FacilityProductionToggled(facilityIndex, inProduction); } /** * @dev Add secondary market for a miner. */ function addSecondaryMarketForMiner( uint256 minerIndex, uint256 price ) external onlyOwner { minerSecondHandMarket[minerIndex] = price; emit Events.MinerSecondaryMarketAdded(minerIndex, price); } function setMinetendo(address _minetendo) external onlyOwner { minetendo = _minetendo; } function setMinetoshi(address _minetoshi) external onlyOwner { minetoshi = _minetoshi; } function setInitialFacilityPrice(uint256 _initialPrice) external onlyOwner { initialFacilityPrice = _initialPrice; } function setReferralFee(uint256 fee) external onlyOwner { if (fee > 1e18) revert Errors.InvalidFee(); referralFee = fee; } function setSecondTierReferralFee(uint256 fee) external onlyOwner { if (fee > 1e18) revert Errors.InvalidFee(); secondTierReferralFee = fee; } function setBurnPct(uint256 burn) external onlyOwner { if (burn > 1e18) revert Errors.InvalidFee(); burnPct = burn; } function setEnableUpgradeFacility(bool enable) external onlyOwner { enableUpgradeFacility = enable; } function setCooldown(uint256 _cooldown) external onlyOwner { cooldown = _cooldown; } function withdraw() external onlyOwner { uint256 balance = address(this).balance; (bool success, ) = payable(minetoshi).call{value: balance}(""); if (!success) revert Errors.WithdrawFailed(); } function withdrawMinetendo(uint256 amt) external onlyOwner { IMinetendo(minetendo).transfer(minetoshi, amt); } function changeMinerCost( uint256 minerIndex, uint256 newCost ) external onlyOwner { if (minerIndex > uniqueMinerCount) { revert Errors.NonExistentMiner(); } if (minerIndex == STARTER_MINER_INDEX) { revert Errors.CantModifyStarterMiner(); } Miner storage miner = miners[minerIndex]; miner.cost = newCost; emit Events.MinerCostChanged(minerIndex, newCost); } function changeFacilityCost( uint256 facilityIndex, uint256 newCost ) external onlyOwner { if (facilityIndex > facilityCount) { revert Errors.NonExistentFacility(); } if (facilityIndex == STARTER_FACILITY_INDEX) { revert Errors.CantModifyStarterFacility(); } NewFacility storage facility = facilities[facilityIndex]; facility.cost = newCost; emit Events.FacilityCostChanged(facilityIndex, newCost); } function changeMinerPowerConsumption( uint256 minerIndex, uint256 newPowerConsumption ) external onlyOwner { if (minerIndex > uniqueMinerCount) { revert Errors.NonExistentMiner(); } Miner storage miner = miners[minerIndex]; miner.powerConsumption = newPowerConsumption; emit Events.MinerPowerConsumptionChanged( minerIndex, newPowerConsumption ); } }
//SPDX-License-Identifier: Unlicense pragma solidity ^0.8.24; interface IMinetendo { function mint(address to, uint256 amt) external; function burn(uint256 value) external; function totalSupply() external view returns (uint256); function balanceOf(address account) external view returns (uint256); function transfer(address to, uint256 value) external returns (bool); function allowance(address owner, address spender) external view returns (uint256); function approve(address spender, uint256 value) external returns (bool); function transferFrom(address from, address to, uint256 value) external returns (bool); function setMinter(address _minter) external; function amtBurned() external view returns (uint256); function minter() external view returns (address); function MAX_SUPPLY() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /** * @dev Facilities that can be purchased in game. */ struct NewFacility { uint256 maxMiners; uint256 totalPowerOutput; uint256 cost; bool inProduction; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.7.5; /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface IV3SwapRouter { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, /// and swap the entire amount, enabling contracts to send tokens before calling this function. /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle( ExactInputSingleParams calldata params ) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @dev Setting `amountIn` to 0 will cause the contract to look up its own balance, /// and swap the entire amount, enabling contracts to send tokens before calling this function. /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput( ExactInputParams calldata params ) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// that may remain in the router after the swap. /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle( ExactOutputSingleParams calldata params ) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// that may remain in the router after the swap. /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput( ExactOutputParams calldata params ) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /** * @dev Miners that can be purchased in the game. */ struct Miner { uint256 minerIndex; uint256 id; uint256 hashrate; uint256 powerConsumption; uint256 cost; bool inProduction; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; library Errors { error IncorrectValue(); error AlreadyPurchasedInitialFactory(); error StarterMinerAlreadyAcquired(); error FacilityAtMaxCapacity(); error FacilityInadequatePowerOutput(); error PlayerDoesNotOwnMiner(); error GreatDepression(); error MinerNotInProduction(); error TooPoor(); error NewFacilityNotInProduction(); error CannotDowngradeAFacility(); error NoRewardsPending(); error CannotDecreaseBelowZero(); error InvalidMinerCoordinates(); error NeedToInitializeFacility(); error InvalidReferrer(); error NonExistentMiner(); error CantModifyStarterMiner(); error NonExistentFacility(); error CantModifyStarterFacility(); error AlreadyAtMaxFacility(); error CantBuyNewFacilityYet(); error InvalidMinerIndex(); error InvalidFacilityIndex(); error InvalidFee(); error InvalidPowerOutput(); error MiningHasntStarted(); error WithdrawFailed(); error UpgradeFacilityDisabled(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; /** * @dev Current player's facility. */ struct Facility { uint256 facilityIndex; uint256 maxMiners; uint256 currMiners; uint256 totalPowerOutput; uint256 currPowerOutput; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; library Events { event MiningStarted(uint256 startBlock); event NewMinerAdded( uint256 indexed minerIndex, uint256 hashRate, uint256 powerConsumption, uint256 cost, bool inProduction ); event MinerProductionToggled(uint256 indexed minerIndex, bool inProduction); event FacilityProductionToggled( uint256 indexed facilityIndex, bool inProduction ); event NewFacilityAdded( uint256 indexed facilityIndex, uint256 totalPowerOutput, uint256 cost, bool inProduction ); event MinerSecondaryMarketAdded(uint256 indexed minerIndex, uint256 price); event InitialFacilityPurchased(address indexed player); event FreeMinerRedeemed(address indexed player); event MinerSold( address indexed player, uint256 indexed minerIndex, uint256 secondHandPrice, uint256 minerId ); event MinerBought( address indexed player, uint256 indexed minerIndex, uint256 cost, uint256 minerId ); event FacilityBought( address indexed player, uint256 indexed facilityIndex, uint256 cost ); event PlayerHashrateIncreased( address indexed player, uint256 playerHashrate, uint256 playerPendingRewards ); event PlayerHashrateDecreased( address indexed player, uint256 playerHashrate, uint256 playerPendingRewards ); event RewardsClaimed(address indexed player, uint256 rewards); event MinerCostChanged(uint256 indexed minerIndex, uint256 newCost); event FacilityCostChanged(uint256 indexed facilityIndex, uint256 newCost); event JackpotETHSwapped(uint256 amountIn, uint256 amountOut); event MinerPowerConsumptionChanged( uint256 indexed minerIndex, uint256 newPowerConsumption ); }
// 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); } }
// 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 } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol) /// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) library FixedPointMathLib { /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CUSTOM ERRORS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The operation failed, as the output exceeds the maximum value of uint256. error ExpOverflow(); /// @dev The operation failed, as the output exceeds the maximum value of uint256. error FactorialOverflow(); /// @dev The operation failed, due to an overflow. error RPowOverflow(); /// @dev The mantissa is too big to fit. error MantissaOverflow(); /// @dev The operation failed, due to an multiplication overflow. error MulWadFailed(); /// @dev The operation failed, due to an multiplication overflow. error SMulWadFailed(); /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero. error DivWadFailed(); /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero. error SDivWadFailed(); /// @dev The operation failed, either due to a multiplication overflow, or a division by a zero. error MulDivFailed(); /// @dev The division failed, as the denominator is zero. error DivFailed(); /// @dev The full precision multiply-divide operation failed, either due /// to the result being larger than 256 bits, or a division by a zero. error FullMulDivFailed(); /// @dev The output is undefined, as the input is less-than-or-equal to zero. error LnWadUndefined(); /// @dev The input outside the acceptable domain. error OutOfDomain(); /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* CONSTANTS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev The scalar of ETH and most ERC20s. uint256 internal constant WAD = 1e18; /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* SIMPLIFIED FIXED POINT OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Equivalent to `(x * y) / WAD` rounded down. function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`. if gt(x, div(not(0), y)) { if y { mstore(0x00, 0xbac65e5b) // `MulWadFailed()`. revert(0x1c, 0x04) } } z := div(mul(x, y), WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded down. function sMulWad(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) // Equivalent to `require((x == 0 || z / x == y) && !(x == -1 && y == type(int256).min))`. if iszero(gt(or(iszero(x), eq(sdiv(z, x), y)), lt(not(x), eq(y, shl(255, 1))))) { mstore(0x00, 0xedcd4dd4) // `SMulWadFailed()`. revert(0x1c, 0x04) } z := sdiv(z, WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks. function rawMulWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(mul(x, y), WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded down, but without overflow checks. function rawSMulWad(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := sdiv(mul(x, y), WAD) } } /// @dev Equivalent to `(x * y) / WAD` rounded up. function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) // Equivalent to `require(y == 0 || x <= type(uint256).max / y)`. if iszero(eq(div(z, y), x)) { if y { mstore(0x00, 0xbac65e5b) // `MulWadFailed()`. revert(0x1c, 0x04) } } z := add(iszero(iszero(mod(z, WAD))), div(z, WAD)) } } /// @dev Equivalent to `(x * y) / WAD` rounded up, but without overflow checks. function rawMulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD)) } } /// @dev Equivalent to `(x * WAD) / y` rounded down. function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to `require(y != 0 && x <= type(uint256).max / WAD)`. if iszero(mul(y, lt(x, add(1, div(not(0), WAD))))) { mstore(0x00, 0x7c5f487d) // `DivWadFailed()`. revert(0x1c, 0x04) } z := div(mul(x, WAD), y) } } /// @dev Equivalent to `(x * WAD) / y` rounded down. function sDivWad(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, WAD) // Equivalent to `require(y != 0 && ((x * WAD) / WAD == x))`. if iszero(mul(y, eq(sdiv(z, WAD), x))) { mstore(0x00, 0x5c43740d) // `SDivWadFailed()`. revert(0x1c, 0x04) } z := sdiv(z, y) } } /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks. function rawDivWad(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(mul(x, WAD), y) } } /// @dev Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks. function rawSDivWad(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := sdiv(mul(x, WAD), y) } } /// @dev Equivalent to `(x * WAD) / y` rounded up. function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to `require(y != 0 && x <= type(uint256).max / WAD)`. if iszero(mul(y, lt(x, add(1, div(not(0), WAD))))) { mstore(0x00, 0x7c5f487d) // `DivWadFailed()`. revert(0x1c, 0x04) } z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y)) } } /// @dev Equivalent to `(x * WAD) / y` rounded up, but without overflow and divide by zero checks. function rawDivWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := add(iszero(iszero(mod(mul(x, WAD), y))), div(mul(x, WAD), y)) } } /// @dev Equivalent to `x` to the power of `y`. /// because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`. /// Note: This function is an approximation. function powWad(int256 x, int256 y) internal pure returns (int256) { // Using `ln(x)` means `x` must be greater than 0. return expWad((lnWad(x) * y) / int256(WAD)); } /// @dev Returns `exp(x)`, denominated in `WAD`. /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln /// Note: This function is an approximation. Monotonically increasing. function expWad(int256 x) internal pure returns (int256 r) { unchecked { // When the result is less than 0.5 we return zero. // This happens when `x <= (log(1e-18) * 1e18) ~ -4.15e19`. if (x <= -41446531673892822313) return r; /// @solidity memory-safe-assembly assembly { // When the result is greater than `(2**255 - 1) / 1e18` we can not represent it as // an int. This happens when `x >= floor(log((2**255 - 1) / 1e18) * 1e18) ≈ 135`. if iszero(slt(x, 135305999368893231589)) { mstore(0x00, 0xa37bfec9) // `ExpOverflow()`. revert(0x1c, 0x04) } } // `x` is now in the range `(-42, 136) * 1e18`. Convert to `(-42, 136) * 2**96` // for more intermediate precision and a binary basis. This base conversion // is a multiplication by 1e18 / 2**96 = 5**18 / 2**78. x = (x << 78) / 5 ** 18; // Reduce range of x to (-½ ln 2, ½ ln 2) * 2**96 by factoring out powers // of two such that exp(x) = exp(x') * 2**k, where k is an integer. // Solving this gives k = round(x / log(2)) and x' = x - k * log(2). int256 k = ((x << 96) / 54916777467707473351141471128 + 2 ** 95) >> 96; x = x - k * 54916777467707473351141471128; // `k` is in the range `[-61, 195]`. // Evaluate using a (6, 7)-term rational approximation. // `p` is made monic, we'll multiply by a scale factor later. int256 y = x + 1346386616545796478920950773328; y = ((y * x) >> 96) + 57155421227552351082224309758442; int256 p = y + x - 94201549194550492254356042504812; p = ((p * y) >> 96) + 28719021644029726153956944680412240; p = p * x + (4385272521454847904659076985693276 << 96); // We leave `p` in `2**192` basis so we don't need to scale it back up for the division. int256 q = x - 2855989394907223263936484059900; q = ((q * x) >> 96) + 50020603652535783019961831881945; q = ((q * x) >> 96) - 533845033583426703283633433725380; q = ((q * x) >> 96) + 3604857256930695427073651918091429; q = ((q * x) >> 96) - 14423608567350463180887372962807573; q = ((q * x) >> 96) + 26449188498355588339934803723976023; /// @solidity memory-safe-assembly assembly { // Div in assembly because solidity adds a zero check despite the unchecked. // The q polynomial won't have zeros in the domain as all its roots are complex. // No scaling is necessary because p is already `2**96` too large. r := sdiv(p, q) } // r should be in the range `(0.09, 0.25) * 2**96`. // We now need to multiply r by: // - The scale factor `s ≈ 6.031367120`. // - The `2**k` factor from the range reduction. // - The `1e18 / 2**96` factor for base conversion. // We do this all at once, with an intermediate result in `2**213` // basis, so the final right shift is always by a positive amount. r = int256( (uint256(r) * 3822833074963236453042738258902158003155416615667) >> uint256(195 - k) ); } } /// @dev Returns `ln(x)`, denominated in `WAD`. /// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln /// Note: This function is an approximation. Monotonically increasing. function lnWad(int256 x) internal pure returns (int256 r) { /// @solidity memory-safe-assembly assembly { // We want to convert `x` from `10**18` fixed point to `2**96` fixed point. // We do this by multiplying by `2**96 / 10**18`. But since // `ln(x * C) = ln(x) + ln(C)`, we can simply do nothing here // and add `ln(2**96 / 10**18)` at the end. // Compute `k = log2(x) - 96`, `r = 159 - k = 255 - log2(x) = 255 ^ log2(x)`. r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // We place the check here for more optimal stack operations. if iszero(sgt(x, 0)) { mstore(0x00, 0x1615e638) // `LnWadUndefined()`. revert(0x1c, 0x04) } // forgefmt: disable-next-item r := xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)) // Reduce range of x to (1, 2) * 2**96 // ln(2^k * x) = k * ln(2) + ln(x) x := shr(159, shl(r, x)) // Evaluate using a (8, 8)-term rational approximation. // `p` is made monic, we will multiply by a scale factor later. // forgefmt: disable-next-item let p := sub( // This heavily nested expression is to avoid stack-too-deep for via-ir. sar(96, mul(add(43456485725739037958740375743393, sar(96, mul(add(24828157081833163892658089445524, sar(96, mul(add(3273285459638523848632254066296, x), x))), x))), x)), 11111509109440967052023855526967) p := sub(sar(96, mul(p, x)), 45023709667254063763336534515857) p := sub(sar(96, mul(p, x)), 14706773417378608786704636184526) p := sub(mul(p, x), shl(96, 795164235651350426258249787498)) // We leave `p` in `2**192` basis so we don't need to scale it back up for the division. // `q` is monic by convention. let q := add(5573035233440673466300451813936, x) q := add(71694874799317883764090561454958, sar(96, mul(x, q))) q := add(283447036172924575727196451306956, sar(96, mul(x, q))) q := add(401686690394027663651624208769553, sar(96, mul(x, q))) q := add(204048457590392012362485061816622, sar(96, mul(x, q))) q := add(31853899698501571402653359427138, sar(96, mul(x, q))) q := add(909429971244387300277376558375, sar(96, mul(x, q))) // `p / q` is in the range `(0, 0.125) * 2**96`. // Finalization, we need to: // - Multiply by the scale factor `s = 5.549…`. // - Add `ln(2**96 / 10**18)`. // - Add `k * ln(2)`. // - Multiply by `10**18 / 2**96 = 5**18 >> 78`. // The q polynomial is known not to have zeros in the domain. // No scaling required because p is already `2**96` too large. p := sdiv(p, q) // Multiply by the scaling factor: `s * 5**18 * 2**96`, base is now `5**18 * 2**192`. p := mul(1677202110996718588342820967067443963516166, p) // Add `ln(2) * k * 5**18 * 2**192`. // forgefmt: disable-next-item p := add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, r)), p) // Add `ln(2**96 / 10**18) * 5**18 * 2**192`. p := add(600920179829731861736702779321621459595472258049074101567377883020018308, p) // Base conversion: mul `2**18 / 2**192`. r := sar(174, p) } } /// @dev Returns `W_0(x)`, denominated in `WAD`. /// See: https://en.wikipedia.org/wiki/Lambert_W_function /// a.k.a. Product log function. This is an approximation of the principal branch. /// Note: This function is an approximation. Monotonically increasing. function lambertW0Wad(int256 x) internal pure returns (int256 w) { // forgefmt: disable-next-item unchecked { if ((w = x) <= -367879441171442322) revert OutOfDomain(); // `x` less than `-1/e`. (int256 wad, int256 p) = (int256(WAD), x); uint256 c; // Whether we need to avoid catastrophic cancellation. uint256 i = 4; // Number of iterations. if (w <= 0x1ffffffffffff) { if (-0x4000000000000 <= w) { i = 1; // Inputs near zero only take one step to converge. } else if (w <= -0x3ffffffffffffff) { i = 32; // Inputs near `-1/e` take very long to converge. } } else if (uint256(w >> 63) == uint256(0)) { /// @solidity memory-safe-assembly assembly { // Inline log2 for more performance, since the range is small. let v := shr(49, w) let l := shl(3, lt(0xff, v)) l := add(or(l, byte(and(0x1f, shr(shr(l, v), 0x8421084210842108cc6318c6db6d54be)), 0x0706060506020504060203020504030106050205030304010505030400000000)), 49) w := sdiv(shl(l, 7), byte(sub(l, 31), 0x0303030303030303040506080c13)) c := gt(l, 60) i := add(2, add(gt(l, 53), c)) } } else { int256 ll = lnWad(w = lnWad(w)); /// @solidity memory-safe-assembly assembly { // `w = ln(x) - ln(ln(x)) + b * ln(ln(x)) / ln(x)`. w := add(sdiv(mul(ll, 1023715080943847266), w), sub(w, ll)) i := add(3, iszero(shr(68, x))) c := iszero(shr(143, x)) } if (c == uint256(0)) { do { // If `x` is big, use Newton's so that intermediate values won't overflow. int256 e = expWad(w); /// @solidity memory-safe-assembly assembly { let t := mul(w, div(e, wad)) w := sub(w, sdiv(sub(t, x), div(add(e, t), wad))) } if (p <= w) break; p = w; } while (--i != uint256(0)); /// @solidity memory-safe-assembly assembly { w := sub(w, sgt(w, 2)) } return w; } } do { // Otherwise, use Halley's for faster convergence. int256 e = expWad(w); /// @solidity memory-safe-assembly assembly { let t := add(w, wad) let s := sub(mul(w, e), mul(x, wad)) w := sub(w, sdiv(mul(s, wad), sub(mul(e, t), sdiv(mul(add(t, wad), s), add(t, t))))) } if (p <= w) break; p = w; } while (--i != c); /// @solidity memory-safe-assembly assembly { w := sub(w, sgt(w, 2)) } // For certain ranges of `x`, we'll use the quadratic-rate recursive formula of // R. Iacono and J.P. Boyd for the last iteration, to avoid catastrophic cancellation. if (c == uint256(0)) return w; int256 t = w | 1; /// @solidity memory-safe-assembly assembly { x := sdiv(mul(x, wad), t) } x = (t * (wad + lnWad(x))); /// @solidity memory-safe-assembly assembly { w := sdiv(x, add(wad, t)) } } } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* GENERAL NUMBER UTILITIES */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `a * b == x * y`, with full precision. function fullMulEq(uint256 a, uint256 b, uint256 x, uint256 y) internal pure returns (bool result) { /// @solidity memory-safe-assembly assembly { result := and(eq(mul(a, b), mul(x, y)), eq(mulmod(x, y, not(0)), mulmod(a, b, not(0)))) } } /// @dev Calculates `floor(x * y / d)` with full precision. /// Throws if result overflows a uint256 or when `d` is zero. /// Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv function fullMulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // 512-bit multiply `[p1 p0] = x * y`. // Compute the product mod `2**256` and mod `2**256 - 1` // then use the Chinese Remainder Theorem to reconstruct // the 512 bit result. The result is stored in two 256 // variables such that `product = p1 * 2**256 + p0`. // Temporarily use `z` as `p0` to save gas. z := mul(x, y) // Lower 256 bits of `x * y`. for {} 1 {} { // If overflows. if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) { let mm := mulmod(x, y, not(0)) let p1 := sub(mm, add(z, lt(mm, z))) // Upper 256 bits of `x * y`. /*------------------- 512 by 256 division --------------------*/ // Make division exact by subtracting the remainder from `[p1 p0]`. let r := mulmod(x, y, d) // Compute remainder using mulmod. let t := and(d, sub(0, d)) // The least significant bit of `d`. `t >= 1`. // Make sure `z` is less than `2**256`. Also prevents `d == 0`. // Placing the check here seems to give more optimal stack operations. if iszero(gt(d, p1)) { mstore(0x00, 0xae47f702) // `FullMulDivFailed()`. revert(0x1c, 0x04) } d := div(d, t) // Divide `d` by `t`, which is a power of two. // Invert `d mod 2**256` // Now that `d` is an odd number, it has an inverse // modulo `2**256` such that `d * inv = 1 mod 2**256`. // Compute the inverse by starting with a seed that is correct // correct for four bits. That is, `d * inv = 1 mod 2**4`. let inv := xor(2, mul(3, d)) // Now use Newton-Raphson iteration to improve the precision. // Thanks to Hensel's lifting lemma, this also works in modular // arithmetic, doubling the correct bits in each step. inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**8 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**16 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**32 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**64 inv := mul(inv, sub(2, mul(d, inv))) // inverse mod 2**128 z := mul( // Divide [p1 p0] by the factors of two. // Shift in bits from `p1` into `p0`. For this we need // to flip `t` such that it is `2**256 / t`. or(mul(sub(p1, gt(r, z)), add(div(sub(0, t), t), 1)), div(sub(z, r), t)), mul(sub(2, mul(d, inv)), inv) // inverse mod 2**256 ) break } z := div(z, d) break } } } /// @dev Calculates `floor(x * y / d)` with full precision. /// Behavior is undefined if `d` is zero or the final result cannot fit in 256 bits. /// Performs the full 512 bit calculation regardless. function fullMulDivUnchecked(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) let mm := mulmod(x, y, not(0)) let p1 := sub(mm, add(z, lt(mm, z))) let t := and(d, sub(0, d)) let r := mulmod(x, y, d) d := div(d, t) let inv := xor(2, mul(3, d)) inv := mul(inv, sub(2, mul(d, inv))) inv := mul(inv, sub(2, mul(d, inv))) inv := mul(inv, sub(2, mul(d, inv))) inv := mul(inv, sub(2, mul(d, inv))) inv := mul(inv, sub(2, mul(d, inv))) z := mul( or(mul(sub(p1, gt(r, z)), add(div(sub(0, t), t), 1)), div(sub(z, r), t)), mul(sub(2, mul(d, inv)), inv) ) } } /// @dev Calculates `floor(x * y / d)` with full precision, rounded up. /// Throws if result overflows a uint256 or when `d` is zero. /// Credit to Uniswap-v3-core under MIT license: /// https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/FullMath.sol function fullMulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { z = fullMulDiv(x, y, d); /// @solidity memory-safe-assembly assembly { if mulmod(x, y, d) { z := add(z, 1) if iszero(z) { mstore(0x00, 0xae47f702) // `FullMulDivFailed()`. revert(0x1c, 0x04) } } } } /// @dev Calculates `floor(x * y / 2 ** n)` with full precision. /// Throws if result overflows a uint256. /// Credit to Philogy under MIT license: /// https://github.com/SorellaLabs/angstrom/blob/main/contracts/src/libraries/X128MathLib.sol function fullMulDivN(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Temporarily use `z` as `p0` to save gas. z := mul(x, y) // Lower 256 bits of `x * y`. We'll call this `z`. for {} 1 {} { if iszero(or(iszero(x), eq(div(z, x), y))) { let k := and(n, 0xff) // `n`, cleaned. let mm := mulmod(x, y, not(0)) let p1 := sub(mm, add(z, lt(mm, z))) // Upper 256 bits of `x * y`. // | p1 | z | // Before: | p1_0 ¦ p1_1 | z_0 ¦ z_1 | // Final: | 0 ¦ p1_0 | p1_1 ¦ z_0 | // Check that final `z` doesn't overflow by checking that p1_0 = 0. if iszero(shr(k, p1)) { z := add(shl(sub(256, k), p1), shr(k, z)) break } mstore(0x00, 0xae47f702) // `FullMulDivFailed()`. revert(0x1c, 0x04) } z := shr(and(n, 0xff), z) break } } } /// @dev Returns `floor(x * y / d)`. /// Reverts if `x * y` overflows, or `d` is zero. function mulDiv(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) // Equivalent to `require(d != 0 && (y == 0 || x <= type(uint256).max / y))`. if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) { mstore(0x00, 0xad251c27) // `MulDivFailed()`. revert(0x1c, 0x04) } z := div(z, d) } } /// @dev Returns `ceil(x * y / d)`. /// Reverts if `x * y` overflows, or `d` is zero. function mulDivUp(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(x, y) // Equivalent to `require(d != 0 && (y == 0 || x <= type(uint256).max / y))`. if iszero(mul(or(iszero(x), eq(div(z, x), y)), d)) { mstore(0x00, 0xad251c27) // `MulDivFailed()`. revert(0x1c, 0x04) } z := add(iszero(iszero(mod(z, d))), div(z, d)) } } /// @dev Returns `x`, the modular multiplicative inverse of `a`, such that `(a * x) % n == 1`. function invMod(uint256 a, uint256 n) internal pure returns (uint256 x) { /// @solidity memory-safe-assembly assembly { let g := n let r := mod(a, n) for { let y := 1 } 1 {} { let q := div(g, r) let t := g g := r r := sub(t, mul(r, q)) let u := x x := y y := sub(u, mul(y, q)) if iszero(r) { break } } x := mul(eq(g, 1), add(x, mul(slt(x, 0), n))) } } /// @dev Returns `ceil(x / d)`. /// Reverts if `d` is zero. function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { if iszero(d) { mstore(0x00, 0x65244e4e) // `DivFailed()`. revert(0x1c, 0x04) } z := add(iszero(iszero(mod(x, d))), div(x, d)) } } /// @dev Returns `max(0, x - y)`. Alias for `saturatingSub`. function zeroFloorSub(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(gt(x, y), sub(x, y)) } } /// @dev Returns `max(0, x - y)`. function saturatingSub(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(gt(x, y), sub(x, y)) } } /// @dev Returns `min(2 ** 256 - 1, x + y)`. function saturatingAdd(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := or(sub(0, lt(add(x, y), x)), add(x, y)) } } /// @dev Returns `min(2 ** 256 - 1, x * y)`. function saturatingMul(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := or(sub(or(iszero(x), eq(div(mul(x, y), x), y)), 1), mul(x, y)) } } /// @dev Returns `condition ? x : y`, without branching. function ternary(bool condition, uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), iszero(condition))) } } /// @dev Returns `condition ? x : y`, without branching. function ternary(bool condition, bytes32 x, bytes32 y) internal pure returns (bytes32 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), iszero(condition))) } } /// @dev Returns `condition ? x : y`, without branching. function ternary(bool condition, address x, address y) internal pure returns (address z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), iszero(condition))) } } /// @dev Returns `x != 0 ? x : y`, without branching. function coalesce(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := or(x, mul(y, iszero(x))) } } /// @dev Returns `x != bytes32(0) ? x : y`, without branching. function coalesce(bytes32 x, bytes32 y) internal pure returns (bytes32 z) { /// @solidity memory-safe-assembly assembly { z := or(x, mul(y, iszero(x))) } } /// @dev Returns `x != address(0) ? x : y`, without branching. function coalesce(address x, address y) internal pure returns (address z) { /// @solidity memory-safe-assembly assembly { z := or(x, mul(y, iszero(shl(96, x)))) } } /// @dev Exponentiate `x` to `y` by squaring, denominated in base `b`. /// Reverts if the computation overflows. function rpow(uint256 x, uint256 y, uint256 b) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mul(b, iszero(y)) // `0 ** 0 = 1`. Otherwise, `0 ** n = 0`. if x { z := xor(b, mul(xor(b, x), and(y, 1))) // `z = isEven(y) ? scale : x` let half := shr(1, b) // Divide `b` by 2. // Divide `y` by 2 every iteration. for { y := shr(1, y) } y { y := shr(1, y) } { let xx := mul(x, x) // Store x squared. let xxRound := add(xx, half) // Round to the nearest number. // Revert if `xx + half` overflowed, or if `x ** 2` overflows. if or(lt(xxRound, xx), shr(128, x)) { mstore(0x00, 0x49f7642b) // `RPowOverflow()`. revert(0x1c, 0x04) } x := div(xxRound, b) // Set `x` to scaled `xxRound`. // If `y` is odd: if and(y, 1) { let zx := mul(z, x) // Compute `z * x`. let zxRound := add(zx, half) // Round to the nearest number. // If `z * x` overflowed or `zx + half` overflowed: if or(xor(div(zx, x), z), lt(zxRound, zx)) { // Revert if `x` is non-zero. if x { mstore(0x00, 0x49f7642b) // `RPowOverflow()`. revert(0x1c, 0x04) } } z := div(zxRound, b) // Return properly scaled `zxRound`. } } } } } /// @dev Returns the square root of `x`, rounded down. function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // Let `y = x / 2**r`. We check `y >= 2**(k + 8)` // but shift right by `k` bits to ensure that if `x >= 256`, then `y >= 256`. let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffffff, shr(r, x)))) z := shl(shr(1, r), z) // Goal was to get `z*z*y` within a small factor of `x`. More iterations could // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`. // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small. // That's not possible if `x < 256` but we can just verify those cases exhaustively. // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`. // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`. // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps. // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)` // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`, // with largest error when `s = 1` and when `s = 256` or `1/256`. // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`. // Then we can estimate `sqrt(y)` using // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`. // There is no overflow risk here since `y < 2**136` after the first branch above. z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If `x+1` is a perfect square, the Babylonian method cycles between // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division z := sub(z, lt(div(x, z), z)) } } /// @dev Returns the cube root of `x`, rounded down. /// Credit to bout3fiddy and pcaversaccio under AGPLv3 license: /// https://github.com/pcaversaccio/snekmate/blob/main/src/snekmate/utils/math.vy /// Formally verified by xuwinnie: /// https://github.com/vectorized/solady/blob/main/audits/xuwinnie-solady-cbrt-proof.pdf function cbrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // Makeshift lookup table to nudge the approximate log2 result. z := div(shl(div(r, 3), shl(lt(0xf, shr(r, x)), 0xf)), xor(7, mod(r, 3))) // Newton-Raphson's. z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) z := div(add(add(div(x, mul(z, z)), z), z), 3) // Round down. z := sub(z, lt(div(x, mul(z, z)), z)) } } /// @dev Returns the square root of `x`, denominated in `WAD`, rounded down. function sqrtWad(uint256 x) internal pure returns (uint256 z) { unchecked { if (x <= type(uint256).max / 10 ** 18) return sqrt(x * 10 ** 18); z = (1 + sqrt(x)) * 10 ** 9; z = (fullMulDivUnchecked(x, 10 ** 18, z) + z) >> 1; } /// @solidity memory-safe-assembly assembly { z := sub(z, gt(999999999999999999, sub(mulmod(z, z, x), 1))) // Round down. } } /// @dev Returns the cube root of `x`, denominated in `WAD`, rounded down. /// Formally verified by xuwinnie: /// https://github.com/vectorized/solady/blob/main/audits/xuwinnie-solady-cbrt-proof.pdf function cbrtWad(uint256 x) internal pure returns (uint256 z) { unchecked { if (x <= type(uint256).max / 10 ** 36) return cbrt(x * 10 ** 36); z = (1 + cbrt(x)) * 10 ** 12; z = (fullMulDivUnchecked(x, 10 ** 36, z * z) + z + z) / 3; } /// @solidity memory-safe-assembly assembly { let p := x for {} 1 {} { if iszero(shr(229, p)) { if iszero(shr(199, p)) { p := mul(p, 100000000000000000) // 10 ** 17. break } p := mul(p, 100000000) // 10 ** 8. break } if iszero(shr(249, p)) { p := mul(p, 100) } break } let t := mulmod(mul(z, z), z, p) z := sub(z, gt(lt(t, shr(1, p)), iszero(t))) // Round down. } } /// @dev Returns the factorial of `x`. function factorial(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := 1 if iszero(lt(x, 58)) { mstore(0x00, 0xaba0f2a2) // `FactorialOverflow()`. revert(0x1c, 0x04) } for {} x { x := sub(x, 1) } { z := mul(z, x) } } } /// @dev Returns the log2 of `x`. /// Equivalent to computing the index of the most significant bit (MSB) of `x`. /// Returns 0 if `x` is zero. function log2(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(r, shl(3, lt(0xff, shr(r, x)))) // forgefmt: disable-next-item r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)), 0x0706060506020504060203020504030106050205030304010505030400000000)) } } /// @dev Returns the log2 of `x`, rounded up. /// Returns 0 if `x` is zero. function log2Up(uint256 x) internal pure returns (uint256 r) { r = log2(x); /// @solidity memory-safe-assembly assembly { r := add(r, lt(shl(r, 1), x)) } } /// @dev Returns the log10 of `x`. /// Returns 0 if `x` is zero. function log10(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { if iszero(lt(x, 100000000000000000000000000000000000000)) { x := div(x, 100000000000000000000000000000000000000) r := 38 } if iszero(lt(x, 100000000000000000000)) { x := div(x, 100000000000000000000) r := add(r, 20) } if iszero(lt(x, 10000000000)) { x := div(x, 10000000000) r := add(r, 10) } if iszero(lt(x, 100000)) { x := div(x, 100000) r := add(r, 5) } r := add(r, add(gt(x, 9), add(gt(x, 99), add(gt(x, 999), gt(x, 9999))))) } } /// @dev Returns the log10 of `x`, rounded up. /// Returns 0 if `x` is zero. function log10Up(uint256 x) internal pure returns (uint256 r) { r = log10(x); /// @solidity memory-safe-assembly assembly { r := add(r, lt(exp(10, r), x)) } } /// @dev Returns the log256 of `x`. /// Returns 0 if `x` is zero. function log256(uint256 x) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffff, shr(r, x)))) r := or(shr(3, r), lt(0xff, shr(r, x))) } } /// @dev Returns the log256 of `x`, rounded up. /// Returns 0 if `x` is zero. function log256Up(uint256 x) internal pure returns (uint256 r) { r = log256(x); /// @solidity memory-safe-assembly assembly { r := add(r, lt(shl(shl(3, r), 1), x)) } } /// @dev Returns the scientific notation format `mantissa * 10 ** exponent` of `x`. /// Useful for compressing prices (e.g. using 25 bit mantissa and 7 bit exponent). function sci(uint256 x) internal pure returns (uint256 mantissa, uint256 exponent) { /// @solidity memory-safe-assembly assembly { mantissa := x if mantissa { if iszero(mod(mantissa, 1000000000000000000000000000000000)) { mantissa := div(mantissa, 1000000000000000000000000000000000) exponent := 33 } if iszero(mod(mantissa, 10000000000000000000)) { mantissa := div(mantissa, 10000000000000000000) exponent := add(exponent, 19) } if iszero(mod(mantissa, 1000000000000)) { mantissa := div(mantissa, 1000000000000) exponent := add(exponent, 12) } if iszero(mod(mantissa, 1000000)) { mantissa := div(mantissa, 1000000) exponent := add(exponent, 6) } if iszero(mod(mantissa, 10000)) { mantissa := div(mantissa, 10000) exponent := add(exponent, 4) } if iszero(mod(mantissa, 100)) { mantissa := div(mantissa, 100) exponent := add(exponent, 2) } if iszero(mod(mantissa, 10)) { mantissa := div(mantissa, 10) exponent := add(exponent, 1) } } } } /// @dev Convenience function for packing `x` into a smaller number using `sci`. /// The `mantissa` will be in bits [7..255] (the upper 249 bits). /// The `exponent` will be in bits [0..6] (the lower 7 bits). /// Use `SafeCastLib` to safely ensure that the `packed` number is small /// enough to fit in the desired unsigned integer type: /// ``` /// uint32 packed = SafeCastLib.toUint32(FixedPointMathLib.packSci(777 ether)); /// ``` function packSci(uint256 x) internal pure returns (uint256 packed) { (x, packed) = sci(x); // Reuse for `mantissa` and `exponent`. /// @solidity memory-safe-assembly assembly { if shr(249, x) { mstore(0x00, 0xce30380c) // `MantissaOverflow()`. revert(0x1c, 0x04) } packed := or(shl(7, x), packed) } } /// @dev Convenience function for unpacking a packed number from `packSci`. function unpackSci(uint256 packed) internal pure returns (uint256 unpacked) { unchecked { unpacked = (packed >> 7) * 10 ** (packed & 0x7f); } } /// @dev Returns the average of `x` and `y`. Rounds towards zero. function avg(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = (x & y) + ((x ^ y) >> 1); } } /// @dev Returns the average of `x` and `y`. Rounds towards negative infinity. function avg(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = (x >> 1) + (y >> 1) + (x & y & 1); } } /// @dev Returns the absolute value of `x`. function abs(int256 x) internal pure returns (uint256 z) { unchecked { z = (uint256(x) + uint256(x >> 255)) ^ uint256(x >> 255); } } /// @dev Returns the absolute distance between `x` and `y`. function dist(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := add(xor(sub(0, gt(x, y)), sub(y, x)), gt(x, y)) } } /// @dev Returns the absolute distance between `x` and `y`. function dist(int256 x, int256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := add(xor(sub(0, sgt(x, y)), sub(y, x)), sgt(x, y)) } } /// @dev Returns the minimum of `x` and `y`. function min(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), lt(y, x))) } } /// @dev Returns the minimum of `x` and `y`. function min(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), slt(y, x))) } } /// @dev Returns the maximum of `x` and `y`. function max(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), gt(y, x))) } } /// @dev Returns the maximum of `x` and `y`. function max(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, y), sgt(y, x))) } } /// @dev Returns `x`, bounded to `minValue` and `maxValue`. function clamp(uint256 x, uint256 minValue, uint256 maxValue) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, minValue), gt(minValue, x))) z := xor(z, mul(xor(z, maxValue), lt(maxValue, z))) } } /// @dev Returns `x`, bounded to `minValue` and `maxValue`. function clamp(int256 x, int256 minValue, int256 maxValue) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := xor(x, mul(xor(x, minValue), sgt(minValue, x))) z := xor(z, mul(xor(z, maxValue), slt(maxValue, z))) } } /// @dev Returns greatest common divisor of `x` and `y`. function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { for { z := x } y {} { let t := y y := mod(z, y) z := t } } } /// @dev Returns `a + (b - a) * (t - begin) / (end - begin)`, /// with `t` clamped between `begin` and `end` (inclusive). /// Agnostic to the order of (`a`, `b`) and (`end`, `begin`). /// If `begins == end`, returns `t <= begin ? a : b`. function lerp(uint256 a, uint256 b, uint256 t, uint256 begin, uint256 end) internal pure returns (uint256) { if (begin > end) (t, begin, end) = (~t, ~begin, ~end); if (t <= begin) return a; if (t >= end) return b; unchecked { if (b >= a) return a + fullMulDiv(b - a, t - begin, end - begin); return a - fullMulDiv(a - b, t - begin, end - begin); } } /// @dev Returns `a + (b - a) * (t - begin) / (end - begin)`. /// with `t` clamped between `begin` and `end` (inclusive). /// Agnostic to the order of (`a`, `b`) and (`end`, `begin`). /// If `begins == end`, returns `t <= begin ? a : b`. function lerp(int256 a, int256 b, int256 t, int256 begin, int256 end) internal pure returns (int256) { if (begin > end) (t, begin, end) = (~t, ~begin, ~end); if (t <= begin) return a; if (t >= end) return b; // forgefmt: disable-next-item unchecked { if (b >= a) return int256(uint256(a) + fullMulDiv(uint256(b - a), uint256(t - begin), uint256(end - begin))); return int256(uint256(a) - fullMulDiv(uint256(a - b), uint256(t - begin), uint256(end - begin))); } } /// @dev Returns if `x` is an even number. Some people may need this. function isEven(uint256 x) internal pure returns (bool) { return x & uint256(1) == uint256(0); } /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ /* RAW NUMBER OPERATIONS */ /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ /// @dev Returns `x + y`, without checking for overflow. function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x + y; } } /// @dev Returns `x + y`, without checking for overflow. function rawAdd(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x + y; } } /// @dev Returns `x - y`, without checking for underflow. function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x - y; } } /// @dev Returns `x - y`, without checking for underflow. function rawSub(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x - y; } } /// @dev Returns `x * y`, without checking for overflow. function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) { unchecked { z = x * y; } } /// @dev Returns `x * y`, without checking for overflow. function rawMul(int256 x, int256 y) internal pure returns (int256 z) { unchecked { z = x * y; } } /// @dev Returns `x / y`, returning 0 if `y` is zero. function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := div(x, y) } } /// @dev Returns `x / y`, returning 0 if `y` is zero. function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := sdiv(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mod(x, y) } } /// @dev Returns `x % y`, returning 0 if `y` is zero. function rawSMod(int256 x, int256 y) internal pure returns (int256 z) { /// @solidity memory-safe-assembly assembly { z := smod(x, y) } } /// @dev Returns `(x + y) % d`, return 0 if `d` if zero. function rawAddMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := addmod(x, y, d) } } /// @dev Returns `(x * y) % d`, return 0 if `d` if zero. function rawMulMod(uint256 x, uint256 y, uint256 d) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { z := mulmod(x, y, d) } } }
// 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; } }
{ "evmVersion": "paris", "optimizer": { "enabled": true, "mode": "3" }, "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyAtMaxFacility","type":"error"},{"inputs":[],"name":"AlreadyPurchasedInitialFactory","type":"error"},{"inputs":[],"name":"CantBuyNewFacilityYet","type":"error"},{"inputs":[],"name":"CantModifyStarterFacility","type":"error"},{"inputs":[],"name":"CantModifyStarterMiner","type":"error"},{"inputs":[],"name":"FacilityInadequatePowerOutput","type":"error"},{"inputs":[],"name":"GreatDepression","type":"error"},{"inputs":[],"name":"IncorrectValue","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidFacilityIndex","type":"error"},{"inputs":[],"name":"InvalidFee","type":"error"},{"inputs":[],"name":"InvalidMinerIndex","type":"error"},{"inputs":[],"name":"InvalidPowerOutput","type":"error"},{"inputs":[],"name":"InvalidReferrer","type":"error"},{"inputs":[],"name":"MinerNotInProduction","type":"error"},{"inputs":[],"name":"MiningHasntStarted","type":"error"},{"inputs":[],"name":"NeedToInitializeFacility","type":"error"},{"inputs":[],"name":"NewFacilityNotInProduction","type":"error"},{"inputs":[],"name":"NoRewardsPending","type":"error"},{"inputs":[],"name":"NonExistentFacility","type":"error"},{"inputs":[],"name":"NonExistentMiner","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PlayerDoesNotOwnMiner","type":"error"},{"inputs":[],"name":"StarterMinerAlreadyAcquired","type":"error"},{"inputs":[],"name":"TooPoor","type":"error"},{"inputs":[],"name":"UpgradeFacilityDisabled","type":"error"},{"inputs":[],"name":"WithdrawFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":true,"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"}],"name":"FacilityBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"FacilityCostChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inProduction","type":"bool"}],"name":"FacilityProductionToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"}],"name":"InitialFacilityPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minerId","type":"uint256"}],"name":"MinerBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"MinerCostChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPowerConsumption","type":"uint256"}],"name":"MinerPowerConsumptionChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inProduction","type":"bool"}],"name":"MinerProductionToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"MinerSecondaryMarketAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secondHandPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"minerId","type":"uint256"}],"name":"MinerSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"startBlock","type":"uint256"}],"name":"MiningStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalPowerOutput","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inProduction","type":"bool"}],"name":"NewFacilityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"minerIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"hashRate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"},{"indexed":false,"internalType":"bool","name":"inProduction","type":"bool"}],"name":"NewMinerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"playerHashrate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"playerPendingRewards","type":"uint256"}],"name":"PlayerHashrateDecreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"playerHashrate","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"playerPendingRewards","type":"uint256"}],"name":"PlayerHashrateIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"player","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"inputs":[],"name":"HALVING_INTERVAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INITIAL_MINETENDO_PER_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REWARDS_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STARTER_FACILITY_INDEX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STARTER_MINER_INDEX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SWAP_ROUTER","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"acquiredStarterMiner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxMiners","type":"uint256"},{"internalType":"uint256","name":"totalPowerOutput","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"addFacility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"addMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"price","type":"uint256"}],"name":"addSecondaryMarketForMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"blocksUntilNextHalving","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnPct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"}],"name":"buyMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"changeFacilityCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"newCost","type":"uint256"}],"name":"changeMinerCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"newPowerConsumption","type":"uint256"}],"name":"changeMinerPowerConsumption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cumulativeMinetendoPerHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableUpgradeFacility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"facilities","outputs":[{"internalType":"uint256","name":"maxMiners","type":"uint256"},{"internalType":"uint256","name":"totalPowerOutput","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facilityCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinetendoPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"getPlayerMinersPaginated","outputs":[{"components":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"internalType":"struct Miner[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"getReferrals","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"getTotalMiners","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialFacilityPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"initializedStarterFacility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastFacilityUpgradeTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRewardBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"minerSecondHandMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"miners","outputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minetendo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minetoshi","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"miningHasStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"ownerToFacility","outputs":[{"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"internalType":"uint256","name":"maxMiners","type":"uint256"},{"internalType":"uint256","name":"currMiners","type":"uint256"},{"internalType":"uint256","name":"totalPowerOutput","type":"uint256"},{"internalType":"uint256","name":"currPowerOutput","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerHashrate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"playerMinersId","outputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"uint256","name":"powerConsumption","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerMinersOwned","outputs":[{"internalType":"uint256","name":"_spacer","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerMinetendoDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"playerMinetendoPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"playerPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"purchaseInitialFacility","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referralBonusPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referralFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referrals","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"referredUsers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"secondTierReferralBonusPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"secondTierReferralFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"secondTierReferrals","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerId","type":"uint256"}],"name":"sellMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"burn","type":"uint256"}],"name":"setBurnPct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_cooldown","type":"uint256"}],"name":"setCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"enable","type":"bool"}],"name":"setEnableUpgradeFacility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_initialPrice","type":"uint256"}],"name":"setInitialFacilityPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minetendo","type":"address"}],"name":"setMinetendo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minetoshi","type":"address"}],"name":"setMinetoshi","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee","type":"uint256"}],"name":"setSecondTierReferralFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"timeUntilNextFacilityUpgrade","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"facilityIndex","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"toggleFacilityProduction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"toggleMinerProduction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalHashrate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniqueMinerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgradeFacility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"withdrawMinetendo","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
9c4d535b0000000000000000000000000000000000000000000000000000000000000000010007050f51b4ba674fb0b4ae3a42be6b3dfccc071d8413d0e05b15ae270f8600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x0001000000000002001100000000000200000000000103550000000100200190000000420000c13d000000600210027000000624022001970000008004000039000000400040043f000000040020008c0000111c0000413d000000000301043b000000e003300270000006330030009c000000770000a13d000006340030009c0000008f0000a13d000006350030009c000000fd0000a13d000006360030009c000001430000213d0000063d0030009c000003c20000a13d0000063e0030009c000007b40000613d0000063f0030009c000006a60000613d000006400030009c0000111c0000c13d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000402100370000000000202043b000006260020009c0000111c0000213d0000002401100370000000000101043b000d00000001001d000000000020043f0000001e01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a0000000d0020006b0000111c0000813d0000000d02000029188c15e20000040f0000000302200210000000000101041a000000000121022f0000062601100197000000ff0020008c00000000010020190000033b0000013d000000c001000039000000400010043f0000000001000416000000000001004b0000111c0000c13d0000000006000411000000000006004b0000004f0000c13d0000063101000041000000c00010043f000000c40000043f00000632010000410000188e00010430000000000100041a0000062502100197000000000262019f000000000020041b00000000020004140000062605100197000006240020009c0000062402008041000000c00120021000000627011001c70000800d0200003900000003030000390000062804000041188c18820000040f00000001002001900000111c0000613d00000629010000410000000c02000039000000000012041b0000062a010000410000000d02000039000000000012041b0000062b010000410000000e02000039000000000012041b0000062c020000410000000f03000039000000000023041b0000002102000039000000000012041b0000000602000039000000000102041a000000010110003a000000e10000c13d000006f501000041000000000010043f0000001101000039000000040010043f000006a8010000410000188e00010430000006680030009c000000a70000213d000006820030009c000001110000213d0000068f0030009c000002210000a13d000006900030009c000004250000a13d000006910030009c000007c40000613d000006920030009c000006de0000613d000006930030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001a01000039000007510000013d0000064f0030009c000000ec0000213d0000065c0030009c000001ce0000a13d0000065d0030009c000003930000a13d0000065e0030009c000006330000613d0000065f0030009c000005c80000613d000006600030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001d01000039000003ad0000013d000006690030009c000001270000213d000006760030009c000002440000a13d000006770030009c000004350000a13d000006780030009c000007d30000613d000006790030009c000006ea0000613d0000067a0030009c0000111c0000c13d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000c00000004001d000d00000003001d000000000030043f0000001a01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000c02000029000000000021041b000000400100043d0000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006e304000041000004f70000013d000000000012041b000000800010043f000000400400043d0000062d0040009c000001500000413d000006f501000041000000000010043f0000004101000039000000040010043f000006a8010000410000188e00010430000006500030009c000001e00000a13d000006510030009c0000039e0000a13d000006520030009c0000063b0000613d000006530030009c000005d80000613d000006540030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d000006ca01000041000000800010043f0000069b010000410000188d0001042e000006430030009c000001ed0000a13d000006440030009c000003b20000a13d000006450030009c000007170000613d000006460030009c000005f70000613d000006470030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001601000039000003cf0000013d000006830030009c0000024f0000a13d000006840030009c000004580000a13d000006850030009c000007e30000613d000006860030009c000006ef0000613d000006870030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001101000039000007510000013d0000066a0030009c000002600000a13d0000066b0030009c000004750000a13d0000066c0030009c000008090000613d0000066d0030009c000007120000613d0000066e0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000200041a00000626032001970000000002000411000000000023004b000007af0000c13d000006af0010009c000004c10000213d0000000e02000039000000000012041b00000000010000190000188d0001042e000006370030009c000003e90000a13d000006380030009c000007bf0000613d000006390030009c000006b10000613d0000063a0030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000e01000039000007550000013d000000c002400039000000400020043f00000060034000390000000202000039000d00000003001d000000000023043500000040034000390000000a02000039000900000003001d00000000002304350000008003400039000000010200008a000a00000003001d00000000002304350000002003400039000800000003001d00000000002304350000000000140435000c00000004001d000000a001400039000b00000001001d0000000000010435000000800100043d000000000010043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000c020000290000000002020433000000000101043b000000000021041b000000080200002900000000020204330000000103100039000000000023041b000000090200002900000000020204330000000203100039000000000023041b0000000d0200002900000000020204330000000303100039000000000023041b0000000a0200002900000000020204330000000403100039000000000023041b0000000501100039000000000201041a000006fc022001970000000b030000290000000003030433000000000003004b000000010220c1bf000000000021041b000000400300043d0000062f0030009c000000e60000213d0000008001300039000000400010043f0000004005300039000000010100008a00000000001504350000002007300039000001f4010000390000000000170435000003e8010000390000000000130435000000600630003900000000000604350000000702000039000000000102041a000000010110003a000000710000613d000000000012041b000000000010043f0000001401000039000000200010043f00000040020000390000000001000019000a00000003001d000c00000005001d000d00000006001d000b00000007001d188c184f0000040f0000000a020000290000000002020433000000000021041b0000000b0200002900000000020204330000000103100039000000000023041b0000000c0200002900000000020204330000000203100039000000000023041b0000000301100039000000000201041a000006fc022001970000000d030000290000000003030433000000000003004b000000010220c1bf000000000021041b0000000701000039000000000101041a000000a00010043f000000800200043d0000014000000443000001600020044300000020020000390000018000200443000001a00010044300000100002004430000000201000039000001200010044300000630010000410000188d0001042e000006630030009c000002b30000213d000006660030009c0000048b0000613d000006670030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000002001000039000007510000013d000006570030009c000002fd0000213d0000065a0030009c000004900000613d0000065b0030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d000006d001000041000000800010043f0000069b010000410000188d0001042e0000064a0030009c000003060000213d0000064d0030009c000004a70000613d0000064e0030009c0000111c0000c13d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000402100370000000000202043b000d00000002001d0000002401100370000000000201043b000000000002004b0000000001000039000000010100c039000c00000002001d000000000012004b0000111c0000c13d000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000006a20100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d02000029000000000012004b0000021e0000413d0000000601000039000000000101041a000000000012004b00000c060000a13d000000400100043d000006c90200004100000bb20000013d000006960030009c000003110000213d000006990030009c000004c50000613d0000069a0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001401000039000000200010043f00000040020000390000000001000019188c184f0000040f0000000302100039000000000202041a0000000203100039000000000303041a0000000104100039000000000404041a000000000101041a000000800010043f000000a00040043f000000c00030043f000000ff002001900000000001000039000000010100c039000000e00010043f000006f9010000410000188d0001042e0000067d0030009c000003270000213d000006800030009c000004f90000613d000006810030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000101000039000004940000013d0000068a0030009c000003420000213d0000068d0030009c0000054a0000613d0000068e0030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000301000039000000000101041a000000000001004b000008260000c13d000006f401000041000000800010043f000006b8010000410000188e00010430000006710030009c000003790000213d000006740030009c000005570000613d000006750030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400400043d000006be0040009c000000e60000213d000000000101043b000000c002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000a00000003001d00000000002304350000000202100039000000000202041a0000004003400039000900000003001d00000000002304350000000302100039000000000202041a0000006003400039000b00000003001d00000000002304350000000402100039000000000202041a0000008003400039000c00000003001d0000000000230435000800000004001d000000a0024000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000d00000002001d00000000001204350000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400300043d000000000101043b000700000001001d0000000d010000290000000001010433000000000001004b00000b460000c13d000006e2010000410000041f0000013d000006640030009c000004960000613d000006650030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d0000000d01000029000000000010043f0000001b01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000c02000039000000000202041a000000000101043b000000000101041a000c00000002001d000b00000001001d000000000012001a000000710000413d000006a40100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d0000000b030000290000000c02300029000000000101043b000b00000001001d000000000012004b00000000010000190000033b0000413d0000000d01000029000000000010043f0000001b01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a0000000c0010002a000000710000413d0000000c011000290000000b0110006c0000033b0000813d000000710000013d000006580030009c000004a20000613d000006590030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000f01000039000007550000013d0000064b0030009c000004b30000613d0000064c0030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d000006c701000041000000800010043f0000069b010000410000188d0001042e000006970030009c0000055e0000613d000006980030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000201043b000000000002004b0000000001000039000000010100c039000d00000002001d000000000012004b0000111c0000c13d188c161d0000040f0000000a01000039000000000201041a000006fc02200197000005ae0000013d0000067e0030009c0000059b0000613d0000067f0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001501000039000000200010043f00000040020000390000000001000019188c184f0000040f188c182a0000040f000000400200043d0000000000120435000006240020009c00000624020080410000004001200210000006a3011001c70000188d0001042e0000068b0030009c000005a00000613d0000068c0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000800000001001d000006260010009c0000111c0000213d0000000401000039000000000101041a000000ff00100190000007cb0000613d0000000901000039000000000101041a000a00000001001d000000000001004b000009160000c13d0000000801000029000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000201043b0000000d01000039000000000101041a000006af0010009c000000710000213d0000000e03000039000000000303041a000006af01100099000000000131004b000000710000413d000000000202041a000003750000613d000006fd03100129000000000023004b000009120000413d00000000022100a9000000400100043d000006af0220012a000007cd0000013d000006720030009c000005b20000613d000006730030009c0000111c0000c13d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d0000000701000039000000000101041a000000000013004b000008b90000a13d000006d701000041000000800010043f000006b8010000410000188e00010430000006610030009c000005dd0000613d000006620030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d000006af01000041000000800010043f0000069b010000410000188d0001042e000006550030009c000005e20000613d000006560030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001c01000039000000200010043f00000040020000390000000001000019188c184f0000040f000004940000013d000006480030009c000006a10000613d000006490030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001801000039000005d30000013d000006410030009c000006c60000613d000006420030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000010043f0000001301000039000000200010043f00000040020000390000000001000019188c184f0000040f0000000502100039000000000202041a0000000403100039000000000303041a0000000304100039000000000404041a0000000205100039000000000505041a0000000106100039000000000606041a000000000101041a000000800010043f000000a00060043f000000c00050043f000000e00040043f000001000030043f000000ff002001900000000001000039000000010100c039000001200010043f000006b9010000410000188d0001042e0000063b0030009c000006d30000613d0000063c0030009c0000111c0000c13d000000840020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000006402100370000000000302043b000000000003004b0000000002000039000000010200c039000d00000003001d000000000023004b0000111c0000c13d0000000402100370000000000502043b0000002402100370000000000302043b0000004401100370000000000401043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000a00000005001d000b00000004001d000c00000003001d0000000701000039000000000101041a000900000001001d000000000010043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400300043d000000000101043b0000000101100039000000000101041a0000000c02000029000000000021004b00000bb80000a13d000006a0010000410000000000130435000006240030009c00000624030080410000004001300210000006a1011001c70000188e00010430000006940030009c000007460000613d000006950030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001501000039000007510000013d0000067b0030009c000007590000613d0000067c0030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001701000039000000200010043f00000040020000390000000001000019188c184f0000040f0000000402100039000000000202041a0000000303100039000000000303041a0000000204100039000000000404041a0000000105100039000000000505041a000000000101041a000000800010043f000000a00050043f000000c00040043f000000e00030043f000001000020043f000006e4010000410000188d0001042e000006880030009c000007660000613d000006890030009c0000111c0000c13d0000000001000416000000000001004b0000111c0000c13d0000000001000411188c162d0000040f0000000001000411000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000000001004b000008f30000c13d000000400100043d000006f10200004100000bb20000013d0000066f0030009c000007aa0000613d000006700030009c0000111c0000c13d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000200041a00000626032001970000000002000411000000000023004b000007af0000c13d000006d30010009c000004c10000813d0000000d02000039000000000012041b00000000010000190000188d0001042e0000000001000416000000000001004b0000111c0000c13d0000000c01000039000007550000013d0000000001000416000000000001004b0000111c0000c13d0000000201000039000000000101041a000006370000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001b01000039000007510000013d0000000001000416000000000001004b0000111c0000c13d0000000401000039000006aa0000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001201000039000007510000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000000000200041a00000626032001970000000002000411000000000023004b000007af0000c13d000006af0010009c0000086d0000a13d000006d401000041000000800010043f000006b8010000410000188e00010430000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d0000000601000039000000000101041a000000000013004b000005c40000213d000c00000004001d000d00000003001d000000000030043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b00000003011000390000000c02000029000000000021041b000000400100043d0000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006fa040000410000000d050000290000081c0000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001e01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000301041a000000400200043d000c00000002001d000b00000003001d0000000002320436000d00000002001d000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006b1011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000b05000029000000000005004b0000000d0600002900000000020600190000052e0000613d000000000101043b00000000030000190000000002060019000000000401041a0000062604400197000000000242043600000001011000390000000103300039000000000053004b000005270000413d0000000c0300002900000000013200490000001f01100039000006fe021001970000000001320019000000000021004b00000000020000390000000102004039000006aa0010009c000000e60000213d0000000100200190000000e60000c13d000000400010043f00000020020000390000000002210436000000000303043300000000003204350000004002100039000000000003004b00000b3d0000613d00000000040000190000000065060434000006260550019700000000025204360000000104400039000000000034004b000005430000413d00000b3d0000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d188c161d0000040f0000000101000039000005ac0000013d0000000001000416000000000001004b0000111c0000c13d000006cf01000041000000800010043f0000069b010000410000188d0001042e000000640020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000402100370000000000202043b000006260020009c0000111c0000213d0000002403100370000000000303043b000900000003001d0000004401100370000000000101043b000d00000001001d000000000020043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000201043b000006ba01000041000000040010043f000c00000002001d000000000020043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000006fd02100167000000000202041a000000000002004b00000a480000c13d000000000201041a000000000002004b0000000002000039000000010200c03900000a490000613d0000000103100039000000000303041a000000000003004b00000a490000613d0000000201100039000000000101041a000000000001004b0000000302000039000000020200603900000a490000013d0000000001000416000000000001004b0000111c0000c13d0000000301000039000007550000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d188c161d0000040f0000000201000039000000000201041a00000625022001970000000d022001af000000000021041b00000000010000190000188d0001042e000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d0000000601000039000000000101041a000000000013004b000008710000a13d000006fb01000041000000800010043f000006b8010000410000188e00010430000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001901000039000000200010043f00000040020000390000000001000019188c184f0000040f000006aa0000013d0000000001000416000000000001004b0000111c0000c13d0000000801000039000007550000013d0000000001000416000000000001004b0000111c0000c13d0000000d01000039000007550000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d0000000901000039000000000201041a000000000002004b0000000001000019000008880000c13d0000000000140435000006240040009c00000624040080410000004001400210000006a3011001c70000188d0001042e000000240020008c0000111c0000413d0000000001000416000000000001004b0000111c0000c13d0000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000004020000390000000002200367000000000202043b000d00000002001d000000000101043b000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000201043b00000004010000390000000001100367000000000101043b000006bc0010009c000014190000613d000000000001004b0000000d04000029000006bc04006041000006fd03200167000000000303041a000000000003004b000009b40000c13d000000000302041a000000000043004b00000d5f0000613d0000000103200039000000000303041a000000000043004b00000d5f0000613d0000000202200039000000000202041a000000000042004b000009c30000c13d00000d5f0000013d0000000001000416000000000001004b0000111c0000c13d000000000100041a0000062601100197000000800010043f0000069b010000410000188d0001042e000000840020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000006402100370000000000302043b000000000003004b0000000002000039000000010200c039000d00000003001d000000000023004b0000111c0000c13d0000000402100370000000000302043b0000002402100370000000000402043b0000004401100370000000000501043b000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d0000000602000039000000000102041a000000010110003a000000710000613d000000000012041b0000014002000039000000400020043f000000800010043f000000a00000043f000c00000003001d000000c00030043f000b00000004001d000000e00040043f000a00000005001d000001000050043f0000000d02000029000001200020043f000000000010043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000800200043d000000000021041b0000000102100039000000a00300043d000000000032041b0000000202100039000000c00300043d000000000032041b0000000302100039000000e00300043d000000000032041b0000000402100039000001000300043d000000000032041b0000000501100039000000000301041a000006fc02300197000001200300043d000000000003004b000000010220c1bf000000000021041b0000000601000039000000000501041a000000400100043d00000060021000390000000d03000029000000000032043500000040021000390000000a03000029000000000032043500000020021000390000000b0300002900000000003204350000000c020000290000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006cb011001c70000800d020000390000000203000039000006cc04000041000004f80000013d0000000001000416000000000001004b0000111c0000c13d0000000b01000039000007550000013d0000000001000416000000000001004b0000111c0000c13d0000000a01000039000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f0000069b010000410000188d0001042e000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000601043b000006260060009c0000111c0000213d000000000100041a00000626021001970000000005000411000000000052004b000008210000c13d000000000006004b0000095e0000c13d0000063101000041000000800010043f000000840000043f0000069d010000410000188e00010430000000240020008c0000111c0000413d0000000001000416000000000001004b0000111c0000c13d188c161d0000040f00000004010000390000000001100367000000000101043b0000002102000039000000000012041b00000000010000190000188d0001042e0000000001000416000000000001004b0000111c0000c13d0000000001000412000f00000001001d000e00000000003d0000800501000039000000440300003900000000040004150000000f0440008a000007dd0000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001001000039000007510000013d0000000001000416000000000001004b0000111c0000c13d0000000901000039000007550000013d000000240020008c0000111c0000413d0000000401100370000000000101043b000d00000001001d000006260010009c0000111c0000213d0000002101000039000000000101041a0000000002000416000000000012004b000008d10000c13d0000000001000411000000000010043f0000001801000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000ff0010019000000bb00000c13d00000000010004110000000d0010006b00000c340000c13d000000400100043d000006ea0200004100000bb20000013d0000000001000416000000000001004b0000111c0000c13d0000000601000039000007550000013d000000440020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000402100370000000000202043b000d00000002001d0000002401100370000000000201043b000000000002004b0000000001000039000000010100c039000c00000002001d000000000012004b0000111c0000c13d000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000006a201000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d02000029000000000012004b000007430000413d0000000701000039000000000101041a000000000012004b00000d3a0000a13d000000400100043d000006c60200004100000bb20000013d000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d0000000401100370000000000101043b000006260010009c0000111c0000213d000000000010043f0000001f01000039000000200010043f00000040020000390000000001000019188c184f0000040f000000000101041a000000800010043f0000069b010000410000188d0001042e000000240020008c0000111c0000413d0000000001000416000000000001004b0000111c0000c13d188c161d0000040f00000004010000390000000001100367000000000101043b0000000c02000039000000000012041b00000000010000190000188d0001042e000000240020008c0000111c0000413d0000000002000416000000000002004b0000111c0000c13d000000000200041a00000626032001970000000002000411000000000023004b000007af0000c13d0000000102000039000000000202041a0000000203000039000000000303041a000006c104000041000000800040043f0000000401100370000000000101043b0000062603300197000000840030043f000000a40010043f00000000010004140000062602200197000006240010009c0000062401008041000000c001100210000006f2011001c7188c18820000040f00000060031002700000062403300197000000200030008c000000200a000039000000000a0340190000001f05a0018f0000002006a0019000000080046001bf000007910000613d0000008007000039000000000801034f000000008908043c0000000007970436000000000047004b0000078d0000c13d000000000005004b0000079e0000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f00000000005404350000000100200190000008d50000613d000000800100003900000000020a0019000d0000000a001d188c15fd0000040f0000000d0100002900000080021001bf0000008001000039188c160f0000040f00000000010000190000188d0001042e0000000001000416000000000001004b0000111c0000c13d0000000701000039000007550000013d0000069c01000041000000800010043f000000840020043f0000069d010000410000188e000104300000000001000416000000000001004b0000111c0000c13d0000000a01000039000000000101041a000000ff00100190000008410000c13d000006b701000041000000800010043f000006b8010000410000188e000104300000000001000416000000000001004b0000111c0000c13d0000002101000039000007550000013d0000000001000416000000000001004b0000111c0000c13d0000000401000039000000000101041a000000ff00100190000008550000c13d000000800100003900000000020000190000000000210435000006240010009c00000624010080410000004001100210000006a3011001c70000188d0001042e0000000001000416000000000001004b0000111c0000c13d0000000001000412001100000001001d001000200000003d000080050100003900000044030000390000000004000415000000110440008a0000000504400210000006a202000041188c18640000040f000000800010043f0000069b010000410000188d0001042e0000000001000416000000000001004b0000111c0000c13d000000000100041a00000626021001970000000001000411000000000012004b000008040000c13d000006eb010000410000000000100443000000000100041000000004001004430000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800a02000039188c18870000040f0000000100200190000015310000613d0000000202000039000000000202041a0000062604200197000000000301043b0000000001000414000006240010009c0000062401008041000000c001100210000000000003004b000009820000c13d0000000002040019000009850000013d0000069c02000041000000800020043f000000840010043f0000069d010000410000188e000104300000000001000416000000000001004b0000111c0000c13d000000000100041a00000626021001970000000005000411000000000052004b000008210000c13d0000062501100197000000000010041b0000000001000414000006240010009c0000062401008041000000c00110021000000627011001c70000800d02000039000000030300003900000628040000410000000006000019188c18820000040f00000001002001900000111c0000613d00000000010000190000188d0001042e0000069c01000041000000800010043f000000840050043f0000069d010000410000188e00010430000d00000001001d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b000006cf0210012a0000000103200039000006cf023000d100000000033200d9000006cf0030009c000000710000c13d0000000d03000029000006cf3030012a000000000032001a000000710000413d0000000002320019000000000112004b0000033b0000813d000000710000013d0000000001000411000000000010043f0000001801000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000ff001001900000096a0000c13d000000400100043d000006b60200004100000bb20000013d0000000301000039000000000101041a000d00000001001d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d0210006c000000710000413d000006ce0020009c000000710000213d000000400100043d0000062402200197000006cf0220012a000006d00220027f000007cd0000013d0000000f02000039000000000012041b00000000010000190000188d0001042e000c00000004001d000d00000003001d000006a20100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d02000029000000000012004b00000aef0000c13d000000400100043d000006d90200004100000bb20000013d000b00000002001d0000000301000039000000000101041a000c00000001001d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000c0110006c000000710000413d000006ce0010009c000000710000213d000c00000001001d0000000d01000029000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000c020000290000062402200197000006cf0220012a000006d00220027f000000000101043b000000000301041a00000000012300a9000000000003004b000008b60000613d00000000033100d9000000000023004b00000e8b0000c13d0000000b011000fa000000400400043d000005f10000013d000c00000004001d000d00000003001d000006a201000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000d02000029000000000012004b00000b910000c13d000000400100043d000006d60200004100000bb20000013d000006e501000041000000800010043f000006b8010000410000188e000104300000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008dc0000c13d000000000005004b000008ed0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000006240020009c00000624020080410000004002200210000000000112019f0000188e00010430000d00000001001d0000000001000411000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000001041b0000000d01000039000000000101041a000000000001004b0000000d040000290000090b0000613d000006fd02100129000000000042004b000009120000413d0000000e02000039000000000202041a000000000002004b000009c60000613d000006fd03200129000000000043004b000009c60000813d000006f301000041000000000010043f000006d2010000410000188e000104300000000301000039000000000101041a0000000802000039000000000302041a000000000213004b000000710000413d000006ce0020009c000000710000213d000c00000003001d000006cf1010012a000900000001001d0000000b01000039000000000101041a000d00000001001d0000062401200197000006cf0110012a000b06d000100287000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000c05000029000000000015004b0000000d07000029000000090400002900000e3c0000813d000006cf0250012a0000000103200039000006cf023000d100000000033200d9000006cf0030009c0000000b08000029000000710000c13d000000000042001a000000710000413d0000000003420019000000000013004b00000000020100190000000002034019000000000452004b000000710000413d000000000008004b000009540000613d00000000058400a900000000068500d9000000000046004b000000710000c13d000000000005004b000009540000613d000006af045000d100000000055400d9000006af0050009c000009550000613d000000710000013d00000000040000190000000a044000fa000000000074001a000000710000413d000d00000074001d000000000013004b000000010880a270000b00000008001d000c00000002001d000009270000013d0000062501100197000000000161019f000000000010041b0000000001000414000006240010009c0000062401008041000000c00110021000000627011001c70000800d02000039000000030300003900000628040000410000081c0000013d0000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000c00000001001d000000000201041a0000000701000039000000000101041a000d00000002001d000000000012004b00000d150000c13d000000400100043d000006b50200004100000bb20000013d00000627011001c700008009020000390000000005000019188c18820000040f000000600310027000000624033001980000098e0000c13d00000001002001900000081f0000c13d000000400100043d000006ee0200004100000bb20000013d0000001f04300039000006ec044001970000003f04400039000006ed04400197000000400500043d0000000004450019000000000054004b00000000060000390000000106004039000006aa0040009c000000e60000213d0000000100600190000000e60000c13d000000400040043f0000001f0430018f0000000006350436000006a9053001980000000003560019000009a60000613d000000000701034f000000007807043c0000000006860436000000000036004b000009a20000c13d000000000004004b000009890000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000130435000009890000013d000000200020043f000000000040043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000000001004b00000d5c0000c13d000000400100043d000006bd0200004100000bb20000013d00000000014100a9000c06af001001320000000c0140006c000000710000413d00000000024200a9000a06af002001320000000a0110006c000b00000001001d000000710000413d0000000101000039000000000101041a000006ad0200004100000000002004430000062601100197000900000001001d00000004001004430000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000400300043d00000024013000390000000b020000290000000000210435000006ef0100004100000000001304350000000001000411000006260110019700000004023000390000000000120435000006240030009c000b00000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000902000029188c18820000040f000000010020019000000ea50000613d0000000b01000029000006aa0010009c000000e60000213d0000000b01000029000000400010043f0000000001000411000000000010043f0000001c01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a0000000102000039000000000202041a000006ad0300004100000000003004430000062602200197000b00000002001d0000000400200443000906260010019c000011100000c13d0000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000400300043d00000024013000390000000c020000290000000000210435000006ef0100004100000000001304350000000001000410000006260110019700000004023000390000000000120435000006240030009c000900000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000b02000029188c18820000040f0000000100200190000011a80000613d0000000901000029000006aa0010009c000000e60000213d0000000901000029000000400010043f0000000001000410000000000010043f0000001f01000039000000200010043f0000000001000414000011460000013d0000000102200270000000090520006c00000b0e0000a13d0000000d0050006c0000000d05008029000006aa0050009c000000e60000213d00000005015002100000003f02100039000006f702200197000000400400043d0000000002240019000000000042004b00000000030000390000000103004039000006aa0020009c000000e60000213d0000000100300190000000e60000c13d000000400020043f000800000004001d0000000002540436000700000002001d000600000005001d000000000005004b00000b150000613d00000000020000190000000705000029000000400300043d000006be0030009c000000e60000213d000000c004300039000000400040043f000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b00000a640000413d000d00000000001d000006ba01000041000000040010043f0000000c01000029000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000d03000029000b00090030002d000000000101043b0000000b01100029000000000101041a000a00000001001d000006ba01000041000000040010043f0000000c01000029000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000201043b000006fd01200167000000000101041a000000000001004b00000aa10000613d000000010110027000000aaf0000013d000000000102041a000000000001004b0000000001000039000000010100c03900000aaf0000613d0000000103200039000000000303041a000000000003004b00000aaf0000613d0000000201200039000000000101041a000000000001004b000000030100003900000002010060390000000b0010006b0000110d0000813d0000000a01000029000006bc0010009c0000000001006019000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000006be0020009c000000080500002900000006060000290000000707000029000000e60000213d000000000101043b000000c003200039000000400030043f000000000301041a00000000033204360000000104100039000000000404041a00000000004304350000000203100039000000000303041a000000400420003900000000003404350000000303100039000000000303041a000000600420003900000000003404350000000403100039000000000303041a00000080042000390000000000340435000000a0032000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000000000013043500000000010504330000000d03000029000000000031004b000010b30000a13d0000000501300210000000000171001900000000002104350000000001050433000000000031004b000010b30000a13d000d00010030003d0000000d0060006b00000a7a0000413d00000b150000013d000000000020043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b00000004011000390000000c02000029000000000021041b000000400100043d0000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006d804000041000004f70000013d000000400200043d000006f60020009c000000e60000213d0000002001200039000000400010043f000800000002001d0000000000020435000000400100043d000000200200003900000000022104360000000803000029000000000303043300000000003204350000004002100039000000000003004b00000b3d0000613d00000000040000190000000808000029000000200880003900000000050804330000000076050434000000000662043600000000070704330000000000760435000000400650003900000000060604330000004007200039000000000067043500000060065000390000000006060433000000600720003900000000006704350000008006500039000000000606043300000080072000390000000000670435000000a0055000390000000005050433000000000005004b0000000005000039000000010500c039000000a0062000390000000000560435000000c0022000390000000104400039000000000034004b00000b200000413d0000000002120049000006240020009c00000624020080410000006002200210000006240010009c00000624010080410000004001100210000000000112019f0000188d0001042e0000000101000039000000000201041a000006a70100004100000000001304350000000401300039000000000403001900000000030004110000000000310435000600000004001d000006240040009c0000062401000041000000000104401900000040011002100000000003000414000006240030009c0000062403008041000000c003300210000000000113019f000006a8011001c70000062602200197000500000002001d188c18870000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000060b000029000000060570002900000b6c0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000b680000c13d000000000006004b00000b790000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000c280000613d0000001f01400039000000600110018f0000000002b10019000000000012004b00000000010000390000000101004039000400000002001d000006aa0020009c000000e60000213d0000000100100190000000e60000c13d0000000401000029000000400010043f000000200030008c0000111c0000413d0000000c01000029000000000101043300000000020b0433000000000012004b00000e8f0000813d000006b30100004100000e9e0000013d000000000020043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b00000002011000390000000c02000029000000000021041b000000400100043d0000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006d504000041000004f70000013d000000400100043d000006e6020000410000000000210435000006240010009c00000624010080410000004001100210000006a1011001c70000188e000104300000062f0030009c000000e60000213d0000008001300039000000400010043f00000060043000390000000d01000029000700000004001d000000000014043500000040043000390000000b01000029000600000004001d00000000001404350000000a01000029000800000003001d0000000001130436000a00000001001d00000000002104350000000901000029000000010110003a000000710000613d0000000702000039000000000012041b000000000010043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000008020000290000000002020433000000000101043b000000000021041b0000000a0200002900000000020204330000000103100039000000000023041b000000060200002900000000020204330000000203100039000000000023041b0000000301100039000000000301041a000006fc0230019700000007030000290000000003030433000000000003004b000000010220c1bf000000000021041b0000000701000039000000000501041a000000400100043d00000040021000390000000d03000029000000000032043500000020021000390000000b0300002900000000003204350000000c020000290000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000069e011001c70000800d0200003900000002030000390000069f04000041000004f80000013d000000000020043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000501100039000000000201041a000006fc022001970000000c03000029000000000232019f000000000021041b000000400100043d0000000000310435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006c804000041000004f70000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000c2f0000c13d000008e00000013d000000000010043f0000001801000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000006fc0220019700000001022001bf000000000021041b0000000d0000006b00000de20000c13d000006a201000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b000d00000001001d000000000010043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000c00000002001d0000062f0020009c000000e60000213d000000000101043b0000000c040000290000008002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000b00000003001d00000000002304350000000202100039000000000202041a0000004003400039000000000023043500000060024000390000000301100039000000000101041a000000ff001001900000000001000039000000010100c03900000000001204350000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000d02000029000000000021041b0000000c0200002900000000020204330000000103100039000000000023041b00000003011000390000000b020000290000000002020433000000000021041b0000001901000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000ff001001900000111e0000c13d0000000001000411000000000010043f0000001901000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000006fc0220019700000001022001bf000000000021041b000006a20100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000010043f0000001301000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000d00000002001d000006be0020009c000000e60000213d000000000101043b0000000d04000029000000c002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000b00000003001d00000000002304350000000202100039000000000202041a0000004003400039000a00000003001d00000000002304350000000302100039000000000202041a0000006003400039000c00000003001d00000000002304350000000402100039000000000202041a0000008003400039000800000003001d0000000000230435000000a0024000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000900000002001d00000000001204350000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000c020000290000000002020433000000000101043b000700000001001d0000000401100039000600000001001d000000000101041a000000000012001a000000710000413d000000000112001900000007020000290000000302200039000000000202041a000000000021004b000013f10000a13d000000400100043d000006e10200004100000bb20000013d0000000001000411000000000010043f0000001b01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000b00000001001d000006a40100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b0000000b0110006c000000710000413d0000000c02000039000000000202041a000000000021004b000010300000813d000000400100043d000006b40200004100000bb20000013d000000000020043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000301100039000000000201041a000006fc022001970000000c03000029000000000232019f000000000021041b000000400100043d0000000000310435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000203000039000006c504000041000004f70000013d00000004010000390000000001100367000000000101043b000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000d00000002001d000006be0020009c000000e60000213d000000000101043b0000000d05000029000000c002500039000000400020043f000000000201041a00000000032504360000000104100039000000000404041a00000000004304350000000203100039000000000303041a0000004004500039000b00000004001d00000000003404350000000303100039000000000303041a0000006004500039000c00000004001d00000000003404350000000403100039000000000303041a00000080045000390000000000340435000000a0035000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c0390000000000130435000000000020043f0000001a01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000900000001001d0000000101000039000000000101041a000000400400043d000a00000004001d000006a7020000410000000000240435000000040240003900000000030004100000000000320435000006240040009c0000062402000041000000000204401900000040022002100000000003000414000006240030009c0000062403008041000000c003300210000000000323019f0000062602100197000006a8013001c7188c18870000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0b0000290000000a0570002900000dc10000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000dbd0000c13d000000000006004b00000dce0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000e7f0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006aa0010009c000000e60000213d0000000100200190000000e60000c13d000000400010043f000000200030008c0000111c0000413d00000000020b0433000000090020006b000010b90000a13d000006c30200004100000bb20000013d0000001c01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a00000625022001970000000d03000029000000000232019f000000000021041b000000000030043f0000001e01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000c00000002001d000006aa0020009c000000e60000213d0000000c020000290000000102200039000000000021041b000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006b1011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000c01100029000000000201041a00000625022001970000000003000411000000000232019f000000000021041b0000000d01000029000000000010043f0000001c01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000d06260010019c00000c470000613d0000000001000411000000000010043f0000001d01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a00000625022001970000000d022001af000000000021041b00000c470000013d00000008010000290000062601100197000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000c00000001001d0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000b00000001001d0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a0000000d0210006b000000710000413d0000000b012000b90000000b0000006b00000e700000613d0000000b031000fa000000000023004b000000710000c13d000006af0210012a0000000c0020002a000000710000413d0000000d01000039000000000101041a000006af0010009c000000710000213d0000000e03000039000000000303041a000006af01100099000000000131004b000000710000413d0000000c02200029000003720000c13d000003750000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000e860000c13d000008e00000013d000006d101000041000000000010043f000006d2010000410000188e000104300000000b02000029000000000202043300000007030000290000000403300039000600000003001d000000000303041a000000000032001a000000710000413d000000000232001900000007030000290000000303300039000000000303041a000000000032004b00000ec10000a13d000006e10100004100000004020000290000000000120435000006240020009c00000624020080410000004001200210000006a1011001c70000188e0001043000000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b00000ead0000c13d0000062406600197000000000004004b00000ebf0000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000006001600210000008ee0000013d0000000403000029000000440230003900000000001204350000000001000410000006260110019700000024023000390000000000120435000006ab0100004100000000001304350000000001000411000006260110019700000004023000390000000000120435000006240030009c0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006ac011001c70000000502000029188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000040570002900000ee90000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b00000ee50000c13d000000000006004b00000ef60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000010a70000613d0000001f01400039000000600110018f0000000401100029000006aa0010009c000000e60000213d000000400010043f000000200030008c0000111c0000413d00000004010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b0000111c0000c13d0000000c010000290000000001010433000500000001001d0000000f01000039000000000101041a000400000001001d000000000001004b00000f130000613d000000010100008a00000004011000fa000000050010006c000009120000413d0000000101000039000000000101041a000006ad0200004100000000002004430000062601100197000300000001001d00000004001004430000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000040200002900000005012000b9000006af0310012a000000400200043d000006b00100004100000000001204350000000401200039000100000001001d000400000003001d0000000000310435000006240020009c000500000002001d0000062401000041000000000102401900020040001002180000000001000414000006240010009c0000062401008041000000c00110021000000002011001af000006a8011001c70000000302000029188c18820000040f0000000100200190000011c20000613d0000000501000029000006aa0010009c000000e60000213d0000000501000029000000400010043f0000000c0100002900000000010104330004000400100074000000710000413d0000000101000039000000000101041a000006da0200004100000005040000290000000000240435000006c702000041000000010300002900000000002304350000002402400039000000040300002900000000003204350000000002000414000006240020009c0000062402008041000000c00220021000000002032001af0000062602100197000006c2013001c7188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000050570002900000f6a0000613d000000000801034f0000000509000029000000008a08043c0000000009a90436000000000059004b00000f660000c13d000000000006004b00000f770000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f000000000065043500000001002001900000141d0000613d0000001f01400039000000600110018f0000000501100029000006aa0010009c000000e60000213d000000400010043f000000200030008c0000111c0000413d00000005020000290000000002020433000000000002004b0000000003000039000000010300c039000000000032004b0000111c0000c13d000006db0010009c000000e60000213d0000000102000039000000000302041a0000000202000039000000000402041a000000e002100039000000400020043f0000008002100039000000040500002900000000005204350000062604400197000000600510003900000000004504350000004004100039000027100600003900000000006404350000002006100039000006ca07000041000000000076043500000626033001970000000000310435000000c0031000390000000000030435000000a0071000390000000000070435000006dc08000041000000400900043d000500000009001d0000000000890435000000000101043300000626011001970000000408900039000000000018043500000000010604330000062601100197000000240690003900000000001604350000000001040433000006dd011001970000004404900039000000000014043500000000010504330000062601100197000000640490003900000000001404350000000001020433000000840290003900000000001204350000000001070433000000a402900039000000000012043500000000010304330000062601100197000000c4029000390000000000120435000006240090009c0000062401000041000000000109401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006de011001c7000006c702000041188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000050b000029000000050570002900000fdc0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000fd80000c13d000000000006004b00000fe90000613d000000000171034f0000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f0000000000150435000000010020019000000ff80000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006aa0010009c000000e60000213d0000000100200190000000e60000c13d000000400010043f000000200030008c0000111c0000413d0000000501000039000000000101041a000400000001001d000500010010003e000000710000613d00000005010000390000000502000029000000000021041b0000000a0100002900000000002104350000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000300000001001d0000000401000029000006df0010009c000014190000613d0000000302000029000006fd01200167000200000001001d000000000101041a000000200020043f000400000001001d000000000001004b000015720000c13d0000000301000029000000000101041a000000000001004b000015320000c13d000000050100002900000003020000290000158b0000013d0000000d01000029000000010110003a000000710000613d000000000010043f0000001401000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000400200043d000b00000002001d0000062f0020009c000000e60000213d000000000101043b0000000b040000290000008002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000900000003001d00000000002304350000000202100039000000000202041a0000004003400039000a00000003001d000000000023043500000060024000390000000301100039000000000101041a000000ff001001900000000001000039000000010100c0390000000000120435000000400100043d000d00000001001d000011210000613d0000000101000039000000000201041a000006a7010000410000000d040000290000000000140435000000040140003900000000030004110000000000310435000006240040009c0000062401000041000000000104401900000040011002100000000003000414000006240030009c0000062403008041000000c003300210000000000113019f000006a8011001c70000062602200197000800000002001d188c18870000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000d05700029000010800000613d000000000801034f0000000d09000029000000008a08043c0000000009a90436000000000059004b0000107c0000c13d000000000006004b0000108d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f000000000065043500000001002001900000119c0000613d0000001f01400039000000600110018f0000000d02100029000000000012004b00000000010000390000000101004039000700000002001d000006aa0020009c000000e60000213d0000000100100190000000e60000c13d0000000701000029000000400010043f000000200030008c0000111c0000413d0000000a0100002900000000010104330000000d020000290000000002020433000000000012004b000012000000813d000006b301000041000000070200002900000e9f0000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000010ae0000c13d000008e00000013d000006f501000041000000000010043f0000003201000039000000040010043f000006a8010000410000188e000104300000000001000411000000000010043f0000001701000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000202100039000000000302041a000000000003004b000000710000613d000000010330008a000000000032041b0000000401100039000000000201041a0000000c030000290000000003030433000000000232004b000000710000413d000000000021041b0000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000004020000390000000002200367000000000202043b000c00000002001d000000000101043b000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000004020000390000000002200367000000000202043b000000000002004b0000000c02000029000006bc02006041000c00000002001d000000000201043b000a00000002001d000006fd01200167000600000001001d000000000101041a000700000001001d000000000001004b000011cf0000c13d0000000a040000290000000201400039000800000001001d000000000101041a0000000102400039000000000302041a000000000404041a0000000c0040006c000012c00000c13d0000000a04000029000000000034041b000012c20000013d000000400100043d000006f80200004100000bb20000013d0000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b000011240000c13d00000000010000190000188e00010430000000400100043d000006e70200004100000bb20000013d000006a6010000410000000d0200002900000e9f0000013d000000400300043d00000024013000390000000c020000290000000000210435000006ef010000410000000000130435000000040130003900000009020000290000000000210435000006240030009c000800000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000b02000029188c18820000040f0000000100200190000011b50000613d0000000801000029000006aa0010009c000000e60000213d0000000801000029000000400010043f0000000901000029000000000010043f0000001f01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a0000000c0020002a000000710000413d0000000c02200029000000000021041b0000000001000411000000000010043f0000001d01000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a0000000102000039000000000202041a000006ad0300004100000000003004430000062602200197000c00000002001d0000000400200443000b06260010019c000013950000c13d0000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000400300043d00000024013000390000000a020000290000000000210435000006ef0100004100000000001304350000000001000410000006260110019700000004023000390000000000120435000006240030009c000b00000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000c02000029188c18820000040f0000000100200190000014290000613d0000000b01000029000006aa0010009c000000e60000213d0000000b01000029000000400010043f0000000001000410000000000010043f0000002001000039000000200010043f0000000001000414000013c30000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000011a30000c13d000008e00000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000011b00000c13d00000eb10000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000011bd0000c13d00000eb10000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000011ca0000c13d00000eb10000013d0000000a01000029000000200010043f0000000c01000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000800000001001d000000000101041a000c00000001001d000000000001004b000012c50000613d0000000701000029000000010110027000070001001000920000000c0010006b000011fb0000613d0000000c010000290000000a0110002900000007030000290000000a02300029000000000202041a000000010110008a000000000021041b000000000020043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000c02000029000000000021041b0000000701000029000000010110021000000001011001bf0000000602000029000012c20000013d0000000703000029000000440230003900000000001204350000000001000410000006260110019700000024023000390000000000120435000006ab0100004100000000001304350000000001000411000006260110019700000004023000390000000000120435000006240030009c0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006ac011001c70000000802000029188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000705700029000012280000613d000000000801034f0000000709000029000000008a08043c0000000009a90436000000000059004b000012240000c13d000000000006004b000012350000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000013e20000613d0000001f01400039000000600110018f0000000701100029000006aa0010009c000000e60000213d000000400010043f000000200030008c0000111c0000413d00000007010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b0000111c0000c13d0000000a010000290000000001010433000d00000001001d0000000f01000039000000000101041a000800000001001d000000000001004b000012520000613d000000010100008a00000008011000fa0000000d0010006c000009120000413d0000000101000039000000000101041a000006ad0200004100000000002004430000062601100197000700000001001d00000004001004430000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d00000008020000290000000d012000b9000006af0110012a000000400300043d000006b002000041000000000023043500000004023000390000000000120435000006240030009c000d00000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006a8011001c70000000702000029188c18820000040f0000000100200190000014520000613d0000000d01000029000006aa0010009c000000e60000213d0000000d01000029000000400010043f0000000c01000029000000000101041a000000010110003a000000710000613d0000000c03000029000000000013041b0000000b0100002900000000010104330000000102300039000000000012041b000000030130003900000009020000290000000002020433000000000021041b0000000001000411000000000010043f0000001b01000039000000200010043f000006a40100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000015310000613d000000000101043b000d00000001001d0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000d02000029000000000021041b0000000c01000029000000000601041a0000000a010000290000000001010433000000400200043d0000000000120435000006240020009c000006240200804100000040012002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d020000390000000303000039000006b20400004100000000050004110000081c0000013d0000000c0030006c000013ee0000c13d000000000012041b0000000801000029000000000001041b00000004010000390000000001100367000000000101043b000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000202100039000000000002041b0000000302100039000000000002041b0000000402100039000000000002041b0000000501100039000000000001041b0000000d010000290000000006010433000000400100043d0000000902000029000000000221043600000004030000390000000003300367000000000303043b0000000000320435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d020000390000000303000039000006bf040000410000000005000411188c18820000040f00000001002001900000111c0000613d0000000b010000290000000001010433000d00000001001d0000000001000411188c162d0000040f0000000901000039000000000201041a0000000d0220006c000000710000413d000000000021041b0000000001000411000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a0000000d0220006c000000710000413d000000000021041b0000000001000411000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000d00000001001d0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000101041a000000400200043d000000200320003900000000001304350000000d010000290000000000120435000006240020009c000006240200804100000040012002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d020000390000000203000039000006c0040000410000000005000411188c18820000040f00000001002001900000111c0000613d000000090000006b0000081f0000613d0000000101000039000000000201041a000000400400043d000d00000004001d000000240140003900000009030000290000000000310435000006c10100004100000000001404350000000001000411000006260110019700000004034000390000000000130435000006240040009c0000062401000041000000000104401900000040011002100000000003000414000006240030009c0000062403008041000000c003300210000000000113019f000006c2011001c70000062602200197188c18820000040f00000060031002700000062403300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000d0b0000290000000d05700029000013720000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000136e0000c13d000000000006004b0000137f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000014690000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000006aa0010009c000000e60000213d0000000100200190000000e60000c13d000000400010043f000000200030008c0000111c0000413d00000000010b0433000000000001004b0000000002000039000000010200c039000000000021004b0000081f0000613d0000111c0000013d0000000001000414000006240010009c0000062401008041000000c001100210000006ae011001c70000800202000039188c18870000040f0000000100200190000015310000613d000000000101043b000000000001004b0000111c0000613d000000400300043d00000024013000390000000a020000290000000000210435000006ef01000041000000000013043500000004013000390000000b020000290000000000210435000006240030009c000900000003001d0000062401000041000000000103401900000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006c2011001c70000000c02000029188c18820000040f0000000100200190000014360000613d0000000901000029000006aa0010009c000000e60000213d0000000901000029000000400010043f0000000b01000029000000000010043f0000002001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a0000000a0020002a000000710000413d0000000a02200029000000000021041b000000400100043d0000000d020000290000000000210435000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000121019f000006b1011001c70000800d020000390000000203000039000006f0040000410000000005000411000004f80000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000013e90000c13d000008e00000013d0000000c0010006c000012c30000613d000012c50000013d0000000501000039000000000101041a000500010010003e000000710000613d00000005010000390000000502000029000000000021041b0000000b0100002900000000002104350000000001000411000000000010043f0000001501000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000400000001001d0000000501000029000006bc0010009c000014430000c13d000006e901000041000000000010043f000006d2010000410000188e000104300000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014240000c13d000008e00000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000014310000c13d00000eb10000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b0000143e0000c13d00000eb10000013d0000000402000029000006fd01200167000200000001001d000000000101041a000000200020043f000300000001001d000000000001004b000014ab0000c13d0000000401000029000000000101041a000000000001004b0000145f0000c13d00000005010000290000000402000029000014c40000013d00000060061002700000001f0460018f000006a905600198000000400200043d000000000352001900000eb10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b0000145a0000c13d00000eb10000013d000000050010006c000014c50000613d00000004020000290000000102200039000000000302041a000300000003001d000000000003004b000014750000c13d0000000501000029000014c40000013d0000001f0530018f000006a906300198000000400200043d0000000004620019000008e00000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014700000c13d000008e00000013d0000000303000029000000050030006c000014c50000613d00000004020000290000000202200039000000000302041a000100000003001d000000000003004b000014670000613d0000000103000029000000050030006c000014c50000613d000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000102000039000000000021041b0000000301000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000202000039000000000021041b0000000101000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000302000039000000000021041b000300070000003d0000000501000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000000000002004b000014c50000c13d0000000302000029000000010220027000000004032000290000000504000029000000000043041b0000000102200039000000000021041b000000010120021000000001011001bf0000000202000029000000000012041b0000000501000039000000000101041a000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d0000000d020000290000000002020433000000000301043b000000000023041b0000000b0100002900000000010104330000000102300039000000000012041b0000000a0100002900000000010104330000000202300039000000000012041b0000000c0100002900000000010104330000000302300039000000000012041b000000080200002900000000020204330000000404300039000000000024041b0000000502300039000000000302041a000006fc0330019700000009040000290000000004040433000000000004004b000000010330c1bf000000000032041b00000007020000290000000202200039000000000302041a000000010330003a000000710000613d000000000032041b0000000602000029000000000202041a000000000012001a000000710000413d00000000011200190000000602000029000000000012041b0000000501000039000000000101041a000000400300043d00000020023000390000000000120435000d00000003001d0000000000030435000006a20100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000006240010009c0000062401008041000000c001100210000006c4011001c70000800502000039188c18870000040f0000000100200190000015310000613d000000000601043b0000000d01000029000006240010009c000006240100804100000040011002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d020000390000000303000039000006e0040000410000000005000411188c18820000040f00000001002001900000111c0000613d0000000a0100002900000000020104330000000001000411188c16f10000040f0000000001000414000006240010009c0000062401008041000000c00110021000000627011001c70000800d020000390000000203000039000006e8040000410000000005000411000004f80000013d000000000001042f000000050010006c0000158c0000613d00000003020000290000000102200039000000000302041a000400000003001d000000000003004b0000153c0000c13d00000005010000290000158b0000013d0000000403000029000000050030006c0000158c0000613d00000003020000290000000202200039000000000302041a000100000003001d000000000003004b0000153a0000613d0000000103000029000000050030006c0000158c0000613d000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000102000039000000000021041b0000000401000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000202000039000000000021041b0000000101000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b0000000302000039000000000021041b000400070000003d0000000501000029000000000010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d000000000101043b000000000201041a000000000002004b0000158c0000c13d0000000402000029000000010220027000000003032000290000000504000029000000000043041b0000000102200039000000000021041b000000010120021000000001011001bf0000000202000029000000000012041b0000000501000039000000000101041a000000000010043f0000001601000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f00000001002001900000111c0000613d00000008020000290000000002020433000000000301043b000000000023041b0000000a0100002900000000010104330000000102300039000000000012041b000000090100002900000000010104330000000202300039000000000012041b0000000b0100002900000000020104330000000301300039000000000021041b0000000c0100002900000000010104330000000404300039000000000014041b0000000503300039000000000503041a000006fc045001970000000d050000290000000005050433000000000005004b000000010440c1bf000000000043041b00000007030000290000000203300039000000000403041a000000010440003a000000710000613d000000000043041b0000000603000029000000000303041a000000000023001a000000710000413d00000000022300190000000603000029000000000023041b0000000502000039000000000202041a000000400300043d00000020043000390000000000240435000000000013043500000004010000390000000001100367000000000601043b000006240030009c000006240300804100000040013002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d020000390000000303000039000006e0040000410000000005000411188c18820000040f00000001002001900000111c0000613d000000090100002900000000020104330000000001000411188c16f10000040f00000000010000190000188d0001042e0001000000000002000000000301041a000100000002001d000000000023004b000015f50000a13d000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006b1011001c70000801002000039188c18870000040f0000000100200190000015fb0000613d000000000101043b00000001011000290000000002000019000000000001042d000006f501000041000000000010043f0000003201000039000000040010043f000006a8010000410000188e0001043000000000010000190000188e000104300000001f02200039000006fe022001970000000001120019000000000021004b00000000020000390000000102004039000006aa0010009c000016090000213d0000000100200190000016090000c13d000000400010043f000000000001042d000006f501000041000000000010043f0000004101000039000000040010043f000006a8010000410000188e000104300000000002120049000006ff0020009c0000161b0000213d0000001f0020008c0000161b0000a13d0000000001010433000000000001004b0000000002000039000000010200c039000000000021004b0000161b0000c13d000000000001042d00000000010000190000188e00010430000000000100041a00000626021001970000000001000411000000000012004b000016230000c13d000000000001042d000000400200043d0000069c03000041000000000032043500000004032000390000000000130435000006240020009c00000624020080410000004001200210000006a8011001c70000188e000104300003000000000002000100000001001d0000000901000039000000000101041a000000000001004b00000008020000390000167f0000613d0000000301000039000000000101041a000000000202041a000000000112004b000016e20000413d000006ce0010009c000016e20000213d000300000002001d0000062401100197000006cf0110012a000206d000100287000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000016e80000613d000000000101043b0000000304000029000000000014004b0000168b0000813d000006cf0240012a0000000103200039000006cf023000d100000000033200d9000006cf0030009c0000000207000029000016e20000c13d0000000303000039000000000303041a000006cf3030012a000000000023001a000016e20000413d0000000003230019000000000013004b00000000020100190000000002034019000000000442004b000016e20000413d000000000007004b0000166d0000613d00000000057400a900000000067500d9000000000046004b000016e20000c13d000000000005004b0000166d0000613d000006af045000d100000000055400d9000006af0050009c0000166e0000613d000016e20000013d00000000040000190000000905000039000000000505041a000000000005004b000016e90000613d00000000045400d90000000b05000039000000000505041a000000000045001a000016e20000413d00000000044500190000000b05000039000000000045041b000000000013004b000000010770a270000200000007001d000300000002001d0000163f0000013d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000016e80000613d000000000101043b0000000802000039000000000012041b00000001010000290000062601100197000300000001001d000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000016ef0000613d0000000b02000039000000000202041a000100000002001d000000000101043b000000000101041a000200000001001d0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000016ef0000613d000000000101043b000000000101041a000000010110006b0000000202000029000016e20000413d00000000032100a9000000000002004b000016b80000613d00000000022300d9000000000012004b000016e20000c13d000200000003001d0000000301000029000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000016ef0000613d0000000202000029000006af0220012a000000000101043b000000000301041a000000000023001a000016e20000413d0000000002230019000000000021041b0000000b01000039000000000101041a000200000001001d0000000301000029000000000010043f0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000016ef0000613d000000000101043b0000000202000029000000000021041b000000000001042d000006f501000041000000000010043f0000001101000039000000040010043f000006a8010000410000188e00010430000000000001042f000006f501000041000000000010043f0000001201000039000000040010043f000006a8010000410000188e0001043000000000010000190000188e000104300004000000000002000200000002001d000100000001001d0000000401000039000000000201041a000000ff002001900000171c0000c13d000006fc0220019700000001022001bf000000000021041b000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000018210000613d000000000101043b0000000302000039000000000012041b0000000802000039000000000012041b000000400200043d0000000000120435000006240020009c000006240200804100000040012002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f000006b1011001c70000800d0200003900000001030000390000070004000041188c18820000040f0000000100200190000018280000613d0000000901000039000000000101041a000000000001004b0000176c0000613d0000000301000039000000000101041a0000000802000039000000000202041a000000000112004b0000181b0000413d000006ce0010009c0000181b0000213d000400000002001d0000062401100197000006cf0110012a000306d000100287000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000018210000613d000000000101043b0000000404000029000000000014004b000017780000813d000006cf0240012a0000000103200039000006cf023000d100000000033200d9000006cf0030009c00000003070000290000181b0000c13d0000000303000039000000000303041a000006cf3030012a000000000023001a0000181b0000413d0000000003230019000000000013004b00000000020100190000000002034019000000000442004b0000181b0000413d000000000007004b0000175a0000613d00000000057400a900000000067500d9000000000046004b0000181b0000c13d000000000005004b0000175a0000613d000006af045000d100000000055400d9000006af0050009c0000175b0000613d0000181b0000013d00000000040000190000000905000039000000000505041a000000000005004b000018220000613d00000000045400d90000000b05000039000000000505041a000000000045001a0000181b0000413d00000000044500190000000b05000039000000000045041b000000000013004b000000010770a270000300000007001d000400000002001d0000172c0000013d000006cd0100004100000000001004430000000001000414000006240010009c0000062401008041000000c001100210000006a5011001c70000800b02000039188c18870000040f0000000100200190000018210000613d000000000101043b0000000802000039000000000012041b00000001010000290000062601100197000400000001001d000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d0000000b02000039000000000202041a000100000002001d000000000101043b000000000101041a000300000001001d0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b000000000101041a000000010110006b00000003020000290000181b0000413d00000000032100a9000000000002004b000017a50000613d00000000022300d9000000000012004b0000181b0000c13d000300000003001d0000000401000029000000000010043f0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d0000000302000029000006af0220012a000000000101043b000000000301041a000000000023001a0000181b0000413d0000000002230019000000000021041b0000000b01000039000000000101041a000300000001001d0000000401000029000000000010043f0000001201000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b0000000302000029000000000021041b0000000901000039000000000101041a000000020010002a0000181b0000413d00000002011000290000000902000039000000000012041b0000000401000029000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b000000000201041a000000020020002a0000181b0000413d0000000202200029000000000021041b0000000401000029000000000010043f0000001001000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b000000000101041a000400000001001d0000001101000039000000200010043f0000000001000414000006240010009c0000062401008041000000c0011002100000062e011001c70000801002000039188c18870000040f0000000100200190000018280000613d000000000101043b000000000101041a000000400200043d0000002003200039000000000013043500000004010000290000000000120435000006240020009c000006240200804100000040012002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f0000062e011001c70000800d02000039000000020300003900000000050004110000070104000041188c18820000040f0000000100200190000018280000613d000000000001042d000006f501000041000000000010043f0000001101000039000000040010043f000006a8010000410000188e00010430000000000001042f000006f501000041000000000010043f0000001201000039000000040010043f000006a8010000410000188e0001043000000000010000190000188e00010430000006ba02000041000000040020043f000000000010043f0000000001000414000006240010009c0000062401008041000000c001100210000006bb011001c70000801002000039188c18870000040f00000001002001900000184c0000613d000000000201043b000006fd01200167000000000101041a000000000001004b0000183d0000613d0000000101100270000000000001042d000000000102041a000000000001004b0000000001000039000000010100c0390000184b0000613d0000000103200039000000000303041a000000000003004b0000184b0000613d0000000201200039000000000101041a000000000001004b00000003010000390000000201006039000000000001042d00000000010000190000188e00010430000000000001042f000006240010009c00000624010080410000004001100210000006240020009c00000624020080410000006002200210000000000112019f0000000002000414000006240020009c0000062402008041000000c002200210000000000112019f00000627011001c70000801002000039188c18870000040f0000000100200190000018620000613d000000000101043b000000000001042d00000000010000190000188e0001043000000000050100190000000000200443000000050030008c000018720000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b0000186a0000413d000006240030009c000006240300804100000060013002100000000002000414000006240020009c0000062402008041000000c002200210000000000112019f00000702011001c70000000002050019188c18870000040f0000000100200190000018810000613d000000000101043b000000000001042d000000000001042f00001885002104210000000102000039000000000001042d0000000002000019000000000001042d0000188a002104230000000102000039000000000001042d0000000002000019000000000001042d0000188c000004320000188d0001042e0000188e00010430000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff02000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0000000000000000000000000000000000000000000000000000000000001518000000000000000000000000000000000000000000000000000470de4df820000000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000ffffffffffffff400200000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7f00000002000000000000000000000000000000c00000010000000000000000001e4fbdf7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000c0000000000000000000000000000000000000000000000000000000000000000000000000787a08a500000000000000000000000000000000000000000000000000000000b2678ef000000000000000000000000000000000000000000000000000000000df1e3b7e00000000000000000000000000000000000000000000000000000000ea26fa2c00000000000000000000000000000000000000000000000000000000eef3b2cf00000000000000000000000000000000000000000000000000000000eef3b2d000000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000f5c823ce00000000000000000000000000000000000000000000000000000000ea26fa2d00000000000000000000000000000000000000000000000000000000ec56c7f400000000000000000000000000000000000000000000000000000000e65a2e7d00000000000000000000000000000000000000000000000000000000e65a2e7e00000000000000000000000000000000000000000000000000000000e8ee067000000000000000000000000000000000000000000000000000000000e92820e600000000000000000000000000000000000000000000000000000000df1e3b7f00000000000000000000000000000000000000000000000000000000e0d152af00000000000000000000000000000000000000000000000000000000c8e66bea00000000000000000000000000000000000000000000000000000000d147129500000000000000000000000000000000000000000000000000000000d147129600000000000000000000000000000000000000000000000000000000d9ba62b300000000000000000000000000000000000000000000000000000000dd6a4c6500000000000000000000000000000000000000000000000000000000c8e66beb00000000000000000000000000000000000000000000000000000000ca18117000000000000000000000000000000000000000000000000000000000c51a2bb900000000000000000000000000000000000000000000000000000000c51a2bba00000000000000000000000000000000000000000000000000000000c600589300000000000000000000000000000000000000000000000000000000b2678ef100000000000000000000000000000000000000000000000000000000c2435894000000000000000000000000000000000000000000000000000000008f1f1a260000000000000000000000000000000000000000000000000000000096fd750f000000000000000000000000000000000000000000000000000000009f715f5f000000000000000000000000000000000000000000000000000000009f715f6000000000000000000000000000000000000000000000000000000000a9f8d18100000000000000000000000000000000000000000000000000000000ad5c46480000000000000000000000000000000000000000000000000000000096fd7510000000000000000000000000000000000000000000000000000000009ca423b30000000000000000000000000000000000000000000000000000000094fc19e30000000000000000000000000000000000000000000000000000000094fc19e4000000000000000000000000000000000000000000000000000000009618b31c000000000000000000000000000000000000000000000000000000008f1f1a27000000000000000000000000000000000000000000000000000000008fc593a40000000000000000000000000000000000000000000000000000000084ae2bc5000000000000000000000000000000000000000000000000000000008da5cb5a000000000000000000000000000000000000000000000000000000008da5cb5b000000000000000000000000000000000000000000000000000000008dfc3933000000000000000000000000000000000000000000000000000000008e4f8d480000000000000000000000000000000000000000000000000000000084ae2bc60000000000000000000000000000000000000000000000000000000086b3cd26000000000000000000000000000000000000000000000000000000007e08b5b2000000000000000000000000000000000000000000000000000000007e08b5b300000000000000000000000000000000000000000000000000000000811c508900000000000000000000000000000000000000000000000000000000787a08a6000000000000000000000000000000000000000000000000000000007b4af37c0000000000000000000000000000000000000000000000000000000041a0894c000000000000000000000000000000000000000000000000000000005fd9491c000000000000000000000000000000000000000000000000000000006d12ff5100000000000000000000000000000000000000000000000000000000715018a500000000000000000000000000000000000000000000000000000000715018a60000000000000000000000000000000000000000000000000000000072779cba0000000000000000000000000000000000000000000000000000000077f793c7000000000000000000000000000000000000000000000000000000006d12ff5200000000000000000000000000000000000000000000000000000000713494d7000000000000000000000000000000000000000000000000000000006756a1c6000000000000000000000000000000000000000000000000000000006756a1c70000000000000000000000000000000000000000000000000000000069f0ee33000000000000000000000000000000000000000000000000000000005fd9491d0000000000000000000000000000000000000000000000000000000062de3bd1000000000000000000000000000000000000000000000000000000004fc3f4190000000000000000000000000000000000000000000000000000000059058ad00000000000000000000000000000000000000000000000000000000059058ad1000000000000000000000000000000000000000000000000000000005a5ccef0000000000000000000000000000000000000000000000000000000005c7421e3000000000000000000000000000000000000000000000000000000004fc3f41a00000000000000000000000000000000000000000000000000000000542f9e6a0000000000000000000000000000000000000000000000000000000048cd4cb00000000000000000000000000000000000000000000000000000000048cd4cb1000000000000000000000000000000000000000000000000000000004e3e6fe10000000000000000000000000000000000000000000000000000000041a0894d00000000000000000000000000000000000000000000000000000000445e02d8000000000000000000000000000000000000000000000000000000002b3f1957000000000000000000000000000000000000000000000000000000003223c02f000000000000000000000000000000000000000000000000000000003ccfd60a000000000000000000000000000000000000000000000000000000003ccfd60b000000000000000000000000000000000000000000000000000000003e89bb130000000000000000000000000000000000000000000000000000000040f5da9e000000000000000000000000000000000000000000000000000000003223c03000000000000000000000000000000000000000000000000000000000372500ab00000000000000000000000000000000000000000000000000000000304fbfc600000000000000000000000000000000000000000000000000000000304fbfc70000000000000000000000000000000000000000000000000000000031d7a262000000000000000000000000000000000000000000000000000000002b3f1958000000000000000000000000000000000000000000000000000000002fc96ce6000000000000000000000000000000000000000000000000000000001a267cd1000000000000000000000000000000000000000000000000000000001f6a3bb8000000000000000000000000000000000000000000000000000000001f6a3bb900000000000000000000000000000000000000000000000000000000234f3f1b0000000000000000000000000000000000000000000000000000000024b4464e000000000000000000000000000000000000000000000000000000001a267cd2000000000000000000000000000000000000000000000000000000001e57057d00000000000000000000000000000000000000000000000000000000157e204b00000000000000000000000000000000000000000000000000000000157e204c0000000000000000000000000000000000000000000000000000000017820fd0000000000000000000000000000000000000000000000000000000000682c0310000000000000000000000000000000000000000000000000000000010d967590000000000000000000000000000000000000020000000800000000000000000118cdaa700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000080000000000000000002000000000000000000000000000000000000600000000000000000000000007152312bf5cf776256aadaa3e2daf52b5095f4118a657aafae2bd749931e0f98d2a50ed0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0000000000000000000000000000000000000020000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000047cd2fa60000000000000000000000000000000000000000000000000000000070a0823100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffff23b872dd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000042966c68000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000020000000000000000000000000e2dbc44c627e3876b04b29d12596a77c7d0fa585ccb754b9fcd92e48d813dd77ff0b21e60000000000000000000000000000000000000000000000000000000041fde9ef0000000000000000000000000000000000000000000000000000000072932dd3000000000000000000000000000000000000000000000000000000000c02d44e000000000000000000000000000000000000000000000000000000000e6ce2f100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000080000000000000000000000000000000000000000000000000000000c00000008000000000000000000000000000000000000000000000000000000000000000000000000018fb586402000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000fbb67fda52d4bfb8bf3d9f63cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff3fbb8db292349eecec0f157746522d22a04be58c69c690e5af7d7f15a6a04d4d87e331ada0d0e61e9a4196bf4994f2519193d70a601daff346c4276d591664da9aa9059cbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000515d3e810000000000000000000000000000000000000000000000000000000002000002000000000000000000000000000000440000000000000000000000000bd772fd008a8dd5673c42a4f50f72220b2603eee55113cd6c38ff78d71e644fedd999f8000000000000000000000000000000000000000000000000000000000000000000000000000000007712fa47387542819d4e35a23f8116c90c18767cd0a7ceb410ade2d440d8ed59d6b338fe480f98025101655790e0de736edddabe3b87f109000000000000000000000000000000000000000000000000000000000000000000000000000000003439153eb7af838ad19d56e1571fbd09333c28090200000000000000000000000000000000000080000000000000000000000000e0a2f8482bbba7e119c069eb63409ac33b15fc516cffed25aeabb6a9669e07c242cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd1000000000000000000000000000000000000000000000000000000000545ffff0000000000000000000000000000000000000000000000000000000000054600000000000000000000000000000000000000000000000001a055690d9db8000000000000000000000000000000000000000000000000000000000000ad251c2700000000000000000000000000000000000000040000001c00000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000158d620b300000000000000000000000000000000000000000000000000000000f721e9425607d38abda58b925d2a080b3aefa127d46973d2683875dc87cb9a6bf1fa1762000000000000000000000000000000000000000000000000000000006cb4090800000000000000000000000000000000000000000000000000000000f920b24ea96b3814655944622f9eb86875e3193c5de1a9de018777e6c8705cee4705d68400000000000000000000000000000000000000000000000000000000095ea7b300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1f04e45aaf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffff00000000000000000000000000000000000000e40000000000000000000000000000000000000000000000000000000000000000000000fbb67fda52d4bfb8bee9a3d31ddc75e6f55428f56a99300650dd35074dbe47cffa59e8292fe6f2886ffbfd2f4000000000000000000000000000000000000000000000000000000000aa8a9b980000000000000000000000000000000000000000000000000000000086257f0afab037798cc4548a6d86125f52c92410a1e29aff03d787d49dac20db00000000000000000000000000000000000000a0000000800000000000000000d2ade556000000000000000000000000000000000000000000000000000000008fe6f7d80000000000000000000000000000000000000000000000000000000070e9a55a00000000000000000000000000000000000000000000000000000000e424ed553a53c3a900c875ed34d63043e4dfb799427ee8ae0836b046a603c90e00000000000000000000000000000000000000000000000000000000f5a267f161104228000000000000000000000000000000000000000000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f3900000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000003ffffffe0750b219c0000000000000000000000000000000000000000000000000000000040c10f1900000000000000000000000000000000000000000000000000000000fc30cddea38e2bf4d6ea7d3f9ed3b6ad7f176419f4963bd81318067a4aee73fe0df723dc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000080000000000000000000000000000000000000000000000000000000000000000000000000bac65e5b602fe2ca000000000000000000000000000000000000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe04e23d035000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000800000000000000000e5b88ba483d0be6c345877ef44085c5e1edc7fa963ccb86223d06a681f9306753a6c77df00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdaae9aa758637a0d349f036f099afd70aa88d8ac63fce096321de512ffebc16ca051d58ced8df58040b29d2c939da70a826ae40290f77c9a66b38b8b85315f6502000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fd0fc2d7cabdd70d07801fec85ad015d9ddc48efab396fafdd1a20726b1b8b76
Loading...
Loading
Loading...
Loading
[ 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.