More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 2,504 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Rewards | 6896802 | 9 mins ago | IN | 0 ETH | 0.00000932 | ||||
Claim Rewards | 6896629 | 13 mins ago | IN | 0 ETH | 0.00000727 | ||||
Claim Rewards | 6896161 | 20 mins ago | IN | 0 ETH | 0.00000663 | ||||
Claim Rewards | 6895974 | 24 mins ago | IN | 0 ETH | 0.00000829 | ||||
Buy Miner | 6895799 | 26 mins ago | IN | 0 ETH | 0.00001 | ||||
Upgrade Facility | 6895744 | 27 mins ago | IN | 0 ETH | 0.00000682 | ||||
Buy Miner | 6895723 | 28 mins ago | IN | 0 ETH | 0.00001014 | ||||
Buy Miner | 6895702 | 28 mins ago | IN | 0 ETH | 0.00001823 | ||||
Buy Miner | 6895682 | 29 mins ago | IN | 0 ETH | 0.00001976 | ||||
Claim Rewards | 6895650 | 29 mins ago | IN | 0 ETH | 0.00000798 | ||||
Claim Rewards | 6895578 | 30 mins ago | IN | 0 ETH | 0.00000837 | ||||
Claim Rewards | 6895081 | 39 mins ago | IN | 0 ETH | 0.00001129 | ||||
Claim Rewards | 6893480 | 1 hr ago | IN | 0 ETH | 0.00000625 | ||||
Claim Rewards | 6893406 | 1 hr ago | IN | 0 ETH | 0.00000592 | ||||
Buy Miner | 6892819 | 1 hr ago | IN | 0 ETH | 0.00001007 | ||||
Buy Miner | 6892807 | 1 hr ago | IN | 0 ETH | 0.00001501 | ||||
Claim Rewards | 6892506 | 1 hr ago | IN | 0 ETH | 0.00001073 | ||||
Claim Rewards | 6892314 | 1 hr ago | IN | 0 ETH | 0.0000068 | ||||
Upgrade Facility | 6892287 | 1 hr ago | IN | 0 ETH | 0.00001094 | ||||
Claim Rewards | 6891737 | 1 hr ago | IN | 0 ETH | 0.00001519 | ||||
Claim Rewards | 6891407 | 1 hr ago | IN | 0 ETH | 0.00000703 | ||||
Claim Rewards | 6891357 | 1 hr ago | IN | 0 ETH | 0.00000873 | ||||
Claim Rewards | 6891288 | 1 hr ago | IN | 0 ETH | 0.00000804 | ||||
Claim Rewards | 6890968 | 1 hr ago | IN | 0 ETH | 0.00001628 | ||||
Claim Rewards | 6890643 | 2 hrs ago | IN | 0 ETH | 0.00001173 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
6888489 | 2 hrs ago | 0.01 ETH | ||||
6883626 | 4 hrs ago | 0.01 ETH | ||||
6864645 | 10 hrs ago | 0.01 ETH | ||||
6854766 | 13 hrs ago | 0.01 ETH | ||||
6845962 | 15 hrs ago | 0.01 ETH | ||||
6842995 | 16 hrs ago | 0.01 ETH | ||||
6839275 | 17 hrs ago | 0.01 ETH | ||||
6836572 | 18 hrs ago | 0.01 ETH | ||||
6834487 | 18 hrs ago | 0.01 ETH | ||||
6833329 | 19 hrs ago | 0.01 ETH | ||||
6832672 | 19 hrs ago | 0.01 ETH | ||||
6829611 | 20 hrs ago | 0.01 ETH | ||||
6829313 | 20 hrs ago | 0.01 ETH | ||||
6825736 | 21 hrs ago | 0.01 ETH | ||||
6825019 | 21 hrs ago | 0.01 ETH | ||||
6824487 | 21 hrs ago | 0.01 ETH | ||||
6823979 | 21 hrs ago | 0.01 ETH | ||||
6822923 | 22 hrs ago | 0.01 ETH | ||||
6822702 | 22 hrs ago | 0.01 ETH | ||||
6822478 | 22 hrs ago | 0.01 ETH | ||||
6820808 | 22 hrs ago | 0.01 ETH | ||||
6820393 | 22 hrs ago | 0.01 ETH | ||||
6819490 | 23 hrs ago | 0.01 ETH | ||||
6818834 | 23 hrs ago | 0.01 ETH | ||||
6817972 | 23 hrs ago | 0.01 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 {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; import {EnumerableSetLib} from "solady/src/utils/EnumerableSetLib.sol"; import "./Mining.sol"; contract Main is Mining, Ownable { using EnumerableSetLib for EnumerableSetLib.Uint256Set; constructor() Ownable(_msgSender()) { STARTER_MINER_INDEX = ++uniqueMinerCount; miners[STARTER_MINER_INDEX] = Miner(STARTER_MINER_INDEX, type(uint256).max, 50, 10, 300 ether, true); } function getBitForgePerBlock() public view returns (uint256) { if (!miningHasStarted) { return 0; } uint256 halvingsSinceStart = (block.number - startBlock) / HALVING_INTERVAL; return INITIAL_REWARD_PER_BLOCK / (2 ** halvingsSinceStart); } 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 lastBitForgePerBlock = INITIAL_REWARD_PER_BLOCK / (2 ** ((lastRewardBlock - startBlock) / HALVING_INTERVAL)); uint256 simulatedCumulativeBitForgePerHash = cumulativeBitForgePerHash; uint256 _latestHalvingBlock = latestHalvingBlock; while (currentBlock < block.number) { uint256 nextHalvingBlock = _latestHalvingBlock + HALVING_INTERVAL; uint256 endBlock = (nextHalvingBlock < block.number) ? nextHalvingBlock : block.number; // simulate rewards accumulation if (totalHashrate > 0) { simulatedCumulativeBitForgePerHash += ((lastBitForgePerBlock * (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) { lastBitForgePerBlock /= 2; _latestHalvingBlock = currentBlock; } } return FixedPointMathLib.mulWad( playerPendingRewards[player] + ( (playerHashrate[player] * (simulatedCumulativeBitForgePerHash - playerBitForgeDebt[player])) / REWARDS_PRECISION ), 1e18 - referralFee - secondTierReferralFee ); } function playerBitForgePerBlock(address player) external view returns (uint256) { if (totalHashrate == 0) { return 0; } uint256 currBitForgePerBlock = INITIAL_REWARD_PER_BLOCK / (2 ** ((block.number - startBlock) / HALVING_INTERVAL)); return FixedPointMathLib.mulDiv(playerHashrate[player], currBitForgePerBlock, totalHashrate); } function blocksUntilNextHalving() external view returns (uint256) { if (startBlock == 0) return 0; uint256 nextHalvingBlock = latestHalvingBlock + HALVING_INTERVAL; return nextHalvingBlock - block.number; } function getNextHalvingBlock() external view returns (uint256) { if (startBlock == 0) return 0; return latestHalvingBlock + HALVING_INTERVAL; } function timeUntilNextFacilityUpgrade(address player) external view returns (uint256) { return lastFacilityUpgradeTimestamp[player] + upgradeCooldown; } 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(); } function getReferrals(address referrer) external view returns (address[] memory) { return referredUsers[referrer]; } // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ // OWNER FUNCTIONS // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 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); } 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); } function addSecondaryMarketForMiner(uint256 minerIndex, uint256 price) external onlyOwner { minerSecondHandMarket[minerIndex] = price; emit Events.MinerSecondaryMarketAdded(minerIndex, price); } function setBitForge(address _newAddress) external onlyOwner { bitForge = _newAddress; } function setbittoshi(address _bittoshi) external onlyOwner { bittoshi = _bittoshi; } function setInitialFacility(uint256 _initialPrice, uint256 _initialFacilityPower) external onlyOwner { initialFacilityPrice = _initialPrice; initialFacilityPower = _initialFacilityPower; } function setUpgradeFacility(uint256 _cooldown, uint256 _upgradePrice, uint256 _powers) external onlyOwner { upgradeCooldown = _cooldown; upgradeFacilityPrice = _upgradePrice; powerUpgradeAmount = _powers; } 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 setupgradeCooldown(uint256 _upgradeCooldown) external onlyOwner { upgradeCooldown = _upgradeCooldown; } function withdraw() external onlyOwner { uint256 balance = address(this).balance; (bool success,) = payable(bittoshi).call{value: balance}(""); if (!success) revert Errors.WithdrawFailed(); } function withdrawBit(uint256 amt) external onlyOwner { IBitForge(bitForge).transfer(bittoshi, amt); } function updateMiner(uint256 minerIndex, uint256 cost, uint256 power, uint256 hashrate, bool inProduction) external onlyOwner { Miner storage miner = miners[minerIndex]; miner.cost = cost; miner.powerConsumption = power; miner.hashrate = hashrate; miner.inProduction = inProduction; } function open() external onlyOwner { isOpen = true; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; import {EnumerableSetLib} from "solady/src/utils/EnumerableSetLib.sol"; import {FixedPointMathLib} from "solady/src/utils/FixedPointMathLib.sol"; import {Errors} from "./libraries/Errors.sol"; import {Events} from "./libraries/Events.sol"; import {IBitForge} from "./interfaces/IBitForge.sol"; import {IV3SwapRouter} from "./interfaces/ISwapRouter.sol"; import {Miner} from "./types/Miner.sol"; import {Facility} from "./types/Facility.sol"; contract Mining is Context { address public constant SWAP_ROUTER = 0x7712FA47387542819d4E35A23f8116C90C18767C; address public constant WETH = 0x3439153EB7AF838Ad19d56E1571FBD09333C2809; using EnumerableSetLib for EnumerableSetLib.Uint256Set; address public bitForge; /// @dev bittoshi fee recipient. address public bittoshi; /// @dev Mining start block. uint256 public startBlock; uint256 public latestHalvingBlock; uint256 public havingCount; /// @dev Tracks if mining has started. bool public miningHasStarted; // every miner has an id uint256 universalMinerId; /// @dev Total unique miners. uint256 public uniqueMinerCount; /// @dev Tracks last time we updated rewards. uint256 public lastRewardBlock; /// @dev Total network hashrate. uint256 public totalHashrate; bool public enableUpgradeFacility; /// @dev Tracks BitForge per single hash. uint256 public cumulativeBitForgePerHash; /// @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 playerBitForgeDebt; /// @dev Tracks different miners and its stats. mapping(uint256 => Miner) public miners; /// @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 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; uint256 public upgradeCooldown = 4 hours; uint256 public initialFacilityPrice = 0.01 ether; uint256 public upgradeFacilityPrice = 900 ether; uint256 public initialFacilityPower = 100; uint256 public powerUpgradeAmount = 100; /// @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 constant HALVING_INTERVAL = 172_800; uint256 public constant INITIAL_REWARD_PER_BLOCK = 50e18; uint256 public constant REWARDS_PRECISION = 1e18; bool public isOpen; function purchaseInitialFacility(address referrer) external payable { require(isOpen, "not open"); if (msg.value != initialFacilityPrice) { revert Errors.IncorrectValue(); } if (initializedStarterFacility[_msgSender()]) { revert Errors.AlreadyPurchasedInitialFactory(); } if (referrer == _msgSender()) { revert Errors.InvalidReferrer(); } initializedStarterFacility[_msgSender()] = true; if (referrer != address(0)) { referrals[_msgSender()] = referrer; referredUsers[referrer].push(_msgSender()); // Set second tier referral (referrer's referrer) address secondTierReferrer = referrals[referrer]; if (secondTierReferrer != address(0)) { secondTierReferrals[_msgSender()] = secondTierReferrer; } } Facility storage facility = ownerToFacility[_msgSender()]; facility.totalPowerOutput = initialFacilityPower; _getFreeStarterMiner(_msgSender()); emit Events.InitialFacilityPurchased(_msgSender()); } 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[_msgSender()]; // this case will cover if an index too large is passed in if (!miner.inProduction) revert Errors.MinerNotInProduction(); if (IBitForge(bitForge).balanceOf(_msgSender()) < miner.cost) { revert Errors.TooPoor(); } if (facility.currPowerOutput + miner.powerConsumption > facility.totalPowerOutput) { revert Errors.FacilityInadequatePowerOutput(); } // transfer correct amt of BitForge IBitForge(bitForge).transferFrom(_msgSender(), address(this), miner.cost); uint256 amountToBurn = FixedPointMathLib.mulWad(miner.cost, burnPct); // burn IBitForge(bitForge).burn(amountToBurn); uint256 amountToSwap = miner.cost - amountToBurn; _swapTokentoETH(amountToSwap); miner.id = ++universalMinerId; playerMinersOwned[_msgSender()].add(universalMinerId); playerMinersId[universalMinerId] = miner; // increase facility miners facility.currMiners++; // increase power consumption from factory facility.currPowerOutput += miner.powerConsumption; emit Events.MinerBought(_msgSender(), minerIndex, miner.cost, universalMinerId); _increaseHashrate(_msgSender(), miner.hashrate); } function sellMiner(uint256 minerId) external { if (!playerMinersOwned[_msgSender()].contains(minerId)) { revert Errors.PlayerDoesNotOwnMiner(); } Miner memory miner = playerMinersId[minerId]; uint256 secondHandPrice = minerSecondHandMarket[miner.minerIndex]; if (secondHandPrice > IBitForge(bitForge).balanceOf(address(this))) { revert Errors.GreatDepression(); } Facility storage facility = ownerToFacility[_msgSender()]; facility.currMiners--; facility.currPowerOutput -= miner.powerConsumption; playerMinersOwned[_msgSender()].remove(minerId); delete playerMinersId[minerId]; emit Events.MinerSold(_msgSender(), miner.minerIndex, secondHandPrice, minerId); _decreaseHashrate(_msgSender(), miner.hashrate); if (secondHandPrice > 0) { IBitForge(bitForge).transfer(_msgSender(), secondHandPrice); } } function upgradeFacility() external { if (!enableUpgradeFacility) { revert Errors.UpgradeFacilityDisabled(); } // need to purchase initial facility first if (!initializedStarterFacility[_msgSender()]) { revert Errors.NeedToInitializeFacility(); } Facility storage currFacility = ownerToFacility[_msgSender()]; if (block.timestamp - lastFacilityUpgradeTimestamp[_msgSender()] < upgradeCooldown) { revert Errors.CantBuyNewFacilityYet(); } IBitForge(bitForge).transferFrom(_msgSender(), address(this), upgradeFacilityPrice); _swapTokentoETH(upgradeFacilityPrice); currFacility.totalPowerOutput += powerUpgradeAmount; currFacility.level++; lastFacilityUpgradeTimestamp[_msgSender()] = block.timestamp; emit Events.FacilityBought(_msgSender(), currFacility.level, upgradeFacilityPrice); } function claimRewards() external { _updateRewards(_msgSender()); uint256 rewards = playerPendingRewards[_msgSender()]; if (rewards == 0) { revert Errors.NoRewardsPending(); } playerPendingRewards[_msgSender()] = 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 IBitForge(bitForge).mint(_msgSender(), finalRewards); // Handle tier 1 referral address tier1Referrer = referrals[_msgSender()]; if (tier1Referrer != address(0)) { IBitForge(bitForge).mint(tier1Referrer, tier1Bonus); referralBonusPaid[tier1Referrer] += tier1Bonus; } else { IBitForge(bitForge).mint(address(this), tier1Bonus); referralBonusPaid[address(this)] += tier1Bonus; } // Handle tier 2 referral address tier2Referrer = secondTierReferrals[_msgSender()]; if (tier2Referrer != address(0)) { IBitForge(bitForge).mint(tier2Referrer, tier2Bonus); secondTierReferralBonusPaid[tier2Referrer] += tier2Bonus; } else { // No referrers at all, mint to contract IBitForge(bitForge).mint(address(this), tier2Bonus); secondTierReferralBonusPaid[address(this)] += tier2Bonus; } emit Events.RewardsClaimed(_msgSender(), rewards); } function _getFreeStarterMiner(address user) internal { 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); } function _updateCumulativeRewards() internal { if (totalHashrate == 0) { lastRewardBlock = block.number; return; } uint256 currentBlock = lastRewardBlock; uint256 lastBitForgePerBlock = INITIAL_REWARD_PER_BLOCK / (2 ** ((lastRewardBlock - startBlock) / HALVING_INTERVAL)); while (currentBlock < block.number) { uint256 nextHalvingBlock = latestHalvingBlock + HALVING_INTERVAL; uint256 endBlock = (nextHalvingBlock < block.number) ? nextHalvingBlock : block.number; // apply correct emission rate for this segment cumulativeBitForgePerHash += ((lastBitForgePerBlock * (endBlock - currentBlock) * REWARDS_PRECISION) / totalHashrate); // move to next segment currentBlock = endBlock; // if a halving has happened, apply the new rate if (currentBlock == nextHalvingBlock) { lastBitForgePerBlock /= 2; latestHalvingBlock = currentBlock; havingCount++; } } lastRewardBlock = block.number; } function _updateRewards(address player) internal { _updateCumulativeRewards(); playerPendingRewards[player] += (playerHashrate[player] * (cumulativeBitForgePerHash - playerBitForgeDebt[player])) / REWARDS_PRECISION; playerBitForgeDebt[player] = cumulativeBitForgePerHash; } /** * @dev Increase players hashrate. */ function _increaseHashrate(address player, uint256 hashrate) internal { if (!miningHasStarted) { miningHasStarted = true; startBlock = block.number; latestHalvingBlock = 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(_msgSender(), playerHashrate[player], playerPendingRewards[player]); } 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(_msgSender(), playerHashrate[player], playerPendingRewards[player]); } function _swapTokentoETH(uint256 _amount) internal { IBitForge(bitForge).approve(SWAP_ROUTER, _amount); try IV3SwapRouter(SWAP_ROUTER).exactInputSingle( IV3SwapRouter.ExactInputSingleParams({ tokenIn: bitForge, tokenOut: WETH, fee: 10000, recipient: bittoshi, amountIn: _amount, amountOutMinimum: 0, sqrtPriceLimitX96: 0 }) ) {} catch {} } }
// 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 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 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: Unlicense pragma solidity ^0.8.24; interface IBitForge { 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; 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; 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 level, 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 newCost); event JackpotETHSwapped(uint256 amountIn, uint256 amountOut); event MinerPowerConsumptionChanged( uint256 indexed minerIndex, uint256 newPowerConsumption ); }
// 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; /** * @dev Current player's facility. */ struct Facility { uint256 level; uint256 currMiners; uint256 totalPowerOutput; uint256 currPowerOutput; }
// 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":"AlreadyPurchasedInitialFactory","type":"error"},{"inputs":[],"name":"CantBuyNewFacilityYet","type":"error"},{"inputs":[],"name":"FacilityInadequatePowerOutput","type":"error"},{"inputs":[],"name":"GreatDepression","type":"error"},{"inputs":[],"name":"IncorrectValue","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InvalidFee","type":"error"},{"inputs":[],"name":"InvalidMinerIndex","type":"error"},{"inputs":[],"name":"InvalidReferrer","type":"error"},{"inputs":[],"name":"MinerNotInProduction","type":"error"},{"inputs":[],"name":"NeedToInitializeFacility","type":"error"},{"inputs":[],"name":"NoRewardsPending","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":"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":false,"internalType":"uint256","name":"level","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"cost","type":"uint256"}],"name":"FacilityBought","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":"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":"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_REWARD_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_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":"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":"bitForge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bittoshi","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksUntilNextHalving","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnPct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"minerIndex","type":"uint256"}],"name":"buyMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cumulativeBitForgePerHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableUpgradeFacility","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBitForgePerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextHalvingBlock","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":"havingCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialFacilityPower","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":[],"name":"isOpen","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":[],"name":"latestHalvingBlock","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":"miningHasStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"open","outputs":[],"stateMutability":"nonpayable","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":"level","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":"playerBitForgeDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"player","type":"address"}],"name":"playerBitForgePerBlock","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":"playerPendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"powerUpgradeAmount","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":"address","name":"_newAddress","type":"address"}],"name":"setBitForge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"burn","type":"uint256"}],"name":"setBurnPct","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"},{"internalType":"uint256","name":"_initialFacilityPower","type":"uint256"}],"name":"setInitialFacility","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":[{"internalType":"uint256","name":"_cooldown","type":"uint256"},{"internalType":"uint256","name":"_upgradePrice","type":"uint256"},{"internalType":"uint256","name":"_powers","type":"uint256"}],"name":"setUpgradeFacility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_bittoshi","type":"address"}],"name":"setbittoshi","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_upgradeCooldown","type":"uint256"}],"name":"setupgradeCooldown","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":"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":[{"internalType":"uint256","name":"minerIndex","type":"uint256"},{"internalType":"uint256","name":"cost","type":"uint256"},{"internalType":"uint256","name":"power","type":"uint256"},{"internalType":"uint256","name":"hashrate","type":"uint256"},{"internalType":"bool","name":"inProduction","type":"bool"}],"name":"updateMiner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upgradeCooldown","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"upgradeFacility","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upgradeFacilityPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"withdrawBit","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
9c4d535b000000000000000000000000000000000000000000000000000000000000000001000651b027659008baadfa39ab70ce51343eaf6eaa2c466fab1e8a4b9a77ee00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x0001000000000002000f00000000000200000000000103550000000100200190000000310000c13d00000060021002700000057b022001970000008004000039000000400040043f000000040020008c00000e7d0000413d000000000301043b000000e003300270000005890030009c000000540000213d000005be0030009c000000850000a13d000005bf0030009c000000fd0000a13d000005c00030009c000001230000213d000005c70030009c0000032d0000a13d000005c80030009c000004f50000613d000005c90030009c000006e90000613d000005ca0030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b0000002302000039000000000202041a000000080220027000000582032001970000000002000411000000000023004b000004da0000c13d000006120010009c000004770000213d0000000d02000039000000000012041b0000000001000019000015e70001042e000000a001000039000000400010043f0000000001000416000000000001004b00000e7d0000c13d0000057c010000410000000c02000039000000000012041b0000057d010000410000000d02000039000000000012041b0000057e020000410000000e03000039000000000023041b00003840020000390000001e03000039000000000023041b0000001f02000039000000000012041b0000057f010000410000002002000039000000000012041b00000064010000390000002102000039000000000012041b0000002202000039000000000012041b0000000006000411000000000006004b000000670000c13d0000058701000041000000a00010043f000000a40000043f0000058801000041000015e8000104300000058a0030009c000000960000a13d0000058b0030009c0000010e0000a13d0000058c0030009c000001400000213d000005930030009c000003450000a13d000005940030009c0000050e0000613d000005950030009c000006ee0000613d000005960030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000000301000039000006f20000013d000000080160021000000580011001970000002302000039000000000302041a0000058104300197000000000114019f000000000012041b0000000801300270000000000200041400000582051001970000057b0020009c0000057b02008041000000c00120021000000583011001c70000800d020000390000000303000039000005840400004115e615dc0000040f000000010020019000000e7d0000613d0000000701000039000000000201041a000000010220003a000000a70000c13d0000063e01000041000000000010043f0000001101000039000000040010043f0000060b01000041000015e800010430000005d90030009c000000d80000213d000005e60030009c000001530000a13d000005e70030009c000002da0000a13d000005e80030009c000004900000613d000005e90030009c000005c50000613d000005ea0030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000000b01000039000006f20000013d000005a50030009c000000ee0000213d000005b20030009c000001960000a13d000005b30030009c000002ea0000a13d000005b40030009c0000049c0000613d000005b50030009c000005cf0000613d000005b60030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000000501000039000006b10000013d000000000021041b000000800020043f0000016001000039000000400010043f000000a00020043f000000010100008a000000c00010043f0000003201000039000000e00010043f0000000a01000039000001000010043f0000058501000041000001200010043f0000000101000039000001400010043f000000000020043f0000001201000039000000200010043f000d00000002001d0000004002000039000000000100001915e615a90000040f0000000d04000029000000000041041b0000000102100039000000010300008a000000000032041b00000002021000390000003203000039000000000032041b00000003021000390000000a03000039000000000032041b00000004021000390000058503000041000000000032041b0000000501100039000000000301041a000006440230019700000001022001bf000000000021041b0000014000000443000001600040044300000020010000390000010000100443000000010100003900000120001004430000058601000041000015e70001042e000005da0030009c000001a10000a13d000005db0030009c000002f50000a13d000005dc0030009c000004b00000613d000005dd0030009c000005d40000613d000005de0030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001001000039000007010000013d000005a60030009c000001ac0000a13d000005a70030009c000003120000a13d000005a80030009c000004d30000613d000005a90030009c000005e90000613d000005aa0030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000001e01000039000006f20000013d000005cd0030009c000001c30000a13d000005ce0030009c0000031b0000a13d000005cf0030009c000004df0000613d000005d00030009c000006580000613d000005d10030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000061f01000041000000800010043f000005f201000041000015e70001042e000005990030009c000001ce0000a13d0000059a0030009c000003240000a13d0000059b0030009c000004eb0000613d0000059c0030009c0000068c0000613d0000059d0030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000000a01000039000000000101041a000000ff00100190000007380000c13d0000060201000041000000800010043f0000060301000041000015e800010430000005c10030009c0000036e0000a13d000005c20030009c0000051e0000613d000005c30030009c000006f60000613d000005c40030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000d00000001001d000005820010009c00000e7d0000213d0000000901000039000000000201041a000000000002004b0000000001000019000007ad0000c13d00000000001404350000057b0040009c0000057b040080410000004001400210000005f7011001c7000015e70001042e0000058d0030009c000003910000a13d0000058e0030009c0000052a0000613d0000058f0030009c000007090000613d000005900030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d15e6128f0000040f0000002301000039000000000201041a000006440220019700000001022001bf000000000021041b0000000001000019000015e70001042e000005ed0030009c000001db0000213d000005f00030009c000003ac0000613d000005f10030009c00000e7d0000c13d000000640020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000402100370000000000202043b000005820020009c00000e7d0000213d0000002403100370000000000303043b000900000003001d0000004401100370000000000101043b000d00000001001d000000000020043f0000001301000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000201043b0000060501000041000000040010043f000c00000002001d000000000020043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000606011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000064502100167000000000202041a000000000002004b0000096d0000c13d000000000201041a000000000002004b0000000002000039000000010200c0390000096e0000613d0000000103100039000000000303041a000000000003004b0000096e0000613d0000000201100039000000000101041a000000000001004b000000030200003900000002020060390000096e0000013d000005b90030009c000002240000213d000005bc0030009c000003b30000613d000005bd0030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000002001000039000006f20000013d000005e10030009c0000022f0000213d000005e40030009c000003d20000613d000005e50030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d000000000100041a000004ac0000013d000005ad0030009c000002660000213d000005b00030009c000003df0000613d000005b10030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000d00000001001d000005820010009c00000e7d0000213d15e6128f0000040f000000000100041a0000061a011001970000000d011001af000000000010041b0000000001000019000015e70001042e000005d40030009c0000027f0000213d000005d70030009c000004160000613d000005d80030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000002301000039000006b10000013d000005a00030009c0000029a0000213d000005a30030009c000004670000613d000005a40030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000061101000041000000800010043f000005f201000041000015e70001042e000005ee0030009c000003e40000613d000005ef0030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000002302000039000000000202041a000000080220027000000582032001970000000002000411000000000023004b000004da0000c13d0000000102000039000000000202041a000000000300041a0000060e04000041000000800040043f0000000401100370000000000101043b0000058202200197000000840020043f000000a40010043f000000000100041400000582023001970000057b0010009c0000057b01008041000000c0011002100000063f011001c715e615dc0000040f00000060031002700000057b03300197000000200030008c000000200a000039000000000a0340190000001f05a0018f0000002006a0019000000080046001bf0000020b0000613d0000008007000039000000000801034f000000008908043c0000000007970436000000000047004b000002070000c13d000000000005004b000002180000613d000000000661034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f000000000054043500000001002001900000074c0000613d000000800100003900000000020a0019000d0000000a001d15e6126f0000040f0000000d0100002900000080021001bf000000800100003915e612810000040f0000000001000019000015e70001042e000005ba0030009c000003f60000613d000005bb0030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000061201000041000000800010043f000005f201000041000015e70001042e000005e20030009c000003fb0000613d000005e30030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000800000001001d000005820010009c00000e7d0000213d0000000501000039000000000101041a000000ff00100190000004020000613d0000000901000039000000000101041a000900000001001d000000000001004b0000081a0000c13d0000000801000029000000000010043f0000001001000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000201043b0000000c01000039000000000101041a000006120010009c0000007f0000213d0000000d03000039000000000303041a0000061201100099000000000131004b0000007f0000413d000000000202041a000002620000613d0000064503100129000000000023004b0000078d0000413d00000000022100a9000000400100043d000006120220012a000004040000013d000005ae0030009c0000040a0000613d000005af0030009c00000e7d0000c13d000000640020008c00000e7d0000413d0000000001000416000000000001004b00000e7d0000c13d15e6128f0000040f00000000010003670000000402100370000000000202043b0000001e03000039000000000023041b0000002402100370000000000202043b0000002003000039000000000023041b0000004401100370000000000101043b0000002202000039000000000012041b0000000001000019000015e70001042e000005d50030009c0000047b0000613d000005d60030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001301000039000000200010043f0000004002000039000000000100001915e615a90000040f15e615840000040f000000400200043d00000000001204350000057b0020009c0000057b020080410000004001200210000005f7011001c7000015e70001042e000005a10030009c000004800000613d000005a20030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000001000416000000000001004b00000e7d0000c13d0000000001000411000000000010043f0000001301000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d00000004020000390000000002200367000000000202043b000d00000002001d000000000101043b0000060502000041000000040020043f000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000606011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000201043b00000004010000390000000001100367000000000101043b000006070010009c00000f1e0000613d000000000001004b0000000d0400002900000607040060410000064503200167000000000303041a000000000003004b000008db0000c13d000000000302041a000000000043004b00000ad10000613d0000000103200039000000000303041a000000000043004b00000ad10000613d0000000202200039000000000202041a000000000042004b000008ea0000c13d00000ad10000013d000005eb0030009c0000052f0000613d000005ec0030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001301000039000007010000013d000005b70030009c0000053b0000613d000005b80030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000002301000039000000000101041a0000000801100270000004ac0000013d000005df0030009c000005480000613d000005e00030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d000000000100041115e612a10000040f0000000001000411000000000010043f0000001001000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000000000001004b0000076e0000c13d000000400100043d0000063c0200004100000a9a0000013d000005ab0030009c000005570000613d000005ac0030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000000801000039000006f20000013d000005d20030009c000006190000613d000005d30030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000000901000039000006f20000013d0000059e0030009c000006350000613d0000059f0030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000000101000039000004ab0000013d000005cb0030009c000006910000613d000005cc0030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b0000002302000039000000000202041a000000080220027000000582032001970000000002000411000000000023004b000004da0000c13d000006230010009c000004770000813d0000000c02000039000000000012041b0000000001000019000015e70001042e000005970030009c000006ad0000613d000005980030009c00000e7d0000c13d000000440020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000402100370000000000202043b000005820020009c00000e7d0000213d0000002401100370000000000101043b000d00000001001d000000000020043f0000001b01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a0000000d0020006b00000e7d0000813d0000000d0200002915e612540000040f0000000302200210000000000101041a000000000121022f0000058201100197000000ff0020008c0000000001002019000002930000013d000005c50030009c000006b80000613d000005c60030009c00000e7d0000c13d0000000001000416000000000001004b00000e7d0000c13d0000000501000039000000000101041a000000ff00100190000004020000613d0000000201000039000000000101041a000d00000001001d0000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000118b0000613d000000000101043b0000000d0210006c0000007f0000413d0000061e0020009c0000007f0000213d000000400100043d0000057b022001970000061f0220012a000006200220027f000004040000013d000005910030009c000006e40000613d000005920030009c00000e7d0000c13d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000601043b000005820060009c00000e7d0000213d0000002301000039000000000201041a000000080320027000000582033001970000000005000411000000000053004b0000071e0000c13d000000000006004b000008c90000c13d0000058701000041000000800010043f000000840000043f000005f401000041000015e8000104300000000001000416000000000001004b00000e7d0000c13d0000062001000041000000800010043f000005f201000041000015e70001042e000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001801000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d0000001e02000039000000000202041a000000000101043b000000000101041a000000000012001a0000007f0000413d0000000001120019000000800010043f000005f201000041000015e70001042e000000240020008c00000e7d0000413d0000000001000416000000000001004b00000e7d0000c13d15e6128f0000040f00000004010000390000000001100367000000000101043b0000001e02000039000000000012041b0000000001000019000015e70001042e0000000001000416000000000001004b00000e7d0000c13d0000000e01000039000006f20000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000201043b000000000002004b0000000001000039000000010100c039000d00000002001d000000000012004b00000e7d0000c13d15e6128f0000040f0000000a01000039000000000201041a0000064402200197000006e00000013d0000000001000416000000000001004b00000e7d0000c13d0000000c01000039000006f20000013d0000000001000416000000000001004b00000e7d0000c13d0000000201000039000000000101041a000000000001004b000007230000c13d0000008001000039000000000200001900000000002104350000057b0010009c0000057b010080410000004001100210000005f7011001c7000015e70001042e000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001901000039000004a70000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001b01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000301041a000000400200043d000c00000002001d000b00000003001d0000000002320436000d00000002001d000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000614011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d0000000b05000029000000000005004b0000000d0600002900000000020600190000044b0000613d000000000101043b00000000030000190000000002060019000000000401041a0000058204400197000000000242043600000001011000390000000103300039000000000053004b000004440000413d0000000c0300002900000000013200490000001f0110003900000646021001970000000001320019000000000021004b00000000020000390000000102004039000005fd0010009c000006a70000213d0000000100200190000006a70000c13d000000400010043f00000020020000390000000002210436000000000303043300000000003204350000004002100039000000000003004b00000a450000613d00000000040000190000000065060434000005820550019700000000025204360000000104400039000000000034004b000004600000413d00000a450000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b0000002302000039000000000202041a000000080220027000000582032001970000000002000411000000000023004b000004da0000c13d000006120010009c0000076a0000a13d0000062401000041000000800010043f0000060301000041000015e8000104300000000001000416000000000001004b00000e7d0000c13d0000000201000039000006f20000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001601000039000000200010043f0000004002000039000000000100001915e615a90000040f000006b10000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000000f01000039000007010000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001a01000039000000200010043f0000004002000039000000000100001915e615a90000040f000000000101041a0000058201100197000000800010043f000005f201000041000015e70001042e0000000001000416000000000001004b00000e7d0000c13d0000002301000039000000000101041a000000080110027000000582021001970000000001000411000000000012004b000007190000c13d000006360100004100000000001004430000000001000410000000040010044300000000010004140000057b0010009c0000057b01008041000000c00110021000000626011001c70000800a0200003915e615e10000040f00000001002001900000118b0000613d0000000102000039000000000202041a0000058204200197000000000301043b00000000010004140000057b0010009c0000057b01008041000000c001100210000000000003004b0000085e0000c13d0000000002040019000008610000013d0000000001000416000000000001004b00000e7d0000c13d0000061701000041000000800010043f000005f201000041000015e70001042e000005f301000041000000800010043f000000840020043f000005f401000041000015e800010430000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001101000039000007010000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000000000010043f00000012010000390000063e0000013d0000000001000416000000000001004b00000e7d0000c13d0000002301000039000000000201041a000000080320027000000582033001970000000005000411000000000053004b0000071e0000c13d0000058102200197000000000021041b00000000010004140000057b0010009c0000057b01008041000000c00110021000000583011001c70000800d0200003900000003030000390000058404000041000000000600001915e615dc0000040f000000010020019000000e7d0000613d000008d90000013d0000000001000416000000000001004b00000e7d0000c13d0000000001000412000f00000001001d000e00000000003d0000800501000039000000440300003900000000040004150000000f0440008a0000000504400210000005f50200004115e615be0000040f000000800010043f000005f201000041000015e70001042e000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001d01000039000007010000013d0000000001000416000000000001004b00000e7d0000c13d0000000d01000039000006f20000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001c01000039000007010000013d0000000001000416000000000001004b00000e7d0000c13d0000000201000039000000000101041a000000000001004b0000000001000019000007060000613d0000000301000039000000000101041a0000061c0110009c0000007f0000813d000007060000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000d00000001001d000005820010009c00000e7d0000213d15e6128f0000040f0000000101000039000000000201041a0000061a02200197000006e00000013d000000840020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000004402100370000000000202043b000c00000002001d0000002402100370000000000202043b000d00000002001d0000000402100370000000000202043b000b00000002001d0000006401100370000000000201043b000000000002004b0000000001000039000000010100c039000a00000002001d000000000012004b00000e7d0000c13d0000002301000039000000000101041a000000080110027000000582021001970000000001000411000000000012004b000007190000c13d0000000702000039000000000102041a000000010110003a0000007f0000613d000000000012041b0000014002000039000000400020043f000000800010043f000000a00000043f0000000b02000029000000c00020043f0000000d02000029000000e00020043f0000000c02000029000001000020043f0000000a02000029000001200020043f000000000010043f0000001201000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000800200043d000000000021041b0000000102100039000000a00300043d000000000032041b0000000202100039000000c00300043d000000000032041b0000000302100039000000e00300043d000000000032041b0000000402100039000001000300043d000000000032041b0000000501100039000000000301041a0000064402300197000001200300043d000000000003004b000000010220c1bf000000000021041b0000000701000039000000000501041a000000400100043d00000060021000390000000a03000029000000000032043500000040021000390000000c03000029000000000032043500000020021000390000000d0300002900000000003204350000000b0200002900000000002104350000057b0010009c0000057b01008041000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f00000618011001c70000800d020000390000000203000039000006190400004115e615dc0000040f000000010020019000000e7d0000613d000008d90000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000000000010043f0000001701000039000007010000013d0000000001000416000000000001004b00000e7d0000c13d0000002101000039000006f20000013d000000240020008c00000e7d0000413d0000000401100370000000000101043b000d00000001001d000005820010009c00000e7d0000213d0000002301000039000000000101041a000000ff00100190000007910000c13d0000063301000041000000800010043f0000002001000039000000840010043f0000000801000039000000a40010043f0000063401000041000000c40010043f0000063501000041000015e800010430000000440020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000402100370000000000202043b000d00000002001d0000002401100370000000000201043b000000000002004b0000000001000039000000010100c039000c00000002001d000000000012004b00000e7d0000c13d0000002301000039000000000101041a000000080110027000000582021001970000000001000411000000000012004b000007190000c13d000005f501000041000000000010044300000000010004120000000400100443000000240000044300000000010004140000057b0010009c0000057b01008041000000c00110021000000613011001c7000080050200003915e615e10000040f00000001002001900000118b0000613d000000000101043b0000000d02000029000000000012004b000006160000413d0000000701000039000000000101041a000000000012004b00000aa00000a13d000000400100043d000006160200004100000a9a0000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001501000039000000200010043f0000004002000039000000000100001915e615a90000040f0000000302100039000000000202041a0000000203100039000000000303041a0000000104100039000000000404041a000000000101041a000000800010043f000000a00040043f000000c00030043f000000e00020043f0000062d01000041000015e70001042e000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000000000010043f0000001401000039000000200010043f0000004002000039000000000100001915e615a90000040f0000000502100039000000000202041a0000000403100039000000000303041a0000000304100039000000000404041a0000000205100039000000000505041a0000000106100039000000000606041a000000000101041a000000800010043f000000a00060043f000000c00050043f000000e00040043f000001000030043f000000ff002001900000000001000039000000010100c039000001200010043f0000060401000041000015e70001042e000000440020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000002402100370000000000402043b0000000401100370000000000301043b0000002301000039000000000101041a000000080110027000000582021001970000000001000411000000000012004b000007190000c13d000c00000004001d000d00000003001d000000000030043f0000001701000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000c02000029000000000021041b000000400100043d00000000002104350000057b0010009c0000057b01008041000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f00000614011001c70000800d0200003900000002030000390000062c040000410000000d0500002915e615dc0000040f000000010020019000000e7d0000613d000008d90000013d0000000001000416000000000001004b00000e7d0000c13d0000002201000039000006f20000013d000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000000000010043f0000001201000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000400400043d000006090040009c000007de0000a13d0000063e01000041000000000010043f0000004101000039000000040010043f0000060b01000041000015e8000104300000000001000416000000000001004b00000e7d0000c13d0000000a01000039000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f000005f201000041000015e70001042e000000a40020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000008401100370000000000201043b000000000002004b0000000001000039000000010100c039000d00000002001d000000000012004b00000e7d0000c13d15e6128f0000040f0000000001000367000c0000000103530000000401100370000000000101043b000000000010043f0000001201000039000000200010043f0000004002000039000000000100001915e615a90000040f0000000c0400035f0000002402400370000000000202043b0000000403100039000000000023041b0000004402400370000000000202043b0000000303100039000000000023041b0000006402400370000000000202043b0000000203100039000000000023041b0000000501100039000000000301041a00000644023001970000000d022001af000000000021041b0000000001000019000015e70001042e0000000001000416000000000001004b00000e7d0000c13d0000001f01000039000006f20000013d0000000001000416000000000001004b00000e7d0000c13d0000000701000039000006f20000013d0000000001000416000000000001004b00000e7d0000c13d0000000401000039000000000101041a000000800010043f000005f201000041000015e70001042e000000240020008c00000e7d0000413d0000000002000416000000000002004b00000e7d0000c13d0000000401100370000000000101043b000005820010009c00000e7d0000213d000000000010043f0000001801000039000000200010043f0000004002000039000000000100001915e615a90000040f000000000101041a000000800010043f000005f201000041000015e70001042e0000000001000416000000000001004b00000e7d0000c13d000000000102001915e612480000040f000c00000001001d000d00000002001d15e6128f0000040f0000001f010000390000000c02000029000000000021041b00000021010000390000000d02000029000000000021041b0000000001000019000015e70001042e000005f302000041000000800020043f000000840010043f000005f401000041000015e800010430000005f301000041000000800010043f000000840050043f000005f401000041000015e8000104300000000301000039000000000101041a0000061c0110009c0000007f0000813d000d00000001001d0000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000118b0000613d000000000101043b0000000d0210006b0000007f0000413d000000400100043d000004040000013d0000000001000411000000000010043f0000001601000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000000ff00100190000008900000c13d000000400100043d000006010200004100000a9a0000013d0000001f0530018f000005fc06300198000000400200043d0000000004620019000007570000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000007530000c13d000000000005004b000007640000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000057b0020009c0000057b020080410000004002200210000000000112019f000015e8000104300000000e02000039000000000012041b0000000001000019000015e70001042e000d00000001001d0000000001000411000000000010043f0000001001000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000001041b0000000c01000039000000000101041a000000000001004b0000000d04000029000007860000613d0000064502100129000000000042004b0000078d0000413d0000000d02000039000000000202041a000000000002004b000008ed0000613d0000064503200129000000000043004b000008ed0000813d0000063d01000041000000000010043f0000062201000041000015e8000104300000001f01000039000000000101041a0000000002000416000000000012004b000008c50000c13d0000000001000411000000000010043f0000001601000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000000ff0010019000000a980000c13d00000000010004110000000d0010006b00000b530000c13d000000400100043d000006320200004100000a9a0000013d000b00000002001d0000000201000039000000000101041a000c00000001001d0000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000118b0000613d000000000101043b0000000c0110006c0000007f0000413d0000061e0010009c0000007f0000213d000c00000001001d0000000d01000029000000000010043f0000000f01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d0000000c020000290000057b022001970000061f0220012a000006200220027f000000000101043b000000000301041a00000000012300a9000000000003004b000007db0000613d00000000033100d9000000000023004b00000c260000c13d0000000b011000fa000000400400043d0000013a0000013d000000000101043b000000c002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000a00000003001d00000000002304350000000202100039000000000202041a0000004003400039000900000003001d00000000002304350000000302100039000000000202041a0000006003400039000b00000003001d00000000002304350000000402100039000000000202041a0000008003400039000c00000003001d0000000000230435000800000004001d000000a0024000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000d00000002001d00000000001204350000000001000411000000000010043f0000001501000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000400300043d000000000101043b000700000001001d0000000d010000290000000001010433000000000001004b00000a4e0000c13d0000062b0100004100000000001304350000057b0030009c0000057b03008041000000400130021000000600011001c7000015e8000104300000000201000039000000000101041a0000000802000039000000000202041a000000000112004b0000007f0000413d0000061e0010009c0000007f0000213d000b00000002001d0000000302000039000000000202041a000c00000002001d0000000b02000039000000000202041a000d00000002001d0000057b011001970000061f0110012a000a0620001002870000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000118b0000613d000000000101043b0000000b04000029000000000014004b0000000d070000290000000c0800002900000bd70000813d0000061c0380009c0000000a090000290000007f0000813d000000000013004b00000000020100190000000002034019000000000442004b0000007f0000413d000000000009004b000008520000613d00000000059400a900000000069500d9000000000046004b0000007f0000c13d000000000005004b000008520000613d00000612045000d100000000055400d9000006120050009c000008530000613d0000007f0000013d000000000400001900000009044000fa000000000074001a0000007f0000413d000d00000074001d000000000013004b000000000802a019000c00000008001d000000010990a270000a00000009001d000b00000002001d0000082c0000013d00000583011001c70000800902000039000000000500001915e615dc0000040f00000060031002700000057b033001980000086a0000c13d0000000100200190000008d90000c13d000000400100043d000006390200004100000a9a0000013d0000001f0430003900000637044001970000003f044000390000063804400197000000400500043d0000000004450019000000000054004b00000000060000390000000106004039000005fd0040009c000006a70000213d0000000100600190000006a70000c13d000000400040043f0000001f0430018f0000000006350436000005fc053001980000000003560019000008820000613d000000000701034f000000007807043c0000000006860436000000000036004b0000087e0000c13d000000000004004b000008650000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000130435000008650000013d0000000001000411000000000010043f0000001501000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000d00000001001d0000001801000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000c00000001001d000005f801000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000118b0000613d000000000101043b000b00000001001d0000000c0110006c0000007f0000413d000000400200043d000c00000002001d0000001e02000039000000000202041a000000000021004b00000c2a0000813d000005ff010000410000000c0200002900000cc30000013d0000062e01000041000000800010043f0000060301000041000015e800010430000005810220019700000008036002100000058003300197000000000232019f000000000021041b00000000010004140000057b0010009c0000057b01008041000000c00110021000000583011001c70000800d020000390000000303000039000005840400004115e615dc0000040f000000010020019000000e7d0000613d0000000001000019000015e70001042e000000200020043f000000000040043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000000000001004b00000ace0000c13d000000400100043d000006080200004100000a9a0000013d00000000014100a9000c0612001001320000000c0140006c0000007f0000413d00000000024200a9000a0612002001320000000a0110006c000b00000001001d0000007f0000413d000000000100041a000006250200004100000000002004430000058201100197000900000001001d000000040010044300000000010004140000057b0010009c0000057b01008041000000c00110021000000626011001c7000080020200003915e615e10000040f00000001002001900000118b0000613d000000000101043b000000000001004b00000e7d0000613d000000400300043d00000024013000390000000b0200002900000000002104350000063a01000041000000000013043500000000010004110000058201100197000000040230003900000000001204350000057b0030009c000b00000003001d0000057b010000410000000001034019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000060f011001c7000000090200002915e615dc0000040f000000010020019000000d230000613d0000000b01000029000005fd0010009c000006a70000213d0000000b01000029000000400010043f0000000001000411000000000010043f0000001901000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000000000200041a000006250300004100000000003004430000058202200197000b00000002001d0000000400200443000905820010019c00000e710000c13d00000000010004140000057b0010009c0000057b01008041000000c00110021000000626011001c7000080020200003915e615e10000040f00000001002001900000118b0000613d000000000101043b000000000001004b00000e7d0000613d000000400300043d00000024013000390000000c0200002900000000002104350000063a01000041000000000013043500000000010004100000058201100197000000040230003900000000001204350000057b0030009c000900000003001d0000057b010000410000000001034019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000060f011001c70000000b0200002915e615dc0000040f000000010020019000000f220000613d0000000901000029000005fd0010009c000006a70000213d0000000901000029000000400010043f0000000001000410000000000010043f0000001c01000039000000200010043f000000000100041400000ea10000013d0000000102200270000000090520006c00000a160000a13d0000000d0050006c0000000d05008029000006410050009c000006a70000813d00000005015002100000003f021000390000064202200197000000400400043d0000000002240019000000000042004b00000000030000390000000103004039000005fd0020009c000006a70000213d0000000100300190000006a70000c13d000000400020043f000800000004001d0000000002540436000700000002001d000600000005001d000000000005004b00000a1d0000613d00000000020000190000000705000029000000400300043d000006090030009c000006a70000213d000000c004300039000000400040043f000000a0043000390000000000040435000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000452001900000000003404350000002002200039000000000012004b000009890000413d000d00000000001d0000060501000041000000040010043f0000000c01000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000606011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d0000000d03000029000b00090030002d000000000101043b0000000b01100029000000000101041a000a00000001001d0000060501000041000000040010043f0000000c01000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000606011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000201043b0000064501200167000000000101041a000000000001004b000009c70000613d00000001011002700000000b04000029000009d60000013d000000000102041a000000000001004b0000000001000039000000010100c0390000000b04000029000009d60000613d0000000103200039000000000303041a000000000003004b000009d60000613d0000000201200039000000000101041a000000000001004b00000003010000390000000201006039000000000014004b00000e6e0000813d0000000a01000029000006070010009c0000000001006019000000000010043f0000001401000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000400200043d000006090020009c000000080500002900000006060000290000000707000029000006a70000213d000000000101043b000000c003200039000000400030043f000000000301041a00000000033204360000000104100039000000000404041a00000000004304350000000203100039000000000303041a000000400420003900000000003404350000000303100039000000000303041a000000600420003900000000003404350000000403100039000000000303041a00000080042000390000000000340435000000a0032000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000000000013043500000000010504330000000d03000029000000000031004b00000e140000a13d0000000501300210000000000171001900000000002104350000000001050433000000000031004b00000e140000a13d000d00010030003d0000000d0060006b0000099f0000413d00000a1d0000013d000000400200043d000006400020009c000006a70000213d0000002001200039000000400010043f000800000002001d0000000000020435000000400100043d000000200200003900000000022104360000000803000029000000000303043300000000003204350000004002100039000000000003004b00000a450000613d00000000040000190000000808000029000000200880003900000000050804330000000076050434000000000662043600000000070704330000000000760435000000400650003900000000060604330000004007200039000000000067043500000060065000390000000006060433000000600720003900000000006704350000008006500039000000000606043300000080072000390000000000670435000000a0055000390000000005050433000000000005004b0000000005000039000000010500c039000000a0062000390000000000560435000000c0022000390000000104400039000000000034004b00000a280000413d00000000021200490000057b0020009c0000057b0200804100000060022002100000057b0010009c0000057b010080410000004001100210000000000112019f000015e70001042e000000000200041a0000060a0100004100000000001304350000000401300039000000000403001900000000030004110000000000310435000600000004001d0000057b0040009c0000057b010000410000000001044019000000400110021000000000030004140000057b0030009c0000057b03008041000000c003300210000000000113019f0000060b011001c70000058202200197000500000002001d15e615e10000040f00000060031002700000057b03300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000060b000029000000060570002900000a730000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000a6f0000c13d000000000006004b00000a800000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000ac20000613d0000001f01400039000000600110018f0000000002b10019000000000012004b00000000010000390000000101004039000400000002001d000005fd0020009c000006a70000213d0000000100100190000006a70000c13d0000000401000029000000400010043f000000200030008c00000e7d0000413d0000000c01000029000000000101043300000000020b0433000000000012004b00000cb30000813d0000062a0100004100000cc20000013d000000400100043d0000062f0200004100000000002104350000057b0010009c0000057b01008041000000400110021000000600011001c7000015e800010430000000000020043f0000001201000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000501100039000000000201041a00000644022001970000000c03000029000000000232019f000000000021041b000000400100043d00000000003104350000057b0010009c0000057b01008041000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f00000614011001c70000800d0200003900000002030000390000061504000041000006870000013d0000001f0530018f000005fc06300198000000400200043d0000000004620019000007570000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000ac90000c13d000007570000013d00000004010000390000000001100367000000000101043b000000000010043f0000001401000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000400200043d000d00000002001d000006090020009c000006a70000213d000000000101043b0000000d05000029000000c002500039000000400020043f000000000201041a00000000032504360000000104100039000000000404041a00000000004304350000000203100039000000000303041a0000004004500039000b00000004001d00000000003404350000000303100039000000000303041a0000006004500039000c00000004001d00000000003404350000000403100039000000000303041a00000080045000390000000000340435000000a0035000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c0390000000000130435000000000020043f0000001701000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000900000001001d000000000100041a000000400400043d000a00000004001d0000060a0200004100000000002404350000000402400039000000000300041000000000003204350000057b0040009c0000057b020000410000000002044019000000400220021000000000030004140000057b0030009c0000057b03008041000000c003300210000000000323019f00000582021001970000060b013001c715e615e10000040f00000060031002700000057b03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000a0b0000290000000a0570002900000b320000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00000b2e0000c13d000000000006004b00000b3f0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000c1a0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000005fd0010009c000006a70000213d0000000100200190000006a70000c13d000000400010043f000000200030008c00000e7d0000413d00000000020b0433000000090020006b00000e1a0000a13d000006100200004100000a9a0000013d000000000010043f0000001601000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a000006440220019700000001022001bf000000000021041b0000000d0000006b00000cc90000c13d0000000001000411000000000010043f0000001501000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d0000002102000039000000000202041a000000000101043b0000000201100039000000000021041b000005f501000041000000000010044300000000010004120000000400100443000000240000044300000000010004140000057b0010009c0000057b01008041000000c00110021000000613011001c7000080050200003915e615e10000040f00000001002001900000118b0000613d000000000101043b000000000010043f0000001201000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000400200043d000d00000002001d000006090020009c000006a70000213d000000000101043b0000000d04000029000000c002400039000000400020043f000000000201041a00000000032404360000000102100039000000000202041a000b00000003001d00000000002304350000000202100039000000000202041a0000004003400039000a00000003001d00000000002304350000000302100039000000000202041a0000006003400039000c00000003001d00000000002304350000000402100039000000000202041a0000008003400039000800000003001d0000000000230435000000a0024000390000000501100039000000000101041a000000ff001001900000000001000039000000010100c039000900000002001d00000000001204350000000001000411000000000010043f0000001501000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d0000000c020000290000000002020433000000000101043b000700000001001d0000000301100039000600000001001d000000000101041a000000000012001a0000007f0000413d000000000112001900000007020000290000000202200039000000000202041a000000000021004b00000ef60000a13d000000400100043d000006290200004100000a9a0000013d00000008010000290000058201100197000000000010043f0000001001000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000c00000001001d0000000f01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000b00000001001d0000001101000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a0000000d0210006b0000007f0000413d0000000b012000b90000000b0000006b00000c0b0000613d0000000b031000fa000000000023004b0000007f0000c13d000006120210012a0000000c0020002a0000007f0000413d0000000c01000039000000000101041a000006120010009c0000007f0000213d0000000d03000039000000000303041a0000061201100099000000000131004b0000007f0000413d0000000c022000290000025f0000c13d000002620000013d0000001f0530018f000005fc06300198000000400200043d0000000004620019000007570000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000c210000c13d000007570000013d0000062101000041000000000010043f0000062201000041000015e8000104300000002001000039000000000101041a0000000c040000290000004402400039000000000300041a00000000001204350000000001000410000005820110019700000024024000390000000000120435000005fa01000041000000000014043500000000010004110000058201100197000000040240003900000000001204350000057b0040009c0000057b010000410000000001044019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000058202300197000005fb011001c715e615dc0000040f00000060031002700000057b03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000c0570002900000c550000613d000000000801034f0000000c09000029000000008a08043c0000000009a90436000000000059004b00000c510000c13d000000000006004b00000c620000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000d3f0000613d0000001f01400039000000600210018f0000000c01200029000000000021004b00000000020000390000000102004039000005fd0010009c000006a70000213d0000000100200190000006a70000c13d000000400010043f000000200030008c00000e7d0000413d0000000c010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b00000e7d0000c13d0000002001000039000000000101041a15e613670000040f0000002201000039000000000201041a0000000d010000290000000201100039000000000301041a000000000023001a0000007f0000413d0000000002230019000000000021041b0000000d01000029000000000101041a000000010110003a0000007f0000613d0000000d02000029000000000012041b0000000001000411000000000010043f0000001801000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000b02000029000000000021041b0000000d01000029000000000101041a0000002002000039000000000202041a000000400300043d0000002004300039000000000024043500000000001304350000057b0030009c0000057b03008041000000400130021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f000005f6011001c70000800d020000390000000203000039000005fe04000041000000000500041115e615dc0000040f000000010020019000000e7d0000613d000008d90000013d0000000b02000029000000000202043300000007030000290000000303300039000600000003001d000000000303041a000000000032001a0000007f0000413d000000000232001900000007030000290000000203300039000000000303041a000000000032004b00000d4b0000a13d0000062901000041000000040200002900000000001204350000057b0020009c0000057b02008041000000400120021000000600011001c7000015e8000104300000001901000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a0000061a022001970000000d03000029000000000232019f000000000021041b000000000030043f0000001b01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a000c00000002001d000005fd0020009c000006a70000213d0000000c020000290000000102200039000000000021041b000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000614011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000c01100029000000000201041a0000061a022001970000000003000411000000000232019f000000000021041b0000000d01000029000000000010043f0000001901000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000d05820010019c00000b660000613d0000000001000411000000000010043f0000001a01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a0000061a022001970000000d022001af000000000021041b00000b660000013d00000060061002700000001f0460018f000005fc05600198000000400200043d000000000352001900000d2f0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b00000d2b0000c13d0000057b06600197000000000004004b00000d3d0000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000006001600210000007650000013d0000001f0530018f000005fc06300198000000400200043d0000000004620019000007570000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000d460000c13d000007570000013d0000000403000029000000440230003900000000001204350000000001000410000005820110019700000024023000390000000000120435000005fa01000041000000000013043500000000010004110000058201100197000000040230003900000000001204350000057b0030009c0000057b010000410000000001034019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f000005fb011001c7000000050200002915e615dc0000040f00000060031002700000057b03300197000000200030008c000000200400003900000000040340190000001f0640018f0000002007400190000000040570002900000d730000613d000000000801034f0000000409000029000000008a08043c0000000009a90436000000000059004b00000d6f0000c13d000000000006004b00000d800000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000000010020019000000e080000613d0000001f01400039000000600110018f0000000401100029000005fd0010009c000006a70000213d000000400010043f000000200030008c00000e7d0000413d00000004010000290000000001010433000000000001004b0000000002000039000000010200c039000000000021004b00000e7d0000c13d0000000c010000290000000001010433000500000001001d0000000e01000039000000000101041a000400000001001d000000000001004b00000d9d0000613d000000010100008a00000004011000fa000000050010006c0000078d0000413d000000000100041a000006250200004100000000002004430000058201100197000300000001001d000000040010044300000000010004140000057b0010009c0000057b01008041000000c00110021000000626011001c7000080020200003915e615e10000040f00000001002001900000118b0000613d000000000101043b000000000001004b00000e7d0000613d000000040200002900000005012000b9000006120210012a000000400300043d000006270100004100000000001304350000000401300039000400000002001d00000000002104350000057b0030009c000500000003001d0000057b010000410000000001034019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000060b011001c7000000030200002915e615dc0000040f000000010020019000000f3c0000613d0000000501000029000005fd0010009c000006a70000213d0000000501000029000000400010043f0000000c010000290000000001010433000000040110006c0000007f0000413d15e613670000040f0000000601000039000000000101041a000500010010003e0000007f0000613d00000006010000390000000502000029000000000021041b0000000a0100002900000000002104350000000001000411000000000010043f0000001301000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000060502000041000000040020043f000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000606011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000400000001001d0000000501000029000006070010009c00000f1e0000613d00000004020000290000064501200167000200000001001d000000000101041a000000200020043f000300000001001d000000000001004b000011d80000c13d0000000401000029000000000101041a000000000001004b0000118c0000c13d00000005010000290000000402000029000011f10000013d0000001f0530018f000005fc06300198000000400200043d0000000004620019000007570000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000e0f0000c13d000007570000013d0000063e01000041000000000010043f0000003201000039000000040010043f0000060b01000041000015e8000104300000000001000411000000000010043f0000001501000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000102100039000000000302041a000000000003004b0000007f0000613d000000010330008a000000000032041b0000000301100039000000000201041a0000000c030000290000000003030433000000000232004b0000007f0000413d000000000021041b0000000001000411000000000010043f0000001301000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d00000004020000390000000002200367000000000202043b000c00000002001d000000000101043b0000060502000041000000040020043f000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000606011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d00000004020000390000000002200367000000000202043b000000000002004b0000000c020000290000060702006041000c00000002001d000000000201043b000a00000002001d0000064501200167000600000001001d000000000101041a000700000001001d000000000001004b00000f490000c13d0000000a040000290000000201400039000800000001001d000000000101041a0000000102400039000000000302041a000000000404041a0000000c0040006c00000f7a0000c13d0000000a04000029000000000034041b00000f7c0000013d000000400100043d000006430200004100000a9a0000013d00000000010004140000057b0010009c0000057b01008041000000c00110021000000626011001c7000080020200003915e615e10000040f00000001002001900000118b0000613d000000000101043b000000000001004b00000e7f0000c13d0000000001000019000015e800010430000000400300043d00000024013000390000000c0200002900000000002104350000063a0100004100000000001304350000000401300039000000090200002900000000002104350000057b0030009c000800000003001d0000057b010000410000000001034019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000060f011001c70000000b0200002915e615dc0000040f000000010020019000000f2f0000613d0000000801000029000005fd0010009c000006a70000213d0000000801000029000000400010043f0000000901000029000000000010043f0000001c01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a0000000c0020002a0000007f0000413d0000000c02200029000000000021041b0000000001000411000000000010043f0000001a01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000000000200041a000006250300004100000000003004430000058202200197000c00000002001d0000000400200443000b05820010019c0000104e0000c13d00000000010004140000057b0010009c0000057b01008041000000c00110021000000626011001c7000080020200003915e615e10000040f00000001002001900000118b0000613d000000000101043b000000000001004b00000e7d0000613d000000400300043d00000024013000390000000a0200002900000000002104350000063a01000041000000000013043500000000010004100000058201100197000000040230003900000000001204350000057b0030009c000b00000003001d0000057b010000410000000001034019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000060f011001c70000000c0200002915e615dc0000040f0000000100200190000010bf0000613d0000000b01000029000005fd0010009c000006a70000213d0000000b01000029000000400010043f0000000001000410000000000010043f0000001d01000039000000200010043f00000000010004140000107c0000013d0000000601000039000000000101041a000500010010003e0000007f0000613d00000006010000390000000502000029000000000021041b0000000b0100002900000000002104350000000001000411000000000010043f0000001301000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000060502000041000000040020043f000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000606011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000400000001001d0000000501000029000006070010009c0000109a0000c13d0000063101000041000000000010043f0000062201000041000015e80001043000000060061002700000001f0460018f000005fc05600198000000400200043d000000000352001900000d2f0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b00000f2a0000c13d00000d2f0000013d00000060061002700000001f0460018f000005fc05600198000000400200043d000000000352001900000d2f0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b00000f370000c13d00000d2f0000013d00000060061002700000001f0460018f000005fc05600198000000400200043d000000000352001900000d2f0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b00000f440000c13d00000d2f0000013d0000000a01000029000000200010043f0000000c01000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000800000001001d000000000101041a000c00000001001d000000000001004b00000f7f0000613d0000000701000029000000010110027000070001001000920000000c0010006b00000f750000613d0000000c010000290000000a0110002900000007030000290000000a02300029000000000202041a000000010110008a000000000021041b000000000020043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000c02000029000000000021041b0000000701000029000000010110021000000001011001bf000000060200002900000f7c0000013d0000000c0030006c000010a90000c13d000000000012041b0000000801000029000000000001041b00000004010000390000000001100367000000000101043b000000000010043f0000001401000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000001041b0000000102100039000000000002041b0000000202100039000000000002041b0000000302100039000000000002041b0000000402100039000000000002041b0000000501100039000000000001041b0000000d010000290000000006010433000000400100043d0000000902000029000000000221043600000004030000390000000003300367000000000303043b00000000003204350000057b0010009c0000057b01008041000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f000005f6011001c70000800d0200003900000003030000390000060c04000041000000000500041115e615dc0000040f000000010020019000000e7d0000613d0000000b010000290000000001010433000d00000001001d000000000100041115e612a10000040f0000000901000039000000000201041a0000000d0220006c0000007f0000413d000000000021041b0000000001000411000000000010043f0000000f01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a0000000d0220006c0000007f0000413d000000000021041b0000000001000411000000000010043f0000000f01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000d00000001001d0000001001000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000101041a000000400200043d000000200320003900000000001304350000000d0100002900000000001204350000057b0020009c0000057b02008041000000400120021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f000005f6011001c70000800d0200003900000002030000390000060d04000041000000000500041115e615dc0000040f000000010020019000000e7d0000613d000000090000006b000008d90000613d000000400400043d000d00000004001d0000002401400039000000000200041a000000090300002900000000003104350000060e01000041000000000014043500000000010004110000058201100197000000040340003900000000001304350000057b0040009c0000057b010000410000000001044019000000400110021000000000030004140000057b0030009c0000057b03008041000000c003300210000000000113019f0000060f011001c7000005820220019715e615dc0000040f00000060031002700000057b03300197000000200030008c000000200400003900000000040340190000001f0640018f00000020074001900000000d0b0000290000000d057000290000102b0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000010270000c13d000000000006004b000010380000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000011960000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000005fd0010009c000006a70000213d0000000100200190000006a70000c13d000000400010043f000000200030008c00000e7d0000413d00000000010b0433000000000001004b0000000002000039000000010200c039000000000021004b000008d90000613d00000e7d0000013d00000000010004140000057b0010009c0000057b01008041000000c00110021000000626011001c7000080020200003915e615e10000040f00000001002001900000118b0000613d000000000101043b000000000001004b00000e7d0000613d000000400300043d00000024013000390000000a0200002900000000002104350000063a01000041000000000013043500000004013000390000000b0200002900000000002104350000057b0030009c000900000003001d0000057b010000410000000001034019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000060f011001c70000000c0200002915e615dc0000040f0000000100200190000010cc0000613d0000000901000029000005fd0010009c000006a70000213d0000000901000029000000400010043f0000000b01000029000000000010043f0000001d01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a0000000a0020002a0000007f0000413d0000000a02200029000000000021041b000000400100043d0000000d0200002900000000002104350000057b0010009c0000057b01008041000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000121019f00000614011001c70000800d0200003900000002030000390000063b0400004100000cae0000013d00000004020000290000064501200167000200000001001d000000000101041a000000200020043f000300000001001d000000000001004b000011060000c13d0000000401000029000000000101041a000000000001004b000010ac0000c13d000000050100002900000004020000290000111f0000013d0000000c0010006c00000f7d0000613d00000f7f0000013d000000050010006c000011200000613d00000004020000290000000102200039000000000302041a000300000003001d000000000003004b000010bd0000613d0000000303000029000000050030006c000011200000613d00000004020000290000000202200039000000000302041a000100000003001d000000000003004b000010d90000c13d00000005010000290000111f0000013d00000060061002700000001f0460018f000005fc05600198000000400200043d000000000352001900000d2f0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000010c70000c13d00000d2f0000013d00000060061002700000001f0460018f000005fc05600198000000400200043d000000000352001900000d2f0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b000010d40000c13d00000d2f0000013d0000000103000029000000050030006c000011200000613d000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000102000039000000000021041b0000000301000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000202000039000000000021041b0000000101000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000302000039000000000021041b000300070000003d0000000501000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a000000000002004b000011200000c13d0000000302000029000000010220027000000004032000290000000504000029000000000043041b0000000102200039000000000021041b000000010120021000000001011001bf0000000202000029000000000012041b0000000601000039000000000101041a000000000010043f0000001401000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d0000000d020000290000000002020433000000000301043b000000000023041b0000000b0100002900000000010104330000000102300039000000000012041b0000000a0100002900000000010104330000000202300039000000000012041b0000000c0100002900000000010104330000000302300039000000000012041b000000080200002900000000020204330000000404300039000000000024041b0000000502300039000000000302041a000006440330019700000009040000290000000004040433000000000004004b000000010330c1bf000000000032041b00000007020000290000000102200039000000000302041a000000010330003a0000007f0000613d000000000032041b0000000602000029000000000202041a000000000012001a0000007f0000413d00000000011200190000000602000029000000000012041b0000000601000039000000000101041a000000400300043d00000020023000390000000000120435000d00000003001d0000000000030435000005f501000041000000000010044300000000010004120000000400100443000000240000044300000000010004140000057b0010009c0000057b01008041000000c00110021000000613011001c7000080050200003915e615e10000040f00000001002001900000118b0000613d000000000601043b0000000d010000290000057b0010009c0000057b01008041000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f000005f6011001c70000800d0200003900000003030000390000062804000041000000000500041115e615dc0000040f000000010020019000000e7d0000613d0000000a010000290000000002010433000000000100041115e614470000040f00000000010004140000057b0010009c0000057b01008041000000c00110021000000583011001c70000800d020000390000000203000039000006300400004100000cae0000013d000000000001042f000000050010006c000011f20000613d00000004020000290000000102200039000000000302041a000300000003001d000000000003004b000011a20000c13d0000000501000029000011f10000013d0000001f0530018f000005fc06300198000000400200043d0000000004620019000007570000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000119d0000c13d000007570000013d0000000303000029000000050030006c000011f20000613d00000004020000290000000202200039000000000302041a000100000003001d000000000003004b000011940000613d0000000103000029000000050030006c000011f20000613d000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000102000039000000000021041b0000000301000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000202000039000000000021041b0000000101000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b0000000302000039000000000021041b000300070000003d0000000501000029000000000010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d000000000101043b000000000201041a000000000002004b000011f20000c13d0000000302000029000000010220027000000004032000290000000504000029000000000043041b0000000102200039000000000021041b000000010120021000000001011001bf0000000202000029000000000012041b0000000601000039000000000101041a000000000010043f0000001401000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f000000010020019000000e7d0000613d00000008020000290000000002020433000000000301043b000000000023041b0000000a0100002900000000010104330000000102300039000000000012041b000000090100002900000000010104330000000202300039000000000012041b0000000b0100002900000000020104330000000301300039000000000021041b0000000c0100002900000000010104330000000404300039000000000014041b0000000503300039000000000503041a00000644045001970000000d050000290000000005050433000000000005004b000000010440c1bf000000000043041b00000007030000290000000103300039000000000403041a000000010440003a0000007f0000613d000000000043041b0000000603000029000000000303041a000000000023001a0000007f0000413d00000000022300190000000603000029000000000023041b0000000602000039000000000202041a000000400300043d00000020043000390000000000240435000000000013043500000004010000390000000001100367000000000601043b0000057b0030009c0000057b03008041000000400130021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f000005f6011001c70000800d0200003900000003030000390000062804000041000000000500041115e615dc0000040f000000010020019000000e7d0000613d00000009010000290000000002010433000000000100041115e614470000040f0000000001000019000015e70001042e000006470010009c000012520000213d000000430010008c000012520000a13d00000000020003670000000401200370000000000101043b0000002402200370000000000202043b000000000001042d0000000001000019000015e8000104300001000000000002000000000301041a000100000002001d000000000023004b000012670000a13d000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000614011001c7000080100200003915e615e10000040f00000001002001900000126d0000613d000000000101043b00000001011000290000000002000019000000000001042d0000063e01000041000000000010043f0000003201000039000000040010043f0000060b01000041000015e8000104300000000001000019000015e8000104300000001f0220003900000646022001970000000001120019000000000021004b00000000020000390000000102004039000005fd0010009c0000127b0000213d00000001002001900000127b0000c13d000000400010043f000000000001042d0000063e01000041000000000010043f0000004101000039000000040010043f0000060b01000041000015e8000104300000000002120049000006470020009c0000128d0000213d0000001f0020008c0000128d0000a13d0000000001010433000000000001004b0000000002000039000000010200c039000000000021004b0000128d0000c13d000000000001042d0000000001000019000015e8000104300000002301000039000000000101041a000000080110027000000582021001970000000001000411000000000012004b000012970000c13d000000000001042d000000400200043d000005f3030000410000000000320435000000040320003900000000001304350000057b0020009c0000057b0200804100000040012002100000060b011001c7000015e8000104300003000000000002000100000001001d0000000901000039000000000101041a000000000001004b0000000802000039000012f50000613d0000000201000039000000000101041a000000000302041a000000000113004b000013580000413d0000061e0010009c000013580000213d0000057b011001970000061f0110012a000006200710027f000200000007001d000300000003001d0000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000135e0000613d000000000101043b0000000304000029000000000014004b0000000207000029000013010000813d0000000302000039000000000202041a0000061c0320009c000013580000813d000000000013004b00000000020100190000000002034019000000000442004b000013580000413d000000000007004b000012da0000613d00000000057400a900000000067500d9000000000046004b000013580000c13d000000000005004b000012da0000613d00000612045000d100000000055400d9000006120050009c000012db0000613d000013580000013d00000000040000190000000905000039000000000505041a000000000005004b0000135f0000613d00000000045400d90000000b05000039000000000505041a000000000045001a000013580000413d00000000044500190000000b05000039000000000045041b000000000013004b0000000003020019000012b30000213d0000000301000039000000000021041b0000000401000039000000000101041a000000010110003a000013580000613d0000000403000039000000000013041b00000001077002700000000003020019000012b20000013d0000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000135e0000613d000000000101043b0000000802000039000000000012041b00000001010000290000058201100197000300000001001d000000000010043f0000000f01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000013650000613d0000000b02000039000000000202041a000100000002001d000000000101043b000000000101041a000200000001001d0000001101000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000013650000613d000000000101043b000000000101041a000000010110006b0000000202000029000013580000413d00000000032100a9000000000002004b0000132e0000613d00000000022300d9000000000012004b000013580000c13d000200000003001d0000000301000029000000000010043f0000001001000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000013650000613d0000000202000029000006120220012a000000000101043b000000000301041a000000000023001a000013580000413d0000000002230019000000000021041b0000000b01000039000000000101041a000200000001001d0000000301000029000000000010043f0000001101000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000013650000613d000000000101043b0000000202000029000000000021041b000000000001042d0000063e01000041000000000010043f0000001101000039000000040010043f0000060b01000041000015e800010430000000000001042f0000063e01000041000000000010043f0000001201000039000000040010043f0000060b01000041000015e8000104300000000001000019000015e8000104300002000000000002000000400400043d000200000004001d0000002403400039000000000200041a000100000001001d0000000000130435000006480100004100000000001404350000000401400039000006110300004100000000003104350000057b0040009c0000057b010000410000000001044019000000400110021000000000030004140000057b0030009c0000057b03008041000000c003300210000000000113019f0000060f011001c7000005820220019715e615dc0000040f000000020b00002900000060031002700000057b03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000138f0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000138b0000c13d000000000006004b0000139c0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f00000000006504350000000100200190000014290000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000005fd0010009c000014210000213d0000000100200190000014210000c13d000000400010043f0000001f0030008c000014270000a13d00000000020b0433000000000002004b0000000003000039000000010300c039000000000032004b000014270000c13d000006490010009c000014210000213d0000000102000039000000000302041a000000e002100039000000000400041a000000400020043f00000080021000390000000105000029000000000052043500000582033001970000006005100039000000000035043500000040031000390000271006000039000000000063043500000020061000390000061707000041000000000076043500000582044001970000000000410435000000c0041000390000000000040435000000a00710003900000000000704350000064a08000041000000400900043d000200000009001d00000000008904350000000001010433000005820110019700000004089000390000000000180435000000000106043300000582011001970000002406900039000000000016043500000000010304330000064b011001970000004403900039000000000013043500000000010504330000058201100197000000640390003900000000001304350000000001020433000000840290003900000000001204350000000001070433000000a402900039000000000012043500000000010404330000058201100197000000c40290003900000000001204350000057b0090009c0000057b010000410000000001094019000000400110021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000064c011001c7000006110200004115e615dc0000040f000000020b00002900000060031002700000057b03300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000014040000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000014000000c13d000000000006004b000014110000613d000000000171034f0000000306600210000000000705043300000000076701cf000000000767022f000000000101043b0000010006600089000000000161022f00000000016101cf000000000171019f00000000001504350000000100200190000014200000613d0000001f01400039000000600210018f0000000001b20019000000000021004b00000000020000390000000102004039000005fd0010009c000014210000213d0000000100200190000014210000c13d000000400010043f000000200030008c000014270000413d000000000001042d0000063e01000041000000000010043f0000004101000039000000040010043f0000060b01000041000015e8000104300000000001000019000015e8000104300000001f0530018f000005fc06300198000000400200043d0000000004620019000014340000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000014300000c13d000000000005004b000014410000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500000060013002100000057b0020009c0000057b020080410000004002200210000000000112019f000015e8000104300004000000000002000200000002001d000100000001001d0000000501000039000000000201041a000000ff00200190000014740000c13d000006440220019700000001022001bf000000000021041b0000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000157b0000613d000000000101043b0000000202000039000000000012041b0000000302000039000000000012041b0000000802000039000000000012041b000000400200043d00000000001204350000057b0020009c0000057b02008041000000400120021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f00000614011001c70000800d0200003900000001030000390000064d0400004115e615dc0000040f0000000100200190000015820000613d0000000901000039000000000101041a000000000001004b000014c60000613d0000000201000039000000000101041a0000000802000039000000000302041a000000000113004b000015750000413d0000061e0010009c000015750000213d0000057b011001970000061f0110012a000006200710027f000300000007001d000400000003001d0000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000157b0000613d000000000101043b0000000404000029000000000014004b0000000307000029000014d20000813d0000000302000039000000000202041a0000061c0320009c000015750000813d000000000013004b00000000020100190000000002034019000000000442004b000015750000413d000000000007004b000014ab0000613d00000000057400a900000000067500d9000000000046004b000015750000c13d000000000005004b000014ab0000613d00000612045000d100000000055400d9000006120050009c000014ac0000613d000015750000013d00000000040000190000000905000039000000000505041a000000000005004b0000157c0000613d00000000045400d90000000b05000039000000000505041a000000000045001a000015750000413d00000000044500190000000b05000039000000000045041b000000000013004b0000000003020019000014840000213d0000000301000039000000000021041b0000000401000039000000000101041a000000010110003a000015750000613d0000000403000039000000000013041b00000001077002700000000003020019000014830000013d0000061d01000041000000000010044300000000010004140000057b0010009c0000057b01008041000000c001100210000005f9011001c70000800b0200003915e615e10000040f00000001002001900000157b0000613d000000000101043b0000000802000039000000000012041b00000001010000290000058201100197000400000001001d000000000010043f0000000f01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000015820000613d0000000b02000039000000000202041a000100000002001d000000000101043b000000000101041a000300000001001d0000001101000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000015820000613d000000000101043b000000000101041a000000010110006b0000000302000029000015750000413d00000000032100a9000000000002004b000014ff0000613d00000000022300d9000000000012004b000015750000c13d000300000003001d0000000401000029000000000010043f0000001001000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000015820000613d0000000302000029000006120220012a000000000101043b000000000301041a000000000023001a000015750000413d0000000002230019000000000021041b0000000b01000039000000000101041a000300000001001d0000000401000029000000000010043f0000001101000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000015820000613d000000000101043b0000000302000029000000000021041b0000000901000039000000000101041a000000020010002a000015750000413d00000002011000290000000902000039000000000012041b0000000401000029000000000010043f0000000f01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000015820000613d000000000101043b000000000201041a000000020020002a000015750000413d0000000202200029000000000021041b0000000401000029000000000010043f0000000f01000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000015820000613d000000000101043b000000000101041a000400000001001d0000001001000039000000200010043f00000000010004140000057b0010009c0000057b01008041000000c001100210000005f6011001c7000080100200003915e615e10000040f0000000100200190000015820000613d000000000101043b000000000101041a000000400200043d00000020032000390000000000130435000000040100002900000000001204350000057b0020009c0000057b02008041000000400120021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f000005f6011001c70000800d02000039000000020300003900000000050004110000064e0400004115e615dc0000040f0000000100200190000015820000613d000000000001042d0000063e01000041000000000010043f0000001101000039000000040010043f0000060b01000041000015e800010430000000000001042f0000063e01000041000000000010043f0000001201000039000000040010043f0000060b01000041000015e8000104300000000001000019000015e8000104300000060502000041000000040020043f000000000010043f00000000010004140000057b0010009c0000057b01008041000000c00110021000000606011001c7000080100200003915e615e10000040f0000000100200190000015a60000613d000000000201043b0000064501200167000000000101041a000000000001004b000015970000613d0000000101100270000000000001042d000000000102041a000000000001004b0000000001000039000000010100c039000015a50000613d0000000103200039000000000303041a000000000003004b000015a50000613d0000000201200039000000000101041a000000000001004b00000003010000390000000201006039000000000001042d0000000001000019000015e800010430000000000001042f0000057b0010009c0000057b0100804100000040011002100000057b0020009c0000057b020080410000006002200210000000000112019f00000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f00000583011001c7000080100200003915e615e10000040f0000000100200190000015bc0000613d000000000101043b000000000001042d0000000001000019000015e80001043000000000050100190000000000200443000000050030008c000015cc0000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b000015c40000413d0000057b0030009c0000057b03008041000000600130021000000000020004140000057b0020009c0000057b02008041000000c002200210000000000112019f0000064f011001c7000000000205001915e615e10000040f0000000100200190000015db0000613d000000000101043b000000000001042d000000000001042f000015df002104210000000102000039000000000001042d0000000002000019000000000001042d000015e4002104230000000102000039000000000001042d0000000002000019000000000001042d000015e600000432000015e70001042e000015e80001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000470de4df820000000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000030ca024f987b9000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffff0000000000000000000000000000000000000000ff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff02000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e000000000000000000000000000000000000000000000001043561a882930000000000002000000000000000000000000000000800000010000000000000000001e4fbdf7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000a0000000000000000000000000000000000000000000000000000000000000000000000000811c508800000000000000000000000000000000000000000000000000000000c51a2bb900000000000000000000000000000000000000000000000000000000e8ee066f00000000000000000000000000000000000000000000000000000000eef3b2cf00000000000000000000000000000000000000000000000000000000f5c823cd00000000000000000000000000000000000000000000000000000000f5c823ce00000000000000000000000000000000000000000000000000000000f934e92500000000000000000000000000000000000000000000000000000000fcfff16f00000000000000000000000000000000000000000000000000000000eef3b2d000000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000ea26fa2c00000000000000000000000000000000000000000000000000000000ea26fa2d00000000000000000000000000000000000000000000000000000000eca17aee00000000000000000000000000000000000000000000000000000000ed83784700000000000000000000000000000000000000000000000000000000e8ee067000000000000000000000000000000000000000000000000000000000e92820e600000000000000000000000000000000000000000000000000000000dd6a4c6400000000000000000000000000000000000000000000000000000000e0d152ae00000000000000000000000000000000000000000000000000000000e0d152af00000000000000000000000000000000000000000000000000000000e356351700000000000000000000000000000000000000000000000000000000e65a2e7e00000000000000000000000000000000000000000000000000000000dd6a4c6500000000000000000000000000000000000000000000000000000000e04aa40600000000000000000000000000000000000000000000000000000000ca18116f00000000000000000000000000000000000000000000000000000000ca18117000000000000000000000000000000000000000000000000000000000d9ba62b300000000000000000000000000000000000000000000000000000000c51a2bba00000000000000000000000000000000000000000000000000000000c6005893000000000000000000000000000000000000000000000000000000009618b31b000000000000000000000000000000000000000000000000000000009f715f5f00000000000000000000000000000000000000000000000000000000ad5c464700000000000000000000000000000000000000000000000000000000ad5c464800000000000000000000000000000000000000000000000000000000c243589400000000000000000000000000000000000000000000000000000000c2ccf143000000000000000000000000000000000000000000000000000000009f715f6000000000000000000000000000000000000000000000000000000000a9f8d181000000000000000000000000000000000000000000000000000000009ca423b2000000000000000000000000000000000000000000000000000000009ca423b3000000000000000000000000000000000000000000000000000000009d654831000000000000000000000000000000000000000000000000000000009618b31c000000000000000000000000000000000000000000000000000000009af4a7d100000000000000000000000000000000000000000000000000000000873fd4ef000000000000000000000000000000000000000000000000000000008e4f8d47000000000000000000000000000000000000000000000000000000008e4f8d4800000000000000000000000000000000000000000000000000000000940e6d150000000000000000000000000000000000000000000000000000000094fc19e400000000000000000000000000000000000000000000000000000000873fd4f0000000000000000000000000000000000000000000000000000000008da5cb5b0000000000000000000000000000000000000000000000000000000084ae2bc50000000000000000000000000000000000000000000000000000000084ae2bc60000000000000000000000000000000000000000000000000000000086b3cd2600000000000000000000000000000000000000000000000000000000811c508900000000000000000000000000000000000000000000000000000000846bf7fa0000000000000000000000000000000000000000000000000000000041a0894c0000000000000000000000000000000000000000000000000000000062de3bd0000000000000000000000000000000000000000000000000000000007855d4f8000000000000000000000000000000000000000000000000000000007b4af37b000000000000000000000000000000000000000000000000000000007b4af37c000000000000000000000000000000000000000000000000000000007e08b5b3000000000000000000000000000000000000000000000000000000007e4785f4000000000000000000000000000000000000000000000000000000007855d4f9000000000000000000000000000000000000000000000000000000007a89397e00000000000000000000000000000000000000000000000000000000715018a500000000000000000000000000000000000000000000000000000000715018a60000000000000000000000000000000000000000000000000000000072779cba0000000000000000000000000000000000000000000000000000000077f793c70000000000000000000000000000000000000000000000000000000062de3bd100000000000000000000000000000000000000000000000000000000713494d700000000000000000000000000000000000000000000000000000000542f9e69000000000000000000000000000000000000000000000000000000005c6d6c20000000000000000000000000000000000000000000000000000000005c6d6c21000000000000000000000000000000000000000000000000000000005c7421e3000000000000000000000000000000000000000000000000000000005fd9491d00000000000000000000000000000000000000000000000000000000542f9e6a000000000000000000000000000000000000000000000000000000005a5ccef00000000000000000000000000000000000000000000000000000000048cd4cb00000000000000000000000000000000000000000000000000000000048cd4cb1000000000000000000000000000000000000000000000000000000004e3e6fe10000000000000000000000000000000000000000000000000000000041a0894d0000000000000000000000000000000000000000000000000000000047535d7b000000000000000000000000000000000000000000000000000000002e360cf50000000000000000000000000000000000000000000000000000000035deaa62000000000000000000000000000000000000000000000000000000003ccfd60a000000000000000000000000000000000000000000000000000000003ccfd60b000000000000000000000000000000000000000000000000000000003e89bb130000000000000000000000000000000000000000000000000000000040f5da9e0000000000000000000000000000000000000000000000000000000035deaa6300000000000000000000000000000000000000000000000000000000372500ab000000000000000000000000000000000000000000000000000000002fc96ce5000000000000000000000000000000000000000000000000000000002fc96ce60000000000000000000000000000000000000000000000000000000031d7a262000000000000000000000000000000000000000000000000000000002e360cf6000000000000000000000000000000000000000000000000000000002ef9eaa6000000000000000000000000000000000000000000000000000000001a267cd100000000000000000000000000000000000000000000000000000000234f3f1a00000000000000000000000000000000000000000000000000000000234f3f1b0000000000000000000000000000000000000000000000000000000024b4464e000000000000000000000000000000000000000000000000000000002d4dfcde000000000000000000000000000000000000000000000000000000001a267cd2000000000000000000000000000000000000000000000000000000001e57057d0000000000000000000000000000000000000000000000000000000017820fcf0000000000000000000000000000000000000000000000000000000017820fd0000000000000000000000000000000000000000000000000000000001a17c1b800000000000000000000000000000000000000000000000000000000121564d600000000000000000000000000000000000000000000000000000000157e204c0000000000000000000000000000000000000020000000800000000000000000118cdaa7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000800000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e02000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000020000000000000000000000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d95539132020000020000000000000000000000000000000400000000000000000000000023b872dd00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000000000000000000000000000ffffffffffffffffe2dbc44c627e3876b04b29d12596a77c7d0fa585ccb754b9fcd92e48d813dd7741fde9ef0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000c02d44e000000000000000000000000000000000000000000000000000000000e6ce2f100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000080000000000000000000000000000000000000000000000000000000c00000008000000000000000000000000000000000000000000000000000000000000000000000000018fb586402000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000fbb67fda52d4bfb8bf3d9f63cb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff3f70a08231000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000bb8db292349eecec0f157746522d22a04be58c69c690e5af7d7f15a6a04d4d87e331ada0d0e61e9a4196bf4994f2519193d70a601daff346c4276d591664da9aa9059cbb000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000000000000000000000515d3e81000000000000000000000000000000000000000000000000000000000000000000000000000000007712fa47387542819d4e35a23f8116c90c18767c0000000000000000000000000000000000000000000000000de0b6b3a764000002000002000000000000000000000000000000440000000000000000000000000200000000000000000000000000000000000020000000000000000000000000d0a7ceb410ade2d440d8ed59d6b338fe480f98025101655790e0de736edddabe3b87f109000000000000000000000000000000000000000000000000000000000000000000000000000000003439153eb7af838ad19d56e1571fbd09333c28090200000000000000000000000000000000000080000000000000000000000000e0a2f8482bbba7e119c069eb63409ac33b15fc516cffed25aeabb6a9669e07c2ffffffffffffffffffffffff0000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5cfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd5d0042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd10000000000000000000000000000000000000000000000000000000002a2ffff000000000000000000000000000000000000000000000000000000000002a300000000000000000000000000000000000000000000000002b5e3af16b188000000000000000000000000000000000000000000000000000000000000ad251c2700000000000000000000000000000000000000040000001c00000000000000000000000000000000000000000000000000000000000000000de0b6b3a764000158d620b3000000000000000000000000000000000000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000042966c6800000000000000000000000000000000000000000000000000000000e9a3d31ddc75e6f55428f56a99300650dd35074dbe47cffa59e8292fe6f2886ffbfd2f4000000000000000000000000000000000000000000000000000000000ff0b21e600000000000000000000000000000000000000000000000000000000aa8a9b980000000000000000000000000000000000000000000000000000000086257f0afab037798cc4548a6d86125f52c92410a1e29aff03d787d49dac20db0000000000000000000000000000000000000080000000800000000000000000d2ade556000000000000000000000000000000000000000000000000000000008fe6f7d800000000000000000000000000000000000000000000000000000000e424ed553a53c3a900c875ed34d63043e4dfb799427ee8ae0836b046a603c90e00000000000000000000000000000000000000000000000000000000f5a267f1611042280000000000000000000000000000000000000000000000000000000008c379a0000000000000000000000000000000000000000000000000000000006e6f74206f70656e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000008000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f3900000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000003ffffffe0750b219c0000000000000000000000000000000000000000000000000000000040c10f1900000000000000000000000000000000000000000000000000000000fc30cddea38e2bf4d6ea7d3f9ed3b6ad7f176419f4963bd81318067a4aee73fe0df723dc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000bac65e5b4e487b71000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffffdf00000000000000000000000000000000000000000000000100000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe04e23d03500000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff095ea7b300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1f04e45aaf000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffff00000000000000000000000000000000000000e4000000000000000000000000daae9aa758637a0d349f036f099afd70aa88d8ac63fce096321de512ffebc16ca051d58ced8df58040b29d2c939da70a826ae40290f77c9a66b38b8b85315f6502000002000000000000000000000000000000000000000000000000000000001863e397912dac9a59d9c8d81b23047d22a76badf14545a75ea04f7f84a4efd1
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.