ETH Price: $2,530.27 (-2.77%)

Token

fees.wtf (WTF)
 

Overview

Max Total Supply

245,312,937.887255362992952707 WTF

Holders

21,032 (0.00%)

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-

Other Info

Token Contract (WITH 18 Decimals)

Filtered by Token Holder
mrphillyjawn.eth
Balance
1,730.107895131796112764 WTF

Value
$0.00
0x337d90e3f63cca39202fba3e720fb562d15134cc
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume

Contract Source Code Verified (Exact Match)

Contract Name:
WTF

Compiler Version
v0.8.11+commit.d7f03943

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Multiple files format)

File 7 of 8: WTF.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

import "./WTFNFT.sol";
import "./Treasury.sol";
import "./StakingRewards.sol";

interface Callable {
	function tokenCallback(address _from, uint256 _tokens, bytes calldata _data) external returns (bool);
}

interface Router {
	function WETH() external pure returns (address);
	function factory() external pure returns (address);
}

interface Factory {
	function createPair(address, address) external returns (address);
}

interface Pair {
	function token0() external view returns (address);
	function totalSupply() external view returns (uint256);
	function balanceOf(address) external view returns (uint256);
	function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}


contract WTF {

	uint256 constant private FLOAT_SCALAR = 2**64;
	uint256 constant private UINT_MAX = type(uint256).max;
	uint256 constant private TRANSFER_FEE_SCALE = 1000; // 1 = 0.1%
	uint256 constant private WTF_STAKING_SUPPLY = 2e25; // 20M WTF
	uint256 constant private LP_STAKING_SUPPLY = 4e25; // 40M WTF
	uint256 constant private TREASURY_SUPPLY = 4e25; // 40M WTF
	uint256 constant private BASE_UPGRADE_COST = 1e19; // 10 WTF
	uint256 constant private SERVICE_FEE = 0.01 ether;

	string constant public name = "fees.wtf";
	string constant public symbol = "WTF";
	uint8 constant public decimals = 18;

	struct User {
		uint256 balance;
		mapping(address => uint256) allowance;
		int256 scaledPayout;
		uint256 reflinkLevel;
		bool unlocked;
	}

	struct Info {
		bytes32 merkleRoot;
		uint256 openingTime;
		uint256 closingTime;
		uint256 totalSupply;
		uint256 scaledRewardsPerToken;
		mapping(uint256 => uint256) claimedWTFBitMap;
		mapping(uint256 => uint256) claimedNFTBitMap;
		mapping(address => User) users;
		mapping(address => bool) toWhitelist;
		mapping(address => bool) fromWhitelist;
		address owner;
		Router router;
		Pair pair;
		bool weth0;
		WTFNFT nft;
		TeamReferral team;
		Treasury treasury;
		StakingRewards stakingRewards;
		StakingRewards lpStakingRewards;
		address feeManager;
		uint256 transferFee;
		uint256 feeManagerPercent;
	}
	Info private info;


	event Transfer(address indexed from, address indexed to, uint256 tokens);
	event Approval(address indexed owner, address indexed spender, uint256 tokens);
	event WhitelistUpdated(address indexed user, bool fromWhitelisted, bool toWhitelisted);
	event ReflinkRewards(address indexed referrer, uint256 amount);
	event ClaimRewards(address indexed user, uint256 amount);
	event Reward(uint256 amount);

	modifier _onlyOwner() {
		require(msg.sender == owner());
		_;
	}


	constructor(bytes32 _merkleRoot, uint256 _openingTime, uint256 _stakingRewardsStart) {
		info.merkleRoot = _merkleRoot;
		info.openingTime = block.timestamp < _openingTime ? _openingTime : block.timestamp;
		info.closingTime = openingTime() + 30 days;
		info.router = Router(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
		info.pair = Pair(Factory(info.router.factory()).createPair(info.router.WETH(), address(this)));
		info.weth0 = info.pair.token0() == info.router.WETH();
		info.transferFee = 40; // 4%
		info.feeManagerPercent = 25; // 25%
		info.owner = 0x65dd4990719bE9B20322e4E8D3Bd77a4401a0357;
		info.nft = new WTFNFT();
		info.team = new TeamReferral();
		info.treasury = new Treasury();
		_mint(treasuryAddress(), TREASURY_SUPPLY);
		info.stakingRewards = new StakingRewards(WTF_STAKING_SUPPLY, _stakingRewardsStart, ERC20(address(this)));
		_mint(stakingRewardsAddress(), WTF_STAKING_SUPPLY);
		info.lpStakingRewards = new StakingRewards(LP_STAKING_SUPPLY, _stakingRewardsStart, ERC20(pairAddress()));
		_mint(lpStakingRewardsAddress(), LP_STAKING_SUPPLY);
		info.feeManager = address(new FeeManager());
		_approve(feeManagerAddress(), stakingRewardsAddress(), UINT_MAX);
		_approve(feeManagerAddress(), lpStakingRewardsAddress(), UINT_MAX);
	}

	function setOwner(address _owner) external _onlyOwner {
		info.owner = _owner;
	}

	function setFeeManager(address _feeManager) external _onlyOwner {
		info.feeManager = _feeManager;
	}

	function setClosingTime(uint256 _closingTime) external _onlyOwner {
		info.closingTime = _closingTime;
	}

	function setTransferFee(uint256 _transferFee) external _onlyOwner {
		require(_transferFee <= 100); // ≤10%
		info.transferFee = _transferFee;
	}

	function setFeeManagerPercent(uint256 _feeManagerPercent) external _onlyOwner {
		require(_feeManagerPercent <= 100);
		info.feeManagerPercent = _feeManagerPercent;
	}

	function setWhitelisted(address _address, bool _fromWhitelisted, bool _toWhitelisted) external _onlyOwner {
		info.fromWhitelist[_address] = _fromWhitelisted;
		info.toWhitelist[_address] = _toWhitelisted;
		emit WhitelistUpdated(_address, _fromWhitelisted, _toWhitelisted);
	}


	function disburse(uint256 _amount) external {
		require(_amount > 0);
		uint256 _balanceBefore = balanceOf(address(this));
		_transfer(msg.sender, address(this), _amount);
		uint256 _amountReceived = balanceOf(address(this)) - _balanceBefore;
		_disburse(_amountReceived);
	}

	function sweep() external {
		if (address(this).balance > 0) {
			teamAddress().transfer(address(this).balance);
		}
	}

	function upgradeReflink(uint256 _toLevel) external {
		uint256 _currentLevel = reflinkLevel(msg.sender);
		require(_currentLevel < _toLevel);
		uint256 _totalCost = 0;
		for (uint256 i = _currentLevel; i < _toLevel; i++) {
			_totalCost += upgradeCost(i);
		}
		burn(_totalCost);
		info.users[msg.sender].reflinkLevel = _toLevel;
	}

	function unlock(address _account, address payable _referrer) external payable {
		require(block.timestamp < closingTime());
		require(!isUnlocked(_account));
		require(msg.value == SERVICE_FEE);
		uint256 _refFee = 0;
		if (_referrer != address(0x0)) {
			_refFee = SERVICE_FEE * reflinkPercent(_referrer) / 100;
			!_referrer.send(_refFee);
			emit ReflinkRewards(_referrer, _refFee);
		}
		uint256 _remaining = SERVICE_FEE - _refFee;
		teamAddress().transfer(_remaining);
		emit ReflinkRewards(teamAddress(), _remaining);
		info.users[_account].unlocked = true;
	}
	
	function claim(address _account, uint256[9] calldata _data, bytes32[] calldata _proof) external {
		// Data array in format: (index, amount, totalFees, failFees, totalGas, avgGwei, totalDonated, totalTxs, failTxs)
		claimWTF(_account, _data, _proof);
		claimNFT(_account, _data, _proof);
	}
	
	function claimWTF(address _account, uint256[9] calldata _data, bytes32[] calldata _proof) public {
		require(isOpen());
		require(isUnlocked(_account));
		uint256 _index = _data[0];
		uint256 _amount = _data[1];
		require(!isClaimedWTF(_index));
		require(_verify(_proof, keccak256(abi.encodePacked(_account, _data))));
		uint256 _claimedWordIndex = _index / 256;
		uint256 _claimedBitIndex = _index % 256;
		info.claimedWTFBitMap[_claimedWordIndex] = info.claimedWTFBitMap[_claimedWordIndex] | (1 << _claimedBitIndex);
		_mint(_account, _amount);
	}

	function claimNFT(address _account, uint256[9] calldata _data, bytes32[] calldata _proof) public {
		require(isOpen());
		require(isUnlocked(_account));
		uint256 _index = _data[0];
		require(!isClaimedNFT(_index));
		require(_verify(_proof, keccak256(abi.encodePacked(_account, _data))));
		uint256 _claimedWordIndex = _index / 256;
		uint256 _claimedBitIndex = _index % 256;
		info.claimedNFTBitMap[_claimedWordIndex] = info.claimedNFTBitMap[_claimedWordIndex] | (1 << _claimedBitIndex);
		info.nft.mint(_account, _data[2], _data[3], _data[4], _data[5], _data[6], _data[7], _data[8]);
	}

	function claimRewards() external {
		boostRewards();
		uint256 _rewards = rewardsOf(msg.sender);
		if (_rewards > 0) {
			info.users[msg.sender].scaledPayout += int256(_rewards * FLOAT_SCALAR);
			_transfer(address(this), msg.sender, _rewards);
			emit ClaimRewards(msg.sender, _rewards);
		}
	}

	function boostRewards() public {
		address _this = address(this);
		uint256 _rewards = rewardsOf(_this);
		if (_rewards > 0) {
			info.users[_this].scaledPayout += int256(_rewards * FLOAT_SCALAR);
			_disburse(_rewards);
			emit ClaimRewards(_this, _rewards);
		}
	}

	function burn(uint256 _tokens) public {
		require(balanceOf(msg.sender) >= _tokens);
		info.totalSupply -= _tokens;
		info.users[msg.sender].balance -= _tokens;
		info.users[msg.sender].scaledPayout -= int256(_tokens * info.scaledRewardsPerToken);
		emit Transfer(msg.sender, address(0x0), _tokens);
	}

	function transfer(address _to, uint256 _tokens) external returns (bool) {
		return _transfer(msg.sender, _to, _tokens);
	}

	function approve(address _spender, uint256 _tokens) external returns (bool) {
		return _approve(msg.sender, _spender, _tokens);
	}

	function transferFrom(address _from, address _to, uint256 _tokens) external returns (bool) {
		uint256 _allowance = allowance(_from, msg.sender);
		require(_allowance >= _tokens);
		if (_allowance != UINT_MAX) {
			info.users[_from].allowance[msg.sender] -= _tokens;
		}
		return _transfer(_from, _to, _tokens);
	}

	function transferAndCall(address _to, uint256 _tokens, bytes calldata _data) external returns (bool) {
		uint256 _balanceBefore = balanceOf(_to);
		_transfer(msg.sender, _to, _tokens);
		uint256 _tokensReceived = balanceOf(_to) - _balanceBefore;
		uint32 _size;
		assembly {
			_size := extcodesize(_to)
		}
		if (_size > 0) {
			require(Callable(_to).tokenCallback(msg.sender, _tokensReceived, _data));
		}
		return true;
	}
	

	function pairAddress() public view returns (address) {
		return address(info.pair);
	}

	function nftAddress() external view returns (address) {
		return address(info.nft);
	}

	function teamAddress() public view returns (address payable) {
		return payable(address(info.team));
	}

	function treasuryAddress() public view returns (address) {
		return address(info.treasury);
	}

	function stakingRewardsAddress() public view returns (address) {
		return address(info.stakingRewards);
	}

	function lpStakingRewardsAddress() public view returns (address) {
		return address(info.lpStakingRewards);
	}

	function feeManagerAddress() public view returns (address) {
		return info.feeManager;
	}

	function owner() public view returns (address) {
		return info.owner;
	}

	function transferFee() public view returns (uint256) {
		return info.transferFee;
	}

	function feeManagerPercent() public view returns (uint256) {
		return info.feeManagerPercent;
	}

	function isFromWhitelisted(address _address) public view returns (bool) {
		return info.fromWhitelist[_address];
	}

	function isToWhitelisted(address _address) public view returns (bool) {
		return info.toWhitelist[_address];
	}

	function merkleRoot() public view returns (bytes32) {
		return info.merkleRoot;
	}

	function openingTime() public view returns (uint256) {
		return info.openingTime;
	}

	function closingTime() public view returns (uint256) {
		return info.closingTime;
	}

	function isOpen() public view returns (bool) {
		return block.timestamp > openingTime() && block.timestamp < closingTime();
	}

	function isUnlocked(address _user) public view returns (bool) {
		return info.users[_user].unlocked;
	}

	function isClaimedWTF(uint256 _index) public view returns (bool) {
		uint256 _claimedWordIndex = _index / 256;
		uint256 _claimedBitIndex = _index % 256;
		uint256 _claimedWord = info.claimedWTFBitMap[_claimedWordIndex];
		uint256 _mask = (1 << _claimedBitIndex);
		return _claimedWord & _mask == _mask;
	}

	function isClaimedNFT(uint256 _index) public view returns (bool) {
		uint256 _claimedWordIndex = _index / 256;
		uint256 _claimedBitIndex = _index % 256;
		uint256 _claimedWord = info.claimedNFTBitMap[_claimedWordIndex];
		uint256 _mask = (1 << _claimedBitIndex);
		return _claimedWord & _mask == _mask;
	}
	
	function totalSupply() public view returns (uint256) {
		return info.totalSupply;
	}

	function balanceOf(address _user) public view returns (uint256) {
		return info.users[_user].balance;
	}

	function rewardsOf(address _user) public view returns (uint256) {
		return uint256(int256(info.scaledRewardsPerToken * balanceOf(_user)) - info.users[_user].scaledPayout) / FLOAT_SCALAR;
	}

	function allowance(address _user, address _spender) public view returns (uint256) {
		return info.users[_user].allowance[_spender];
	}

	function reflinkLevel(address _user) public view returns (uint256) {
		return info.users[_user].reflinkLevel;
	}

	function reflinkPercent(address _user) public view returns (uint256) {
		return 10 * (reflinkLevel(_user) + 1);
	}

	function upgradeCost(uint256 _reflinkLevel) public pure returns (uint256) {
		require(_reflinkLevel < 4);
		return BASE_UPGRADE_COST * 10**_reflinkLevel;
	}

	function reflinkInfoFor(address _user) external view returns (uint256 balance, uint256 level, uint256 percent) {
		return (balanceOf(_user), reflinkLevel(_user), reflinkPercent(_user));
	}

	function claimInfoFor(uint256 _index, address _user) external view returns (uint256 openTime, uint256 closeTime, bool unlocked, bool claimedWTF, bool claimedNFT, uint256 wethReserve, uint256 wtfReserve) {
		openTime = openingTime();
		closeTime = closingTime();
		unlocked = isUnlocked(_user);
		claimedWTF = isClaimedWTF(_index);
		claimedNFT = isClaimedNFT(_index);
		( , , wethReserve, wtfReserve, , , ) = allInfoFor(address(0x0));
	}

	function allInfoFor(address _user) public view returns (uint256 totalTokens, uint256 totalLPTokens, uint256 wethReserve, uint256 wtfReserve, uint256 userBalance, uint256 userRewards, uint256 userLPBalance) {
		totalTokens = totalSupply();
		totalLPTokens = info.pair.totalSupply();
		(uint256 _res0, uint256 _res1, ) = info.pair.getReserves();
		wethReserve = info.weth0 ? _res0 : _res1;
		wtfReserve = info.weth0 ? _res1 : _res0;
		userBalance = balanceOf(_user);
		userRewards = rewardsOf(_user);
		userLPBalance = info.pair.balanceOf(_user);
	}


	function _mint(address _account, uint256 _amount) internal {
		info.totalSupply += _amount;
		info.users[_account].balance += _amount;
		info.users[_account].scaledPayout += int256(_amount * info.scaledRewardsPerToken);
		emit Transfer(address(0x0), _account, _amount);
	}
	
	function _approve(address _owner, address _spender, uint256 _tokens) internal returns (bool) {
		info.users[_owner].allowance[_spender] = _tokens;
		emit Approval(_owner, _spender, _tokens);
		return true;
	}
	
	function _transfer(address _from, address _to, uint256 _tokens) internal returns (bool) {
		require(balanceOf(_from) >= _tokens);
		info.users[_from].balance -= _tokens;
		info.users[_from].scaledPayout -= int256(_tokens * info.scaledRewardsPerToken);
		uint256 _fee = 0;
		if (!_isExcludedFromFee(_from, _to)) {
			_fee = _tokens * transferFee() / TRANSFER_FEE_SCALE;
			address _this = address(this);
			info.users[_this].balance += _fee;
			info.users[_this].scaledPayout += int256(_fee * info.scaledRewardsPerToken);
			emit Transfer(_from, _this, _fee);
		}
		uint256 _transferred = _tokens - _fee;
		info.users[_to].balance += _transferred;
		info.users[_to].scaledPayout += int256(_transferred * info.scaledRewardsPerToken);
		emit Transfer(_from, _to, _transferred);
		if (_fee > 0) {
			uint256 _feeManagerRewards = _fee * feeManagerPercent() / 100;
			info.users[feeManagerAddress()].scaledPayout -= int256(_feeManagerRewards * FLOAT_SCALAR);
			_disburse(_fee - _feeManagerRewards);
		}
		return true;
	}

	function _disburse(uint256 _amount) internal {
		if (_amount > 0) {
			info.scaledRewardsPerToken += _amount * FLOAT_SCALAR / totalSupply();
			emit Reward(_amount);
		}
	}


	function _isExcludedFromFee(address _from, address _to) internal view returns (bool) {
		return isFromWhitelisted(_from) || isToWhitelisted(_to)
			|| _from == address(this) || _to == address(this)
			|| _from == feeManagerAddress() || _to == feeManagerAddress()
			|| _from == treasuryAddress() || _to == treasuryAddress()
			|| _from == stakingRewardsAddress() || _to == stakingRewardsAddress()
			|| _from == lpStakingRewardsAddress() || _to == lpStakingRewardsAddress();
	}
	
	function _verify(bytes32[] memory _proof, bytes32 _leaf) internal view returns (bool) {
		bytes32 _computedHash = _leaf;
		for (uint256 i = 0; i < _proof.length; i++) {
			bytes32 _proofElement = _proof[i];
			if (_computedHash <= _proofElement) {
				_computedHash = keccak256(abi.encodePacked(_computedHash, _proofElement));
			} else {
				_computedHash = keccak256(abi.encodePacked(_proofElement, _computedHash));
			}
		}
		return _computedHash == merkleRoot();
	}
}

File 1 of 8: ERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

interface ERC20 {
	function allowance(address, address) external view returns (uint256);
	function balanceOf(address) external view returns (uint256);
	function transfer(address, uint256) external returns (bool);
	function transferFrom(address, address, uint256) external returns (bool);
}

File 2 of 8: Metadata.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

import "./WTFNFT.sol";

interface PriceOracle {
	function getPrice() external view returns (uint256);
}


contract Metadata {
	
	string public name = "fees.wtf NFT";
	string public symbol = "fees.wtf";

	string constant private TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

	WTFNFT public nft;
	PriceOracle public oracle;

	constructor(WTFNFT _nft) {
		nft = _nft;
		oracle = PriceOracle(0xe89b5B2770Aa1a6BcfAc6F3517510aB8e9146651);
	}

	function setPriceOracle(PriceOracle _oracle) external {
		require(msg.sender == nft.owner());
		oracle = _oracle;
	}


	function tokenURI(uint256 _tokenId) external view returns (string memory) {
		( , , address _user, uint256[7] memory _info) = nft.getToken(_tokenId);
		return rawTokenURI(_user, _info[0], _info[1], _info[2], _info[3], _info[4], _info[5], _info[6], oracle.getPrice());
	}

	function rawTokenURI(address _user, uint256 _totalFees, uint256 _failFees, uint256 _totalGas, uint256 _avgGwei, uint256 _totalDonated, uint256 _totalTxs, uint256 _failTxs, uint256 _price) public pure returns (string memory) {
		string memory _json = string(abi.encodePacked('{"name":"', _trimAddress(_user, 6), '","description":"[fees.wtf](https://fees.wtf) snapshot at block 13916450 for [', _address2str(_user), '](https://etherscan.io/address/', _address2str(_user), ')",'));
		_json = string(abi.encodePacked(_json, '"image":"data:image/svg+xml;base64,', _encode(bytes(getRawSVG(_totalFees, _failFees, _totalGas, _avgGwei, _totalDonated, _totalTxs, _failTxs, _price))), '","attributes":['));
		if (_totalFees > 0) {
			_json = string(abi.encodePacked(_json, '{"trait_type":"Total Fees","value":', _uint2str(_totalFees, 18, 5, false, true), '}'));
			_json = string(abi.encodePacked(_json, ',{"trait_type":"Fail Fees","value":', _uint2str(_failFees, 18, 5, false, true), '}'));
			_json = string(abi.encodePacked(_json, ',{"trait_type":"Total Gas","value":', _uint2str(_totalGas, 0, 0, false, false), '}'));
			_json = string(abi.encodePacked(_json, ',{"trait_type":"Average Gwei","value":', _uint2str(_avgGwei, 9, 5, false, true), '}'));
			_json = string(abi.encodePacked(_json, ',{"trait_type":"Total Transactions","value":', _uint2str(_totalTxs, 0, 0, false, false), '}'));
			_json = string(abi.encodePacked(_json, ',{"trait_type":"Failed Transactions","value":', _uint2str(_failTxs, 0, 0, false, false), '}'));
			_json = string(abi.encodePacked(_json, ',{"display_type":"number","trait_type":"Spender Level","value":', _uint2str(_logn(_totalFees / 1e13, 2), 0, 0, false, false), '}'));
			_json = string(abi.encodePacked(_json, ',{"display_type":"number","trait_type":"Oof Level","value":', _uint2str(_logn(_failFees / 1e13, 2), 0, 0, false, false), '}'));
		}
		if (_totalDonated > 0) {
			_json = string(abi.encodePacked(_json, _totalFees > 0 ? ',' : '', '{"display_type":"number","trait_type":"Donator Level","value":', _uint2str(_logn(_totalDonated / 1e14, 10) + 1, 0, 0, false, false), '}'));
		}
		_json = string(abi.encodePacked(_json, ']}'));
		return string(abi.encodePacked("data:application/json;base64,", _encode(bytes(_json))));
	}

	function getSVG(uint256 _tokenId) public view returns (string memory) {
		uint256[7] memory _info = nft.getTokenCompressedInfo(_tokenId);
		return getRawSVG(_info[0], _info[1], _info[2], _info[3], _info[4], _info[5], _info[6], oracle.getPrice());
	}

	function getRawSVG(uint256 _totalFees, uint256 _failFees, uint256 _totalGas, uint256 _avgGwei, uint256 _totalDonated, uint256 _totalTxs, uint256 _failTxs, uint256 _price) public pure returns (string memory svg) {
		svg = string(abi.encodePacked("<svg xmlns='http://www.w3.org/2000/svg' version='1.1' preserveAspectRatio='xMidYMid meet' viewBox='0 0 512 512' width='100%' height='100%'>"));
		svg = string(abi.encodePacked(svg, "<defs><style type='text/css'>text{text-anchor:middle;alignment-baseline:central;}tspan>tspan{fill:#03a9f4;font-weight:700;}</style></defs>"));
		svg = string(abi.encodePacked(svg, "<rect width='100%' height='100%' fill='#222222' />"));
		svg = string(abi.encodePacked(svg, "<text x='0' y='256' transform='translate(256)' fill='#f0f8ff' font-family='Arial,sans-serif' font-weight='600' font-size='30'>"));
		if (_totalFees > 0) {
			svg = string(abi.encodePacked(svg, unicode"<tspan x='0' dy='-183'>You spent <tspan>Ξ", _uint2str(_totalFees, 18, 5, true, false), "</tspan> on gas</tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='35'>before block 13916450.</tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='35'>Right now, that's</tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='35'><tspan>$", _uint2str(_totalFees * _price / 1e18, 18, 2, true, true), "</tspan>.</tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='70'>You used <tspan>", _uint2str(_totalGas, 0, 0, true, false), "</tspan></tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='35'>gas to send <tspan>", _uint2str(_totalTxs, 0, 0, true, false), "</tspan></tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='35'>transaction", _totalTxs == 1 ? "" : "s", ", with an average</tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='35'>price of <tspan>", _uint2str(_avgGwei, 9, 3, true, false), "</tspan> Gwei.</tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='70'><tspan>", _uint2str(_failTxs, 0, 0, true, false), "</tspan> of them failed,</tspan>"));
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='35'>costing you <tspan>", _failFees == 0 ? "nothing" : string(abi.encodePacked(unicode"Ξ", _uint2str(_failFees, 18, 5, true, false))), "</tspan>.</tspan></text>"));
		} else {
			svg = string(abi.encodePacked(svg, "<tspan x='0' dy='8'>Did not qualify.</tspan></text>"));
		}
		if (_totalDonated > 0) {
			for (uint256 i = 0; i <= _logn(_totalDonated / 1e14, 10); i++) {
				for (uint256 j = 0; j < 4; j++) {
					string memory _prefix = string(abi.encodePacked("<text x='", j < 2 ? "16" : "496", "' y='", j % 2 == 0 ? "18" : "498", "' font-size='10' transform='translate("));
					svg = string(abi.encodePacked(svg, _prefix, j < 2 ? "" : "-", _uint2str(16 * i, 0, 0, false, false), ")'>", unicode"❤️</text>"));
					if (i > 0) {
						svg = string(abi.encodePacked(svg, _prefix, "0,", j % 2 == 0 ? "" : "-", _uint2str(16 * i, 0, 0, false, false), ")'>", unicode"❤️</text>"));
					}
				}
			}
		}
		svg = string(abi.encodePacked(svg, "<text x='0' y='500' transform='translate(256)' fill='#f0f8ff' font-family='Arial,sans-serif' font-weight='600' font-size='10'><tspan>fees<tspan>.wtf</tspan></tspan></text></svg>"));
	}


	function _logn(uint256 _num, uint256 _n) internal pure returns (uint256) {
		require(_n > 0);
		uint256 _count = 0;
		while (_num > _n - 1) {
			_num /= _n;
			_count++;
		}
		return _count;
	}
	
	function _address2str(address _address) internal pure returns (string memory str) {
		str = "0x";
		for (uint256 i; i < 40; i++) {
			uint256 _hex = (uint160(_address) >> (4 * (39 - i))) % 16;
			bytes memory _char = new bytes(1);
			_char[0] = bytes1(uint8(_hex) + (_hex > 9 ? 87 : 48));
			str = string(abi.encodePacked(str, string(_char)));
		}
	}

	function _trimAddress(address _address, uint256 _padding) internal pure returns (string memory str) {
		require(_padding < 20);
		str = "";
		bytes memory _strAddress = bytes(_address2str(_address));
		uint256 _length = 2 * _padding + 2;
		for (uint256 i = 0; i < 2 * _padding + 2; i++) {
			bytes memory _char = new bytes(1);
			_char[0] = _strAddress[i < _padding + 2 ? i : 42 + i - _length];
			str = string(abi.encodePacked(str, string(_char)));
			if (i == _padding + 1) {
				str = string(abi.encodePacked(str, unicode"…"));
			}
		}
	}
	
	function _uint2str(uint256 _value, uint256 _scale, uint256 _maxDecimals, bool _commas, bool _full) internal pure returns (string memory str) {
		uint256 _d = _scale > _maxDecimals ? _maxDecimals : _scale;
		uint256 _n = _value / 10**(_scale > _d ? _scale - _d : 0);
		if (_n == 0) {
			return "0";
		}
		uint256 _digits = 1;
		uint256 _tmp = _n;
		while (_tmp > 9) {
			_tmp /= 10;
			_digits++;
		}
		_tmp = _digits > _d ? _digits : _d + 1;
		uint256 _offset = (!_full && _tmp > _d + 1 ? _tmp - _d - 1 > _d ? _d : _tmp - _d - 1 : 0);
		for (uint256 i = 0; i < _tmp - _offset; i++) {
			uint256 _dec = i < _tmp - _digits ? 0 : (_n / (10**(_tmp - i - 1))) % 10;
			bytes memory _char = new bytes(1);
			_char[0] = bytes1(uint8(_dec) + 48);
			str = string(abi.encodePacked(str, string(_char)));
			if (i < _tmp - _d - 1) {
				if (_commas && (i + 1) % 3 == (_tmp - _d) % 3) {
					str = string(abi.encodePacked(str, ","));
				}
			} else {
				if (!_full && (_n / 10**_offset) % 10**(_tmp - _offset - i - 1) == 0) {
					break;
				} else if (i == _tmp - _d - 1) {
					str = string(abi.encodePacked(str, "."));
				}
			}
		}
	}
	
	function _encode(bytes memory _data) internal pure returns (string memory result) {
		if (_data.length == 0) return '';
		string memory _table = TABLE;
		uint256 _encodedLen = 4 * ((_data.length + 2) / 3);
		result = new string(_encodedLen + 32);

		assembly {
			mstore(result, _encodedLen)
			let tablePtr := add(_table, 1)
			let dataPtr := _data
			let endPtr := add(dataPtr, mload(_data))
			let resultPtr := add(result, 32)

			for {} lt(dataPtr, endPtr) {}
			{
				dataPtr := add(dataPtr, 3)
				let input := mload(dataPtr)
				mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F)))))
				resultPtr := add(resultPtr, 1)
				mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F)))))
				resultPtr := add(resultPtr, 1)
				mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr( 6, input), 0x3F)))))
				resultPtr := add(resultPtr, 1)
				mstore(resultPtr, shl(248, mload(add(tablePtr, and(        input,  0x3F)))))
				resultPtr := add(resultPtr, 1)
			}
			switch mod(mload(_data), 3)
			case 1 { mstore(sub(resultPtr, 2), shl(240, 0x3d3d)) }
			case 2 { mstore(sub(resultPtr, 1), shl(248, 0x3d)) }
		}
		return result;
	}
}

File 3 of 8: PRBMath.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.4;

/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivFixedPointOverflow(uint256 prod1);

/// @notice Emitted when the result overflows uint256.
error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);

/// @notice Emitted when one of the inputs is type(int256).min.
error PRBMath__MulDivSignedInputTooSmall();

/// @notice Emitted when the intermediary absolute result overflows int256.
error PRBMath__MulDivSignedOverflow(uint256 rAbs);

/// @notice Emitted when the input is MIN_SD59x18.
error PRBMathSD59x18__AbsInputTooSmall();

/// @notice Emitted when ceiling a number overflows SD59x18.
error PRBMathSD59x18__CeilOverflow(int256 x);

/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__DivInputTooSmall();

/// @notice Emitted when one of the intermediary unsigned results overflows SD59x18.
error PRBMathSD59x18__DivOverflow(uint256 rAbs);

/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathSD59x18__ExpInputTooBig(int256 x);

/// @notice Emitted when the input is greater than 192.
error PRBMathSD59x18__Exp2InputTooBig(int256 x);

/// @notice Emitted when flooring a number underflows SD59x18.
error PRBMathSD59x18__FloorUnderflow(int256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format overflows SD59x18.
error PRBMathSD59x18__FromIntOverflow(int256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format underflows SD59x18.
error PRBMathSD59x18__FromIntUnderflow(int256 x);

/// @notice Emitted when the product of the inputs is negative.
error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);

/// @notice Emitted when multiplying the inputs overflows SD59x18.
error PRBMathSD59x18__GmOverflow(int256 x, int256 y);

/// @notice Emitted when the input is less than or equal to zero.
error PRBMathSD59x18__LogInputTooSmall(int256 x);

/// @notice Emitted when one of the inputs is MIN_SD59x18.
error PRBMathSD59x18__MulInputTooSmall();

/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__MulOverflow(uint256 rAbs);

/// @notice Emitted when the intermediary absolute result overflows SD59x18.
error PRBMathSD59x18__PowuOverflow(uint256 rAbs);

/// @notice Emitted when the input is negative.
error PRBMathSD59x18__SqrtNegativeInput(int256 x);

/// @notice Emitted when the calculating the square root overflows SD59x18.
error PRBMathSD59x18__SqrtOverflow(int256 x);

/// @notice Emitted when addition overflows UD60x18.
error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);

/// @notice Emitted when ceiling a number overflows UD60x18.
error PRBMathUD60x18__CeilOverflow(uint256 x);

/// @notice Emitted when the input is greater than 133.084258667509499441.
error PRBMathUD60x18__ExpInputTooBig(uint256 x);

/// @notice Emitted when the input is greater than 192.
error PRBMathUD60x18__Exp2InputTooBig(uint256 x);

/// @notice Emitted when converting a basic integer to the fixed-point format format overflows UD60x18.
error PRBMathUD60x18__FromUintOverflow(uint256 x);

/// @notice Emitted when multiplying the inputs overflows UD60x18.
error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);

/// @notice Emitted when the input is less than 1.
error PRBMathUD60x18__LogInputTooSmall(uint256 x);

/// @notice Emitted when the calculating the square root overflows UD60x18.
error PRBMathUD60x18__SqrtOverflow(uint256 x);

/// @notice Emitted when subtraction underflows UD60x18.
error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);

/// @dev Common mathematical functions used in both PRBMathSD59x18 and PRBMathUD60x18. Note that this shared library
/// does not always assume the signed 59.18-decimal fixed-point or the unsigned 60.18-decimal fixed-point
/// representation. When it does not, it is explicitly mentioned in the NatSpec documentation.
library PRBMath {
	/// STRUCTS ///

	struct SD59x18 {
		int256 value;
	}

	struct UD60x18 {
		uint256 value;
	}

	/// STORAGE ///

	/// @dev How many trailing decimals can be represented.
	uint256 internal constant SCALE = 1e18;

	/// @dev Largest power of two divisor of SCALE.
	uint256 internal constant SCALE_LPOTD = 262144;

	/// @dev SCALE inverted mod 2^256.
	uint256 internal constant SCALE_INVERSE =
		78156646155174841979727994598816262306175212592076161876661_508869554232690281;

	/// FUNCTIONS ///

	/// @notice Calculates the binary exponent of x using the binary fraction method.
	/// @dev Has to use 192.64-bit fixed-point numbers.
	/// See https://ethereum.stackexchange.com/a/96594/24693.
	/// @param x The exponent as an unsigned 192.64-bit fixed-point number.
	/// @return result The result as an unsigned 60.18-decimal fixed-point number.
	function exp2(uint256 x) internal pure returns (uint256 result) {
		unchecked {
			// Start from 0.5 in the 192.64-bit fixed-point format.
			result = 0x800000000000000000000000000000000000000000000000;

			// Multiply the result by root(2, 2^-i) when the bit at position i is 1. None of the intermediary results overflows
			// because the initial result is 2^191 and all magic factors are less than 2^65.
			if (x & 0x8000000000000000 > 0) {
				result = (result * 0x16A09E667F3BCC909) >> 64;
			}
			if (x & 0x4000000000000000 > 0) {
				result = (result * 0x1306FE0A31B7152DF) >> 64;
			}
			if (x & 0x2000000000000000 > 0) {
				result = (result * 0x1172B83C7D517ADCE) >> 64;
			}
			if (x & 0x1000000000000000 > 0) {
				result = (result * 0x10B5586CF9890F62A) >> 64;
			}
			if (x & 0x800000000000000 > 0) {
				result = (result * 0x1059B0D31585743AE) >> 64;
			}
			if (x & 0x400000000000000 > 0) {
				result = (result * 0x102C9A3E778060EE7) >> 64;
			}
			if (x & 0x200000000000000 > 0) {
				result = (result * 0x10163DA9FB33356D8) >> 64;
			}
			if (x & 0x100000000000000 > 0) {
				result = (result * 0x100B1AFA5ABCBED61) >> 64;
			}
			if (x & 0x80000000000000 > 0) {
				result = (result * 0x10058C86DA1C09EA2) >> 64;
			}
			if (x & 0x40000000000000 > 0) {
				result = (result * 0x1002C605E2E8CEC50) >> 64;
			}
			if (x & 0x20000000000000 > 0) {
				result = (result * 0x100162F3904051FA1) >> 64;
			}
			if (x & 0x10000000000000 > 0) {
				result = (result * 0x1000B175EFFDC76BA) >> 64;
			}
			if (x & 0x8000000000000 > 0) {
				result = (result * 0x100058BA01FB9F96D) >> 64;
			}
			if (x & 0x4000000000000 > 0) {
				result = (result * 0x10002C5CC37DA9492) >> 64;
			}
			if (x & 0x2000000000000 > 0) {
				result = (result * 0x1000162E525EE0547) >> 64;
			}
			if (x & 0x1000000000000 > 0) {
				result = (result * 0x10000B17255775C04) >> 64;
			}
			if (x & 0x800000000000 > 0) {
				result = (result * 0x1000058B91B5BC9AE) >> 64;
			}
			if (x & 0x400000000000 > 0) {
				result = (result * 0x100002C5C89D5EC6D) >> 64;
			}
			if (x & 0x200000000000 > 0) {
				result = (result * 0x10000162E43F4F831) >> 64;
			}
			if (x & 0x100000000000 > 0) {
				result = (result * 0x100000B1721BCFC9A) >> 64;
			}
			if (x & 0x80000000000 > 0) {
				result = (result * 0x10000058B90CF1E6E) >> 64;
			}
			if (x & 0x40000000000 > 0) {
				result = (result * 0x1000002C5C863B73F) >> 64;
			}
			if (x & 0x20000000000 > 0) {
				result = (result * 0x100000162E430E5A2) >> 64;
			}
			if (x & 0x10000000000 > 0) {
				result = (result * 0x1000000B172183551) >> 64;
			}
			if (x & 0x8000000000 > 0) {
				result = (result * 0x100000058B90C0B49) >> 64;
			}
			if (x & 0x4000000000 > 0) {
				result = (result * 0x10000002C5C8601CC) >> 64;
			}
			if (x & 0x2000000000 > 0) {
				result = (result * 0x1000000162E42FFF0) >> 64;
			}
			if (x & 0x1000000000 > 0) {
				result = (result * 0x10000000B17217FBB) >> 64;
			}
			if (x & 0x800000000 > 0) {
				result = (result * 0x1000000058B90BFCE) >> 64;
			}
			if (x & 0x400000000 > 0) {
				result = (result * 0x100000002C5C85FE3) >> 64;
			}
			if (x & 0x200000000 > 0) {
				result = (result * 0x10000000162E42FF1) >> 64;
			}
			if (x & 0x100000000 > 0) {
				result = (result * 0x100000000B17217F8) >> 64;
			}
			if (x & 0x80000000 > 0) {
				result = (result * 0x10000000058B90BFC) >> 64;
			}
			if (x & 0x40000000 > 0) {
				result = (result * 0x1000000002C5C85FE) >> 64;
			}
			if (x & 0x20000000 > 0) {
				result = (result * 0x100000000162E42FF) >> 64;
			}
			if (x & 0x10000000 > 0) {
				result = (result * 0x1000000000B17217F) >> 64;
			}
			if (x & 0x8000000 > 0) {
				result = (result * 0x100000000058B90C0) >> 64;
			}
			if (x & 0x4000000 > 0) {
				result = (result * 0x10000000002C5C860) >> 64;
			}
			if (x & 0x2000000 > 0) {
				result = (result * 0x1000000000162E430) >> 64;
			}
			if (x & 0x1000000 > 0) {
				result = (result * 0x10000000000B17218) >> 64;
			}
			if (x & 0x800000 > 0) {
				result = (result * 0x1000000000058B90C) >> 64;
			}
			if (x & 0x400000 > 0) {
				result = (result * 0x100000000002C5C86) >> 64;
			}
			if (x & 0x200000 > 0) {
				result = (result * 0x10000000000162E43) >> 64;
			}
			if (x & 0x100000 > 0) {
				result = (result * 0x100000000000B1721) >> 64;
			}
			if (x & 0x80000 > 0) {
				result = (result * 0x10000000000058B91) >> 64;
			}
			if (x & 0x40000 > 0) {
				result = (result * 0x1000000000002C5C8) >> 64;
			}
			if (x & 0x20000 > 0) {
				result = (result * 0x100000000000162E4) >> 64;
			}
			if (x & 0x10000 > 0) {
				result = (result * 0x1000000000000B172) >> 64;
			}
			if (x & 0x8000 > 0) {
				result = (result * 0x100000000000058B9) >> 64;
			}
			if (x & 0x4000 > 0) {
				result = (result * 0x10000000000002C5D) >> 64;
			}
			if (x & 0x2000 > 0) {
				result = (result * 0x1000000000000162E) >> 64;
			}
			if (x & 0x1000 > 0) {
				result = (result * 0x10000000000000B17) >> 64;
			}
			if (x & 0x800 > 0) {
				result = (result * 0x1000000000000058C) >> 64;
			}
			if (x & 0x400 > 0) {
				result = (result * 0x100000000000002C6) >> 64;
			}
			if (x & 0x200 > 0) {
				result = (result * 0x10000000000000163) >> 64;
			}
			if (x & 0x100 > 0) {
				result = (result * 0x100000000000000B1) >> 64;
			}
			if (x & 0x80 > 0) {
				result = (result * 0x10000000000000059) >> 64;
			}
			if (x & 0x40 > 0) {
				result = (result * 0x1000000000000002C) >> 64;
			}
			if (x & 0x20 > 0) {
				result = (result * 0x10000000000000016) >> 64;
			}
			if (x & 0x10 > 0) {
				result = (result * 0x1000000000000000B) >> 64;
			}
			if (x & 0x8 > 0) {
				result = (result * 0x10000000000000006) >> 64;
			}
			if (x & 0x4 > 0) {
				result = (result * 0x10000000000000003) >> 64;
			}
			if (x & 0x2 > 0) {
				result = (result * 0x10000000000000001) >> 64;
			}
			if (x & 0x1 > 0) {
				result = (result * 0x10000000000000001) >> 64;
			}

			// We're doing two things at the same time:
			//
			//   1. Multiply the result by 2^n + 1, where "2^n" is the integer part and the one is added to account for
			//      the fact that we initially set the result to 0.5. This is accomplished by subtracting from 191
			//      rather than 192.
			//   2. Convert the result to the unsigned 60.18-decimal fixed-point format.
			//
			// This works because 2^(191-ip) = 2^ip / 2^191, where "ip" is the integer part "2^n".
			result *= SCALE;
			result >>= (191 - (x >> 64));
		}
	}

	/// @notice Finds the zero-based index of the first one in the binary representation of x.
	/// @dev See the note on msb in the "Find First Set" Wikipedia article https://en.wikipedia.org/wiki/Find_first_set
	/// @param x The uint256 number for which to find the index of the most significant bit.
	/// @return msb The index of the most significant bit as an uint256.
	function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
		if (x >= 2**128) {
			x >>= 128;
			msb += 128;
		}
		if (x >= 2**64) {
			x >>= 64;
			msb += 64;
		}
		if (x >= 2**32) {
			x >>= 32;
			msb += 32;
		}
		if (x >= 2**16) {
			x >>= 16;
			msb += 16;
		}
		if (x >= 2**8) {
			x >>= 8;
			msb += 8;
		}
		if (x >= 2**4) {
			x >>= 4;
			msb += 4;
		}
		if (x >= 2**2) {
			x >>= 2;
			msb += 2;
		}
		if (x >= 2**1) {
			// No need to shift x any more.
			msb += 1;
		}
	}

	/// @notice Calculates floor(x*y÷denominator) with full precision.
	///
	/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.
	///
	/// Requirements:
	/// - The denominator cannot be zero.
	/// - The result must fit within uint256.
	///
	/// Caveats:
	/// - This function does not work with fixed-point numbers.
	///
	/// @param x The multiplicand as an uint256.
	/// @param y The multiplier as an uint256.
	/// @param denominator The divisor as an uint256.
	/// @return result The result as an uint256.
	function mulDiv(
		uint256 x,
		uint256 y,
		uint256 denominator
	) internal pure returns (uint256 result) {
		// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
		// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
		// variables such that product = prod1 * 2^256 + prod0.
		uint256 prod0; // Least significant 256 bits of the product
		uint256 prod1; // Most significant 256 bits of the product
		assembly {
			let mm := mulmod(x, y, not(0))
			prod0 := mul(x, y)
			prod1 := sub(sub(mm, prod0), lt(mm, prod0))
		}

		// Handle non-overflow cases, 256 by 256 division.
		if (prod1 == 0) {
			unchecked {
				result = prod0 / denominator;
			}
			return result;
		}

		// Make sure the result is less than 2^256. Also prevents denominator == 0.
		if (prod1 >= denominator) {
			revert PRBMath__MulDivOverflow(prod1, denominator);
		}

		///////////////////////////////////////////////
		// 512 by 256 division.
		///////////////////////////////////////////////

		// Make division exact by subtracting the remainder from [prod1 prod0].
		uint256 remainder;
		assembly {
			// Compute remainder using mulmod.
			remainder := mulmod(x, y, denominator)

			// Subtract 256 bit number from 512 bit number.
			prod1 := sub(prod1, gt(remainder, prod0))
			prod0 := sub(prod0, remainder)
		}

		// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
		// See https://cs.stackexchange.com/q/138556/92363.
		unchecked {
			// Does not overflow because the denominator cannot be zero at this stage in the function.
			uint256 lpotdod = denominator & (~denominator + 1);
			assembly {
				// Divide denominator by lpotdod.
				denominator := div(denominator, lpotdod)

				// Divide [prod1 prod0] by lpotdod.
				prod0 := div(prod0, lpotdod)

				// Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one.
				lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
			}

			// Shift in bits from prod1 into prod0.
			prod0 |= prod1 * lpotdod;

			// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
			// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
			// four bits. That is, denominator * inv = 1 mod 2^4.
			uint256 inverse = (3 * denominator) ^ 2;

			// Use the 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.
			inverse *= 2 - denominator * inverse; // inverse mod 2^8
			inverse *= 2 - denominator * inverse; // inverse mod 2^16
			inverse *= 2 - denominator * inverse; // inverse mod 2^32
			inverse *= 2 - denominator * inverse; // inverse mod 2^64
			inverse *= 2 - denominator * inverse; // inverse mod 2^128
			inverse *= 2 - denominator * inverse; // inverse mod 2^256

			// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
			// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
			// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
			// is no longer required.
			result = prod0 * inverse;
			return result;
		}
	}

	/// @notice Calculates floor(x*y÷1e18) with full precision.
	///
	/// @dev Variant of "mulDiv" with constant folding, i.e. in which the denominator is always 1e18. Before returning the
	/// final result, we add 1 if (x * y) % SCALE >= HALF_SCALE. Without this, 6.6e-19 would be truncated to 0 instead of
	/// being rounded to 1e-18.  See "Listing 6" and text above it at https://accu.org/index.php/journals/1717.
	///
	/// Requirements:
	/// - The result must fit within uint256.
	///
	/// Caveats:
	/// - The body is purposely left uncommented; see the NatSpec comments in "PRBMath.mulDiv" to understand how this works.
	/// - It is assumed that the result can never be type(uint256).max when x and y solve the following two equations:
	///     1. x * y = type(uint256).max * SCALE
	///     2. (x * y) % SCALE >= SCALE / 2
	///
	/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
	/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
	/// @return result The result as an unsigned 60.18-decimal fixed-point number.
	function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {
		uint256 prod0;
		uint256 prod1;
		assembly {
			let mm := mulmod(x, y, not(0))
			prod0 := mul(x, y)
			prod1 := sub(sub(mm, prod0), lt(mm, prod0))
		}

		if (prod1 >= SCALE) {
			revert PRBMath__MulDivFixedPointOverflow(prod1);
		}

		uint256 remainder;
		uint256 roundUpUnit;
		assembly {
			remainder := mulmod(x, y, SCALE)
			roundUpUnit := gt(remainder, 499999999999999999)
		}

		if (prod1 == 0) {
			unchecked {
				result = (prod0 / SCALE) + roundUpUnit;
				return result;
			}
		}

		assembly {
			result := add(
				mul(
					or(
						div(sub(prod0, remainder), SCALE_LPOTD),
						mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))
					),
					SCALE_INVERSE
				),
				roundUpUnit
			)
		}
	}

	/// @notice Calculates floor(x*y÷denominator) with full precision.
	///
	/// @dev An extension of "mulDiv" for signed numbers. Works by computing the signs and the absolute values separately.
	///
	/// Requirements:
	/// - None of the inputs can be type(int256).min.
	/// - The result must fit within int256.
	///
	/// @param x The multiplicand as an int256.
	/// @param y The multiplier as an int256.
	/// @param denominator The divisor as an int256.
	/// @return result The result as an int256.
	function mulDivSigned(
		int256 x,
		int256 y,
		int256 denominator
	) internal pure returns (int256 result) {
		if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
			revert PRBMath__MulDivSignedInputTooSmall();
		}

		// Get hold of the absolute values of x, y and the denominator.
		uint256 ax;
		uint256 ay;
		uint256 ad;
		unchecked {
			ax = x < 0 ? uint256(-x) : uint256(x);
			ay = y < 0 ? uint256(-y) : uint256(y);
			ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);
		}

		// Compute the absolute value of (x*y)÷denominator. The result must fit within int256.
		uint256 rAbs = mulDiv(ax, ay, ad);
		if (rAbs > uint256(type(int256).max)) {
			revert PRBMath__MulDivSignedOverflow(rAbs);
		}

		// Get the signs of x, y and the denominator.
		uint256 sx;
		uint256 sy;
		uint256 sd;
		assembly {
			sx := sgt(x, sub(0, 1))
			sy := sgt(y, sub(0, 1))
			sd := sgt(denominator, sub(0, 1))
		}

		// XOR over sx, sy and sd. This is checking whether there are one or three negative signs in the inputs.
		// If yes, the result should be negative.
		result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
	}

	/// @notice Calculates the square root of x, rounding down.
	/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
	///
	/// Caveats:
	/// - This function does not work with fixed-point numbers.
	///
	/// @param x The uint256 number for which to calculate the square root.
	/// @return result The result as an uint256.
	function sqrt(uint256 x) internal pure returns (uint256 result) {
		if (x == 0) {
			return 0;
		}

		// Set the initial guess to the least power of two that is greater than or equal to sqrt(x).
		uint256 xAux = uint256(x);
		result = 1;
		if (xAux >= 0x100000000000000000000000000000000) {
			xAux >>= 128;
			result <<= 64;
		}
		if (xAux >= 0x10000000000000000) {
			xAux >>= 64;
			result <<= 32;
		}
		if (xAux >= 0x100000000) {
			xAux >>= 32;
			result <<= 16;
		}
		if (xAux >= 0x10000) {
			xAux >>= 16;
			result <<= 8;
		}
		if (xAux >= 0x100) {
			xAux >>= 8;
			result <<= 4;
		}
		if (xAux >= 0x10) {
			xAux >>= 4;
			result <<= 2;
		}
		if (xAux >= 0x8) {
			result <<= 1;
		}

		// The operations can never overflow because the result is max 2^127 when it enters this block.
		unchecked {
			result = (result + x / result) >> 1;
			result = (result + x / result) >> 1;
			result = (result + x / result) >> 1;
			result = (result + x / result) >> 1;
			result = (result + x / result) >> 1;
			result = (result + x / result) >> 1;
			result = (result + x / result) >> 1; // Seven iterations should be enough
			uint256 roundedDownResult = x / result;
			return result >= roundedDownResult ? roundedDownResult : result;
		}
	}
}

File 4 of 8: PRBMathUD60x18.sol
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.8.4;

import "./PRBMath.sol";

/// @title PRBMathUD60x18
/// @author Paul Razvan Berg
/// @notice Smart contract library for advanced fixed-point math that works with uint256 numbers considered to have 18
/// trailing decimals. We call this number representation unsigned 60.18-decimal fixed-point, since there can be up to 60
/// digits in the integer part and up to 18 decimals in the fractional part. The numbers are bound by the minimum and the
/// maximum values permitted by the Solidity type uint256.
library PRBMathUD60x18 {
	/// @dev Half the SCALE number.
	uint256 internal constant HALF_SCALE = 5e17;

	/// @dev log2(e) as an unsigned 60.18-decimal fixed-point number.
	uint256 internal constant LOG2_E = 1_442695040888963407;

	/// @dev The maximum value an unsigned 60.18-decimal fixed-point number can have.
	uint256 internal constant MAX_UD60x18 =
		115792089237316195423570985008687907853269984665640564039457_584007913129639935;

	/// @dev The maximum whole value an unsigned 60.18-decimal fixed-point number can have.
	uint256 internal constant MAX_WHOLE_UD60x18 =
		115792089237316195423570985008687907853269984665640564039457_000000000000000000;

	/// @dev How many trailing decimals can be represented.
	uint256 internal constant SCALE = 1e18;

	/// @notice Calculates the arithmetic average of x and y, rounding down.
	/// @param x The first operand as an unsigned 60.18-decimal fixed-point number.
	/// @param y The second operand as an unsigned 60.18-decimal fixed-point number.
	/// @return result The arithmetic average as an unsigned 60.18-decimal fixed-point number.
	function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {
		// The operations can never overflow.
		unchecked {
			// The last operand checks if both x and y are odd and if that is the case, we add 1 to the result. We need
			// to do this because if both numbers are odd, the 0.5 remainder gets truncated twice.
			result = (x >> 1) + (y >> 1) + (x & y & 1);
		}
	}

	/// @notice Yields the least unsigned 60.18 decimal fixed-point number greater than or equal to x.
	///
	/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
	/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
	///
	/// Requirements:
	/// - x must be less than or equal to MAX_WHOLE_UD60x18.
	///
	/// @param x The unsigned 60.18-decimal fixed-point number to ceil.
	/// @param result The least integer greater than or equal to x, as an unsigned 60.18-decimal fixed-point number.
	function ceil(uint256 x) internal pure returns (uint256 result) {
		if (x > MAX_WHOLE_UD60x18) {
			revert PRBMathUD60x18__CeilOverflow(x);
		}
		assembly {
			// Equivalent to "x % SCALE" but faster.
			let remainder := mod(x, SCALE)

			// Equivalent to "SCALE - remainder" but faster.
			let delta := sub(SCALE, remainder)

			// Equivalent to "x + delta * (remainder > 0 ? 1 : 0)" but faster.
			result := add(x, mul(delta, gt(remainder, 0)))
		}
	}

	/// @notice Divides two unsigned 60.18-decimal fixed-point numbers, returning a new unsigned 60.18-decimal fixed-point number.
	///
	/// @dev Uses mulDiv to enable overflow-safe multiplication and division.
	///
	/// Requirements:
	/// - The denominator cannot be zero.
	///
	/// @param x The numerator as an unsigned 60.18-decimal fixed-point number.
	/// @param y The denominator as an unsigned 60.18-decimal fixed-point number.
	/// @param result The quotient as an unsigned 60.18-decimal fixed-point number.
	function div(uint256 x, uint256 y) internal pure returns (uint256 result) {
		result = PRBMath.mulDiv(x, SCALE, y);
	}

	/// @notice Returns Euler's number as an unsigned 60.18-decimal fixed-point number.
	/// @dev See https://en.wikipedia.org/wiki/E_(mathematical_constant).
	function e() internal pure returns (uint256 result) {
		result = 2_718281828459045235;
	}

	/// @notice Calculates the natural exponent of x.
	///
	/// @dev Based on the insight that e^x = 2^(x * log2(e)).
	///
	/// Requirements:
	/// - All from "log2".
	/// - x must be less than 133.084258667509499441.
	///
	/// @param x The exponent as an unsigned 60.18-decimal fixed-point number.
	/// @return result The result as an unsigned 60.18-decimal fixed-point number.
	function exp(uint256 x) internal pure returns (uint256 result) {
		// Without this check, the value passed to "exp2" would be greater than 192.
		if (x >= 133_084258667509499441) {
			revert PRBMathUD60x18__ExpInputTooBig(x);
		}

		// Do the fixed-point multiplication inline to save gas.
		unchecked {
			uint256 doubleScaleProduct = x * LOG2_E;
			result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);
		}
	}

	/// @notice Calculates the binary exponent of x using the binary fraction method.
	///
	/// @dev See https://ethereum.stackexchange.com/q/79903/24693.
	///
	/// Requirements:
	/// - x must be 192 or less.
	/// - The result must fit within MAX_UD60x18.
	///
	/// @param x The exponent as an unsigned 60.18-decimal fixed-point number.
	/// @return result The result as an unsigned 60.18-decimal fixed-point number.
	function exp2(uint256 x) internal pure returns (uint256 result) {
		// 2^192 doesn't fit within the 192.64-bit format used internally in this function.
		if (x >= 192e18) {
			revert PRBMathUD60x18__Exp2InputTooBig(x);
		}

		unchecked {
			// Convert x to the 192.64-bit fixed-point format.
			uint256 x192x64 = (x << 64) / SCALE;

			// Pass x to the PRBMath.exp2 function, which uses the 192.64-bit fixed-point number representation.
			result = PRBMath.exp2(x192x64);
		}
	}

	/// @notice Yields the greatest unsigned 60.18 decimal fixed-point number less than or equal to x.
	/// @dev Optimized for fractional value inputs, because for every whole value there are (1e18 - 1) fractional counterparts.
	/// See https://en.wikipedia.org/wiki/Floor_and_ceiling_functions.
	/// @param x The unsigned 60.18-decimal fixed-point number to floor.
	/// @param result The greatest integer less than or equal to x, as an unsigned 60.18-decimal fixed-point number.
	function floor(uint256 x) internal pure returns (uint256 result) {
		assembly {
			// Equivalent to "x % SCALE" but faster.
			let remainder := mod(x, SCALE)

			// Equivalent to "x - remainder * (remainder > 0 ? 1 : 0)" but faster.
			result := sub(x, mul(remainder, gt(remainder, 0)))
		}
	}

	/// @notice Yields the excess beyond the floor of x.
	/// @dev Based on the odd function definition https://en.wikipedia.org/wiki/Fractional_part.
	/// @param x The unsigned 60.18-decimal fixed-point number to get the fractional part of.
	/// @param result The fractional part of x as an unsigned 60.18-decimal fixed-point number.
	function frac(uint256 x) internal pure returns (uint256 result) {
		assembly {
			result := mod(x, SCALE)
		}
	}

	/// @notice Converts a number from basic integer form to unsigned 60.18-decimal fixed-point representation.
	///
	/// @dev Requirements:
	/// - x must be less than or equal to MAX_UD60x18 divided by SCALE.
	///
	/// @param x The basic integer to convert.
	/// @param result The same number in unsigned 60.18-decimal fixed-point representation.
	function fromUint(uint256 x) internal pure returns (uint256 result) {
		unchecked {
			if (x > MAX_UD60x18 / SCALE) {
				revert PRBMathUD60x18__FromUintOverflow(x);
			}
			result = x * SCALE;
		}
	}

	/// @notice Calculates geometric mean of x and y, i.e. sqrt(x * y), rounding down.
	///
	/// @dev Requirements:
	/// - x * y must fit within MAX_UD60x18, lest it overflows.
	///
	/// @param x The first operand as an unsigned 60.18-decimal fixed-point number.
	/// @param y The second operand as an unsigned 60.18-decimal fixed-point number.
	/// @return result The result as an unsigned 60.18-decimal fixed-point number.
	function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {
		if (x == 0) {
			return 0;
		}

		unchecked {
			// Checking for overflow this way is faster than letting Solidity do it.
			uint256 xy = x * y;
			if (xy / x != y) {
				revert PRBMathUD60x18__GmOverflow(x, y);
			}

			// We don't need to multiply by the SCALE here because the x*y product had already picked up a factor of SCALE
			// during multiplication. See the comments within the "sqrt" function.
			result = PRBMath.sqrt(xy);
		}
	}

	/// @notice Calculates 1 / x, rounding toward zero.
	///
	/// @dev Requirements:
	/// - x cannot be zero.
	///
	/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the inverse.
	/// @return result The inverse as an unsigned 60.18-decimal fixed-point number.
	function inv(uint256 x) internal pure returns (uint256 result) {
		unchecked {
			// 1e36 is SCALE * SCALE.
			result = 1e36 / x;
		}
	}

	/// @notice Calculates the natural logarithm of x.
	///
	/// @dev Based on the insight that ln(x) = log2(x) / log2(e).
	///
	/// Requirements:
	/// - All from "log2".
	///
	/// Caveats:
	/// - All from "log2".
	/// - This doesn't return exactly 1 for 2.718281828459045235, for that we would need more fine-grained precision.
	///
	/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the natural logarithm.
	/// @return result The natural logarithm as an unsigned 60.18-decimal fixed-point number.
	function ln(uint256 x) internal pure returns (uint256 result) {
		// Do the fixed-point multiplication inline to save gas. This is overflow-safe because the maximum value that log2(x)
		// can return is 196205294292027477728.
		unchecked {
			result = (log2(x) * SCALE) / LOG2_E;
		}
	}

	/// @notice Calculates the common logarithm of x.
	///
	/// @dev First checks if x is an exact power of ten and it stops if yes. If it's not, calculates the common
	/// logarithm based on the insight that log10(x) = log2(x) / log2(10).
	///
	/// Requirements:
	/// - All from "log2".
	///
	/// Caveats:
	/// - All from "log2".
	///
	/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the common logarithm.
	/// @return result The common logarithm as an unsigned 60.18-decimal fixed-point number.
	function log10(uint256 x) internal pure returns (uint256 result) {
		if (x < SCALE) {
			revert PRBMathUD60x18__LogInputTooSmall(x);
		}

		// Note that the "mul" in this block is the assembly multiplication operation, not the "mul" function defined
		// in this contract.
		// prettier-ignore
		assembly {
			switch x
			case 1 { result := mul(SCALE, sub(0, 18)) }
			case 10 { result := mul(SCALE, sub(1, 18)) }
			case 100 { result := mul(SCALE, sub(2, 18)) }
			case 1000 { result := mul(SCALE, sub(3, 18)) }
			case 10000 { result := mul(SCALE, sub(4, 18)) }
			case 100000 { result := mul(SCALE, sub(5, 18)) }
			case 1000000 { result := mul(SCALE, sub(6, 18)) }
			case 10000000 { result := mul(SCALE, sub(7, 18)) }
			case 100000000 { result := mul(SCALE, sub(8, 18)) }
			case 1000000000 { result := mul(SCALE, sub(9, 18)) }
			case 10000000000 { result := mul(SCALE, sub(10, 18)) }
			case 100000000000 { result := mul(SCALE, sub(11, 18)) }
			case 1000000000000 { result := mul(SCALE, sub(12, 18)) }
			case 10000000000000 { result := mul(SCALE, sub(13, 18)) }
			case 100000000000000 { result := mul(SCALE, sub(14, 18)) }
			case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }
			case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }
			case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }
			case 1000000000000000000 { result := 0 }
			case 10000000000000000000 { result := SCALE }
			case 100000000000000000000 { result := mul(SCALE, 2) }
			case 1000000000000000000000 { result := mul(SCALE, 3) }
			case 10000000000000000000000 { result := mul(SCALE, 4) }
			case 100000000000000000000000 { result := mul(SCALE, 5) }
			case 1000000000000000000000000 { result := mul(SCALE, 6) }
			case 10000000000000000000000000 { result := mul(SCALE, 7) }
			case 100000000000000000000000000 { result := mul(SCALE, 8) }
			case 1000000000000000000000000000 { result := mul(SCALE, 9) }
			case 10000000000000000000000000000 { result := mul(SCALE, 10) }
			case 100000000000000000000000000000 { result := mul(SCALE, 11) }
			case 1000000000000000000000000000000 { result := mul(SCALE, 12) }
			case 10000000000000000000000000000000 { result := mul(SCALE, 13) }
			case 100000000000000000000000000000000 { result := mul(SCALE, 14) }
			case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }
			case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }
			case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }
			case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }
			case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }
			case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }
			case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }
			case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }
			case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }
			case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }
			case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }
			case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }
			case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }
			case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }
			case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }
			case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }
			case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }
			case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }
			case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }
			case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }
			case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }
			case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }
			case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }
			case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }
			case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }
			case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }
			case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }
			case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }
			case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }
			case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }
			case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }
			case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }
			case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }
			case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }
			case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }
			case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }
			case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }
			case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }
			case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }
			case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }
			case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }
			case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }
			case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }
			case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }
			case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }
			default {
				result := MAX_UD60x18
			}
		}

		if (result == MAX_UD60x18) {
			// Do the fixed-point division inline to save gas. The denominator is log2(10).
			unchecked {
				result = (log2(x) * SCALE) / 3_321928094887362347;
			}
		}
	}

	/// @notice Calculates the binary logarithm of x.
	///
	/// @dev Based on the iterative approximation algorithm.
	/// https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation
	///
	/// Requirements:
	/// - x must be greater than or equal to SCALE, otherwise the result would be negative.
	///
	/// Caveats:
	/// - The results are nor perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation.
	///
	/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the binary logarithm.
	/// @return result The binary logarithm as an unsigned 60.18-decimal fixed-point number.
	function log2(uint256 x) internal pure returns (uint256 result) {
		if (x < SCALE) {
			revert PRBMathUD60x18__LogInputTooSmall(x);
		}
		unchecked {
			// Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n).
			uint256 n = PRBMath.mostSignificantBit(x / SCALE);

			// The integer part of the logarithm as an unsigned 60.18-decimal fixed-point number. The operation can't overflow
			// because n is maximum 255 and SCALE is 1e18.
			result = n * SCALE;

			// This is y = x * 2^(-n).
			uint256 y = x >> n;

			// If y = 1, the fractional part is zero.
			if (y == SCALE) {
				return result;
			}

			// Calculate the fractional part via the iterative approximation.
			// The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster.
			for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {
				y = (y * y) / SCALE;

				// Is y^2 > 2 and so in the range [2,4)?
				if (y >= 2 * SCALE) {
					// Add the 2^(-m) factor to the logarithm.
					result += delta;

					// Corresponds to z/2 on Wikipedia.
					y >>= 1;
				}
			}
		}
	}

	/// @notice Multiplies two unsigned 60.18-decimal fixed-point numbers together, returning a new unsigned 60.18-decimal
	/// fixed-point number.
	/// @dev See the documentation for the "PRBMath.mulDivFixedPoint" function.
	/// @param x The multiplicand as an unsigned 60.18-decimal fixed-point number.
	/// @param y The multiplier as an unsigned 60.18-decimal fixed-point number.
	/// @return result The product as an unsigned 60.18-decimal fixed-point number.
	function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {
		result = PRBMath.mulDivFixedPoint(x, y);
	}

	/// @notice Returns PI as an unsigned 60.18-decimal fixed-point number.
	function pi() internal pure returns (uint256 result) {
		result = 3_141592653589793238;
	}

	/// @notice Raises x to the power of y.
	///
	/// @dev Based on the insight that x^y = 2^(log2(x) * y).
	///
	/// Requirements:
	/// - All from "exp2", "log2" and "mul".
	///
	/// Caveats:
	/// - All from "exp2", "log2" and "mul".
	/// - Assumes 0^0 is 1.
	///
	/// @param x Number to raise to given power y, as an unsigned 60.18-decimal fixed-point number.
	/// @param y Exponent to raise x to, as an unsigned 60.18-decimal fixed-point number.
	/// @return result x raised to power y, as an unsigned 60.18-decimal fixed-point number.
	function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {
		if (x == 0) {
			result = y == 0 ? SCALE : uint256(0);
		} else {
			result = exp2(mul(log2(x), y));
		}
	}

	/// @notice Raises x (unsigned 60.18-decimal fixed-point number) to the power of y (basic unsigned integer) using the
	/// famous algorithm "exponentiation by squaring".
	///
	/// @dev See https://en.wikipedia.org/wiki/Exponentiation_by_squaring
	///
	/// Requirements:
	/// - The result must fit within MAX_UD60x18.
	///
	/// Caveats:
	/// - All from "mul".
	/// - Assumes 0^0 is 1.
	///
	/// @param x The base as an unsigned 60.18-decimal fixed-point number.
	/// @param y The exponent as an uint256.
	/// @return result The result as an unsigned 60.18-decimal fixed-point number.
	function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {
		// Calculate the first iteration of the loop in advance.
		result = y & 1 > 0 ? x : SCALE;

		// Equivalent to "for(y /= 2; y > 0; y /= 2)" but faster.
		for (y >>= 1; y > 0; y >>= 1) {
			x = PRBMath.mulDivFixedPoint(x, x);

			// Equivalent to "y % 2 == 1" but faster.
			if (y & 1 > 0) {
				result = PRBMath.mulDivFixedPoint(result, x);
			}
		}
	}

	/// @notice Returns 1 as an unsigned 60.18-decimal fixed-point number.
	function scale() internal pure returns (uint256 result) {
		result = SCALE;
	}

	/// @notice Calculates the square root of x, rounding down.
	/// @dev Uses the Babylonian method https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method.
	///
	/// Requirements:
	/// - x must be less than MAX_UD60x18 / SCALE.
	///
	/// @param x The unsigned 60.18-decimal fixed-point number for which to calculate the square root.
	/// @return result The result as an unsigned 60.18-decimal fixed-point .
	function sqrt(uint256 x) internal pure returns (uint256 result) {
		unchecked {
			if (x > MAX_UD60x18 / SCALE) {
				revert PRBMathUD60x18__SqrtOverflow(x);
			}
			// Multiply x by the SCALE to account for the factor of SCALE that is picked up when multiplying two unsigned
			// 60.18-decimal fixed-point numbers together (in this case, those two numbers are both the square root).
			result = PRBMath.sqrt(x * SCALE);
		}
	}

	/// @notice Converts a unsigned 60.18-decimal fixed-point number to basic integer form, rounding down in the process.
	/// @param x The unsigned 60.18-decimal fixed-point number to convert.
	/// @return result The same number in basic integer form.
	function toUint(uint256 x) internal pure returns (uint256 result) {
		unchecked {
			result = x / SCALE;
		}
	}
}

File 5 of 8: StakingRewards.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

import "./WTF.sol";
import "./ERC20.sol";
import "./PRBMathUD60x18.sol";

contract StakingRewards {

	using PRBMathUD60x18 for uint256;

	uint256 constant private FLOAT_SCALAR = 2**64;
	uint256 constant private PERCENT_FEE = 5; // only for WTF staking
	uint256 constant private X_TICK = 30 days;

	struct User {
		uint256 deposited;
		int256 scaledPayout;
	}

	struct Info {
		uint256 totalRewards;
		uint256 startTime;
		uint256 lastUpdated;
		uint256 pendingFee;
		uint256 scaledRewardsPerToken;
		uint256 totalDeposited;
		mapping(address => User) users;
		WTF wtf;
		ERC20 token;
	}
	Info private info;


	event Deposit(address indexed user, uint256 amount, uint256 fee);
	event Withdraw(address indexed user, uint256 amount, uint256 fee);
	event Claim(address indexed user, uint256 amount);
	event Reinvest(address indexed user, uint256 amount);
	event Reward(uint256 amount);


	constructor(uint256 _totalRewards, uint256 _stakingRewardsStart, ERC20 _token) {
		info.totalRewards = _totalRewards;
		info.startTime = block.timestamp < _stakingRewardsStart ? _stakingRewardsStart : block.timestamp;
		info.lastUpdated = startTime();
		info.wtf = WTF(msg.sender);
		info.token = _token;
	}

	function update() public {
		uint256 _now = block.timestamp;
		if (_now > info.lastUpdated && totalDeposited() > 0) {
			uint256 _reward = info.totalRewards.mul(_delta(_getX(info.lastUpdated), _getX(_now)));
			if (info.pendingFee > 0) {
				_reward += info.pendingFee;
				info.pendingFee = 0;
			}
			uint256 _balanceBefore = info.wtf.balanceOf(address(this));
			info.wtf.claimRewards();
			_reward += info.wtf.balanceOf(address(this)) - _balanceBefore;
			info.lastUpdated = _now;
			_disburse(_reward);
		}
	}

	function deposit(uint256 _amount) external {
		depositFor(msg.sender, _amount);
	}

	function depositFor(address _user, uint256 _amount) public {
		require(_amount > 0);
		update();
		uint256 _balanceBefore = info.token.balanceOf(address(this));
		info.token.transferFrom(msg.sender, address(this), _amount);
		uint256 _amountReceived = info.token.balanceOf(address(this)) - _balanceBefore;
		_deposit(_user, _amountReceived);
	}

	function tokenCallback(address _from, uint256 _tokens, bytes calldata) external returns (bool) {
		require(_isWTF() && msg.sender == tokenAddress());
		require(_tokens > 0);
		update();
		_deposit(_from, _tokens);
		return true;
	}

	function disburse(uint256 _amount) public {
		require(_amount > 0);
		update();
		uint256 _balanceBefore = info.wtf.balanceOf(address(this));
		info.wtf.transferFrom(msg.sender, address(this), _amount);
		uint256 _amountReceived = info.wtf.balanceOf(address(this)) - _balanceBefore;
		_processFee(_amountReceived);
	}

	function withdrawAll() public {
		uint256 _deposited = depositedOf(msg.sender);
		if (_deposited > 0) {
			withdraw(_deposited);
		}
	}

	function withdraw(uint256 _amount) public {
		require(_amount > 0 && _amount <= depositedOf(msg.sender));
		update();
		info.totalDeposited -= _amount;
		info.users[msg.sender].deposited -= _amount;
		info.users[msg.sender].scaledPayout -= int256(_amount * info.scaledRewardsPerToken);
		uint256 _fee = _calculateFee(_amount);
		info.token.transfer(msg.sender, _amount - _fee);
		_processFee(_fee);
		emit Withdraw(msg.sender, _amount, _fee);
	}

	function claim() public {
		update();
		uint256 _rewards = rewardsOf(msg.sender);
		if (_rewards > 0) {
			info.users[msg.sender].scaledPayout += int256(_rewards * FLOAT_SCALAR);
			info.wtf.transfer(msg.sender, _rewards);
			emit Claim(msg.sender, _rewards);
		}
	}

	function reinvest() public {
		require(_isWTF());
		update();
		uint256 _rewards = rewardsOf(msg.sender);
		if (_rewards > 0) {
			info.users[msg.sender].scaledPayout += int256(_rewards * FLOAT_SCALAR);
			_deposit(msg.sender, _rewards);
			emit Reinvest(msg.sender, _rewards);
		}
	}

	
	function wtfAddress() public view returns (address) {
		return address(info.wtf);
	}
	
	function tokenAddress() public view returns (address) {
		return address(info.token);
	}

	function startTime() public view returns (uint256) {
		return info.startTime;
	}

	function totalDeposited() public view returns (uint256) {
		return info.totalDeposited;
	}

	function depositedOf(address _user) public view returns (uint256) {
		return info.users[_user].deposited;
	}
	
	function rewardsOf(address _user) public view returns (uint256) {
		return uint256(int256(info.scaledRewardsPerToken * depositedOf(_user)) - info.users[_user].scaledPayout) / FLOAT_SCALAR;
	}
	
	function currentRatePerDay() public view returns (uint256) {
		if (block.timestamp < startTime()) {
			return info.totalRewards.mul(_delta(_getX(startTime()), _getX(startTime() + 24 hours)));
		} else {
			return info.totalRewards.mul(_delta(_getX(block.timestamp), _getX(block.timestamp + 24 hours)));
		}
	}

	function totalDistributed() public view returns (uint256) {
		return info.totalRewards.mul(_sum(_getX(block.timestamp)));
	}

	function allInfoFor(address _user) external view returns (uint256 startingTime, uint256 totalRewardsDistributed, uint256 rewardsRatePerDay, uint256 currentFeePercent, uint256 totalTokensDeposited, uint256 virtualRewards, uint256 userWTF, uint256 userBalance, uint256 userAllowance, uint256 userDeposited, uint256 userRewards) {
		startingTime = startTime();
		totalRewardsDistributed = totalDistributed();
		rewardsRatePerDay = currentRatePerDay();
		currentFeePercent = _calculateFee(1e20);
		totalTokensDeposited = totalDeposited();
		virtualRewards = block.timestamp > info.lastUpdated ? info.totalRewards.mul(_delta(_getX(info.lastUpdated), _getX(block.timestamp))) : 0;
		userWTF = info.wtf.balanceOf(_user);
		userBalance = info.token.balanceOf(_user);
		userAllowance = info.token.allowance(_user, address(this));
		userDeposited = depositedOf(_user);
		userRewards = rewardsOf(_user);
	}

	
	function _deposit(address _user, uint256 _amount) internal {
		uint256 _fee = _calculateFee(_amount);
		uint256 _deposited = _amount - _fee;
		info.totalDeposited += _deposited;
		info.users[_user].deposited += _deposited;
		info.users[_user].scaledPayout += int256(_deposited * info.scaledRewardsPerToken);
		_processFee(_fee);
		emit Deposit(_user, _amount, _fee);
	}
	
	function _processFee(uint256 _fee) internal {
		if (_fee > 0) {
			if (block.timestamp < startTime() || totalDeposited() == 0) {
				info.pendingFee += _fee;
			} else {
				_disburse(_fee);
			}
		}
	}

	function _disburse(uint256 _amount) internal {
		info.scaledRewardsPerToken += _amount * FLOAT_SCALAR / totalDeposited();
		emit Reward(_amount);
	}


	function _isWTF() internal view returns (bool) {
		return wtfAddress() == tokenAddress();
	}

	function _calculateFee(uint256 _amount) internal view returns (uint256) {
		return _isWTF() ? (_amount * PERCENT_FEE / 100).mul(1e18 - _sum(_getX(block.timestamp))) : 0;
	}
	
	function _getX(uint256 t) internal view returns (uint256) {
		uint256 _start = startTime();
		if (t < _start) {
			return 0;
		} else {
			return ((t - _start) * 1e18).div(X_TICK * 1e18);
		}
	}

	function _sum(uint256 x) internal pure returns (uint256) {
		uint256 _e2x = x.exp2();
		return (_e2x - 1e18).div(_e2x);
	}

	function _delta(uint256 x1, uint256 x2) internal pure returns (uint256) {
		require(x2 >= x1);
		return _sum(x2) - _sum(x1);
	}
}

File 6 of 8: Treasury.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

import "./ERC20.sol";
import "./WTF.sol";
import "./StakingRewards.sol";


contract FeeManager {

	WTF private wtf;

	constructor() {
		wtf = WTF(msg.sender);
	}

	function disburse() external {
		wtf.claimRewards();
		uint256 _balance = wtf.balanceOf(address(this));
		if (_balance > 0) {
			uint256 _oneFifth = _balance / 5;
			Treasury(payable(wtf.treasuryAddress())).collect();
			wtf.transfer(wtf.treasuryAddress(), _oneFifth); // 20%
			StakingRewards(wtf.stakingRewardsAddress()).disburse(_oneFifth); // 20%
			StakingRewards(wtf.lpStakingRewardsAddress()).disburse(3 * _oneFifth); // 60%
		}
	}


	function wtfAddress() external view returns (address) {
		return address(wtf);
	}
}


contract TeamReferral {
	receive() external payable {}
	function release() external {
		address _this = address(this);
		require(_this.balance > 0);
		payable(0x6129E7bCb71C0d7D4580141C4E6a995f16293F42).transfer(_this.balance / 10); // 10%
		payable(0xc9AebdD8fD0d52c35A32fD9155467Cf28Ce474c3).transfer(_this.balance / 3); // 30%
		payable(0xdEE79eD62B42e30EA7EbB6f1b7A3f04143D18b7F).transfer(_this.balance / 2); // 30%
		payable(0x575446Aa9E9647C40edB7a467e45C5916add1538).transfer(_this.balance); // 30%
	}
}


contract Treasury {

	address public owner;
	uint256 public lockedUntil;
	WTF private wtf;

	modifier _onlyOwner() {
		require(msg.sender == owner);
		_;
	}

	constructor() {
		owner = 0x65dd4990719bE9B20322e4E8D3Bd77a4401a0357;
		lockedUntil = block.timestamp + 30 days;
		wtf = WTF(msg.sender);
	}

	receive() external payable {}

	function setOwner(address _owner) external _onlyOwner {
		owner = _owner;
	}

	function transferETH(address payable _destination, uint256 _amount) external _onlyOwner {
		require(isUnlocked());
		_destination.transfer(_amount);
	}

	function transferTokens(ERC20 _token, address _destination, uint256 _amount) external _onlyOwner {
		require(isUnlocked());
		_token.transfer(_destination, _amount);
	}

	function collect() external {
		wtf.claimRewards();
	}


	function isUnlocked() public view returns (bool) {
		return block.timestamp > lockedUntil;
	}

	function wtfAddress() external view returns (address) {
		return address(wtf);
	}
}

File 8 of 8: WTFNFT.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.11;

import "./Metadata.sol";

interface Receiver {
	function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes calldata _data) external returns (bytes4);
}


contract WTFNFT {

	struct User {
		uint256 balance;
		mapping(uint256 => uint256) list;
		mapping(address => bool) approved;
		mapping(uint256 => uint256) indexOf;
		uint256 tokenIndex;
	}

	struct Token {
		address user;
		address owner;
		address approved;
		uint128 totalFees;
		uint128 failFees;
		uint128 totalGas;
		uint128 avgGwei;
		uint128 totalDonated;
		uint64 totalTxs;
		uint64 failTxs;
	}

	struct Info {
		uint256 totalSupply;
		mapping(uint256 => Token) list;
		mapping(address => User) users;
		Metadata metadata;
		address wtf;
		address owner;
	}
	Info private info;

	mapping(bytes4 => bool) public supportsInterface;

	event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
	event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
	event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
	event Mint(address indexed owner, uint256 indexed tokenId, uint256 totalFees, uint256 failFees, uint256 totalGas, uint256 avgGwei, uint256 totalDonated, uint256 totalTxs, uint256 failTxs);


	modifier _onlyOwner() {
		require(msg.sender == owner());
		_;
	}


	constructor() {
		info.metadata = new Metadata(this);
		info.wtf = msg.sender;
		info.owner = 0xdEE79eD62B42e30EA7EbB6f1b7A3f04143D18b7F;
		supportsInterface[0x01ffc9a7] = true; // ERC-165
		supportsInterface[0x80ac58cd] = true; // ERC-721
		supportsInterface[0x5b5e139f] = true; // Metadata
		supportsInterface[0x780e9d63] = true; // Enumerable
	}

	function setOwner(address _owner) external _onlyOwner {
		info.owner = _owner;
	}

	function setMetadata(Metadata _metadata) external _onlyOwner {
		info.metadata = _metadata;
	}

	
	function mint(address _receiver, uint256 _totalFees, uint256 _failFees, uint256 _totalGas, uint256 _avgGwei, uint256 _totalDonated, uint256 _totalTxs, uint256 _failTxs) public {
		require(msg.sender == wtfAddress());
		uint256 _tokenId = info.totalSupply++;
		info.users[_receiver].tokenIndex = totalSupply();
		Token storage _newToken = info.list[_tokenId];
		_newToken.user = _receiver;
		_newToken.owner = _receiver;
		_newToken.totalFees = uint128(_totalFees);
		_newToken.failFees = uint128(_failFees);
		_newToken.totalGas = uint128(_totalGas);
		_newToken.avgGwei = uint128(_avgGwei);
		_newToken.totalDonated = uint128(_totalDonated);
		_newToken.totalTxs = uint64(_totalTxs);
		_newToken.failTxs = uint64(_failTxs);
		uint256 _index = info.users[_receiver].balance++;
		info.users[_receiver].indexOf[_tokenId] = _index + 1;
		info.users[_receiver].list[_index] = _tokenId;
		emit Transfer(address(0x0), _receiver, _tokenId);
		emit Mint(_receiver, _tokenId, _totalFees, _failFees, _totalGas, _avgGwei, _totalDonated, _totalTxs, _failTxs);
	}
	
	function approve(address _approved, uint256 _tokenId) external {
		require(msg.sender == ownerOf(_tokenId));
		info.list[_tokenId].approved = _approved;
		emit Approval(msg.sender, _approved, _tokenId);
	}

	function setApprovalForAll(address _operator, bool _approved) external {
		info.users[msg.sender].approved[_operator] = _approved;
		emit ApprovalForAll(msg.sender, _operator, _approved);
	}

	function transferFrom(address _from, address _to, uint256 _tokenId) external {
		_transfer(_from, _to, _tokenId);
	}

	function safeTransferFrom(address _from, address _to, uint256 _tokenId) external {
		safeTransferFrom(_from, _to, _tokenId, "");
	}

	function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes memory _data) public {
		_transfer(_from, _to, _tokenId);
		uint32 _size;
		assembly {
			_size := extcodesize(_to)
		}
		if (_size > 0) {
			require(Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) == 0x150b7a02);
		}
	}


	function name() external view returns (string memory) {
		return info.metadata.name();
	}

	function symbol() external view returns (string memory) {
		return info.metadata.symbol();
	}

	function tokenURI(uint256 _tokenId) external view returns (string memory) {
		return info.metadata.tokenURI(_tokenId);
	}

	function metadataAddress() public view returns (address) {
		return address(info.metadata);
	}

	function wtfAddress() public view returns (address) {
		return info.wtf;
	}

	function owner() public view returns (address) {
		return info.owner;
	}

	function totalSupply() public view returns (uint256) {
		return info.totalSupply;
	}

	function balanceOf(address _owner) public view returns (uint256) {
		return info.users[_owner].balance;
	}

	function ownerOf(uint256 _tokenId) public view returns (address) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].owner;
	}

	function getUser(uint256 _tokenId) public view returns (address) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].user;
	}

	function getApproved(uint256 _tokenId) public view returns (address) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].approved;
	}

	function getTotalFees(uint256 _tokenId) public view returns (uint256) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].totalFees;
	}

	function getFailFees(uint256 _tokenId) public view returns (uint256) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].failFees;
	}

	function getTotalGas(uint256 _tokenId) public view returns (uint256) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].totalGas;
	}

	function getAvgGwei(uint256 _tokenId) public view returns (uint256) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].avgGwei;
	}

	function getTotalDonated(uint256 _tokenId) public view returns (uint256) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].totalDonated;
	}

	function getTotalTxs(uint256 _tokenId) public view returns (uint256) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].totalTxs;
	}

	function getFailTxs(uint256 _tokenId) public view returns (uint256) {
		require(_tokenId < totalSupply());
		return info.list[_tokenId].failTxs;
	}

	function isApprovedForAll(address _owner, address _operator) public view returns (bool) {
		return info.users[_owner].approved[_operator];
	}

	function tokenIdOf(address _user) public view returns (uint256) {
		uint256 _index = info.users[_user].tokenIndex;
		require(_index > 0);
		return _index - 1;
	}

	function tokenByIndex(uint256 _index) public view returns (uint256) {
		require(_index < totalSupply());
		return _index;
	}

	function tokenOfOwnerByIndex(address _owner, uint256 _index) public view returns (uint256) {
		require(_index < balanceOf(_owner));
		return info.users[_owner].list[_index];
	}

	function getTokenCompressedInfo(uint256 _tokenId) public view returns (uint256[7] memory compressedInfo) {
		compressedInfo[0] = getTotalFees(_tokenId);
		compressedInfo[1] = getFailFees(_tokenId);
		compressedInfo[2] = getTotalGas(_tokenId);
		compressedInfo[3] = getAvgGwei(_tokenId);
		compressedInfo[4] = getTotalDonated(_tokenId);
		compressedInfo[5] = getTotalTxs(_tokenId);
		compressedInfo[6] = getFailTxs(_tokenId);
	}

	function getToken(uint256 _tokenId) public view returns (address tokenOwner, address approved, address user, uint256[7] memory compressedInfo) {
		return (ownerOf(_tokenId), getApproved(_tokenId), getUser(_tokenId), getTokenCompressedInfo(_tokenId));
	}

	function getTokens(uint256[] memory _tokenIds) public view returns (address[] memory owners, address[] memory approveds, address[] memory users, uint256[7][] memory compressedInfos) {
		uint256 _length = _tokenIds.length;
		owners = new address[](_length);
		approveds = new address[](_length);
		users = new address[](_length);
		compressedInfos = new uint256[7][](_length);
		for (uint256 i = 0; i < _length; i++) {
			(owners[i], approveds[i], users[i], compressedInfos[i]) = getToken(_tokenIds[i]);
		}
	}

	function getTokensTable(uint256 _limit, uint256 _page, bool _isAsc) public view returns (uint256[] memory tokenIds, address[] memory owners, address[] memory approveds, address[] memory users, uint256[7][] memory compressedInfos, uint256 totalTokens, uint256 totalPages) {
		require(_limit > 0);
		totalTokens = totalSupply();

		if (totalTokens > 0) {
			totalPages = (totalTokens / _limit) + (totalTokens % _limit == 0 ? 0 : 1);
			require(_page < totalPages);

			uint256 _offset = _limit * _page;
			if (_page == totalPages - 1 && totalTokens % _limit != 0) {
				_limit = totalTokens % _limit;
			}

			tokenIds = new uint256[](_limit);
			for (uint256 i = 0; i < _limit; i++) {
				tokenIds[i] = tokenByIndex(_isAsc ? _offset + i : totalTokens - _offset - i - 1);
			}
		} else {
			totalPages = 0;
			tokenIds = new uint256[](0);
		}
		(owners, approveds, users, compressedInfos) = getTokens(tokenIds);
	}

	function getOwnerTokensTable(address _owner, uint256 _limit, uint256 _page, bool _isAsc) public view returns (uint256[] memory tokenIds, address[] memory approveds, address[] memory users, uint256[7][] memory compressedInfos, uint256 totalTokens, uint256 totalPages) {
		require(_limit > 0);
		totalTokens = balanceOf(_owner);

		if (totalTokens > 0) {
			totalPages = (totalTokens / _limit) + (totalTokens % _limit == 0 ? 0 : 1);
			require(_page < totalPages);

			uint256 _offset = _limit * _page;
			if (_page == totalPages - 1 && totalTokens % _limit != 0) {
				_limit = totalTokens % _limit;
			}

			tokenIds = new uint256[](_limit);
			for (uint256 i = 0; i < _limit; i++) {
				tokenIds[i] = tokenOfOwnerByIndex(_owner, _isAsc ? _offset + i : totalTokens - _offset - i - 1);
			}
		} else {
			totalPages = 0;
			tokenIds = new uint256[](0);
		}
		( , approveds, users, compressedInfos) = getTokens(tokenIds);
	}

	function allInfoFor(address _owner) external view returns (uint256 supply, uint256 ownerBalance) {
		return (totalSupply(), balanceOf(_owner));
	}

	
	function _transfer(address _from, address _to, uint256 _tokenId) internal {
		address _owner = ownerOf(_tokenId);
		address _approved = getApproved(_tokenId);
		require(_from == _owner);
		require(msg.sender == _owner || msg.sender == _approved || isApprovedForAll(_owner, msg.sender));

		info.list[_tokenId].owner = _to;
		if (_approved != address(0x0)) {
			info.list[_tokenId].approved = address(0x0);
			emit Approval(address(0x0), address(0x0), _tokenId);
		}

		uint256 _index = info.users[_from].indexOf[_tokenId] - 1;
		uint256 _moved = info.users[_from].list[info.users[_from].balance - 1];
		info.users[_from].list[_index] = _moved;
		info.users[_from].indexOf[_moved] = _index + 1;
		info.users[_from].balance--;
		delete info.users[_from].indexOf[_tokenId];
		uint256 _newIndex = info.users[_to].balance++;
		info.users[_to].indexOf[_tokenId] = _newIndex + 1;
		info.users[_to].list[_newIndex] = _tokenId;
		emit Transfer(_from, _to, _tokenId);
	}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"_openingTime","type":"uint256"},{"internalType":"uint256","name":"_stakingRewardsStart","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ReflinkRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Reward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bool","name":"fromWhitelisted","type":"bool"},{"indexed":false,"internalType":"bool","name":"toWhitelisted","type":"bool"}],"name":"WhitelistUpdated","type":"event"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"allInfoFor","outputs":[{"internalType":"uint256","name":"totalTokens","type":"uint256"},{"internalType":"uint256","name":"totalLPTokens","type":"uint256"},{"internalType":"uint256","name":"wethReserve","type":"uint256"},{"internalType":"uint256","name":"wtfReserve","type":"uint256"},{"internalType":"uint256","name":"userBalance","type":"uint256"},{"internalType":"uint256","name":"userRewards","type":"uint256"},{"internalType":"uint256","name":"userLPBalance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"boostRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256[9]","name":"_data","type":"uint256[9]"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"claimInfoFor","outputs":[{"internalType":"uint256","name":"openTime","type":"uint256"},{"internalType":"uint256","name":"closeTime","type":"uint256"},{"internalType":"bool","name":"unlocked","type":"bool"},{"internalType":"bool","name":"claimedWTF","type":"bool"},{"internalType":"bool","name":"claimedNFT","type":"bool"},{"internalType":"uint256","name":"wethReserve","type":"uint256"},{"internalType":"uint256","name":"wtfReserve","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256[9]","name":"_data","type":"uint256[9]"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"claimNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256[9]","name":"_data","type":"uint256[9]"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"claimWTF","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"closingTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"disburse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeManagerPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"isClaimedNFT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"isClaimedWTF","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isFromWhitelisted","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":"_address","type":"address"}],"name":"isToWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"isUnlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpStakingRewardsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nftAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openingTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pairAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"reflinkInfoFor","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"level","type":"uint256"},{"internalType":"uint256","name":"percent","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"reflinkLevel","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"reflinkPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"rewardsOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_closingTime","type":"uint256"}],"name":"setClosingTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeManager","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_feeManagerPercent","type":"uint256"}],"name":"setFeeManagerPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_transferFee","type":"uint256"}],"name":"setTransferFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bool","name":"_fromWhitelisted","type":"bool"},{"internalType":"bool","name":"_toWhitelisted","type":"bool"}],"name":"setWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingRewardsAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"teamAddress","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"transferAndCall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"address payable","name":"_referrer","type":"address"}],"name":"unlock","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reflinkLevel","type":"uint256"}],"name":"upgradeCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"_toLevel","type":"uint256"}],"name":"upgradeReflink","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b506040516200a7053803806200a70583398101604081905262000034916200076e565b60008390554282116200004857426200004a565b815b60018190556200005e9062278d00620007b3565b600255600b80546001600160a01b031916737a250d5630b4cf539739df2c5dacb4c659f2488d9081179091556040805163c45a015560e01b8152905163c45a0155916004808201926020929091908290030181865afa158015620000c6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000ec9190620007ce565b600b54604080516315ab88c960e31b815290516001600160a01b039384169363c9c6539693169163ad5c46489160048083019260209291908290030181865afa1580156200013e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001649190620007ce565b6040516001600160e01b031960e084901b1681526001600160a01b0390911660048201523060248201526044016020604051808303816000875af1158015620001b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001d79190620007ce565b600c80546001600160a01b0319166001600160a01b03928316179055600b54604080516315ab88c960e31b81529051919092169163ad5c46489160048083019260209291908290030181865afa15801562000236573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200025c9190620007ce565b6001600160a01b03166000600c0160009054906101000a90046001600160a01b03166001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002bc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002e29190620007ce565b600c805460ff60a01b19166001600160a01b039290921692909214600160a01b0217905560286013556019601455600a80547365dd4990719be9b20322e4e8d3bd77a4401a03576001600160a01b0319909116179055604051620003469062000728565b604051809103906000f08015801562000363573d6000803e3d6000fd5b50600d80546001600160a01b0319166001600160a01b0392909216919091179055604051620003929062000736565b604051809103906000f080158015620003af573d6000803e3d6000fd5b50600e80546001600160a01b0319166001600160a01b0392909216919091179055604051620003de9062000744565b604051809103906000f080158015620003fb573d6000803e3d6000fd5b50600f80546001600160a01b0319166001600160a01b0392909216918217905562000433905b6a2116545850052128000000620005eb565b6a108b2a2c2802909400000081306040516200044f9062000752565b92835260208301919091526001600160a01b03166040820152606001604051809103906000f08015801562000488573d6000803e3d6000fd5b50601080546001600160a01b0319166001600160a01b03929092169182179055620004bf906a108b2a2c28029094000000620005eb565b6a211654585005212800000081620004df600c546001600160a01b031690565b604051620004ed9062000752565b92835260208301919091526001600160a01b03166040820152606001604051809103906000f08015801562000526573d6000803e3d6000fd5b50601180546001600160a01b0319166001600160a01b03929092169182179055620005519062000421565b6040516200055f9062000760565b604051809103906000f0801580156200057c573d6000803e3d6000fd5b50601280546001600160a01b0319166001600160a01b03929092169182179055620005b7906010546001600160a01b03165b600019620006bc565b50620005e1620005cf6012546001600160a01b031690565b6011546001600160a01b0316620005ae565b5050505062000869565b8060006003016000828254620006029190620007b3565b90915550506001600160a01b0382166000908152600760205260408120805483929062000631908490620007b3565b909155505060045462000645908262000800565b6001600160a01b038316600090815260076020526040812060020180549091906200067290849062000822565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b6001600160a01b0383811660008181526007602090815260408083209487168084526001909501825280832086905551858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060019392505050565b614f718062002d9683390190565b6102198062007d0783390190565b6104ce8062007f2083390190565b611d4e80620083ee83390190565b6105c9806200a13c83390190565b6000806000606084860312156200078457600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052601160045260246000fd5b60008219821115620007c957620007c96200079d565b500190565b600060208284031215620007e157600080fd5b81516001600160a01b0381168114620007f957600080fd5b9392505050565b60008160001904831182151516156200081d576200081d6200079d565b500290565b600080821280156001600160ff1b03849003851316156200084757620008476200079d565b600160ff1b83900384128116156200086357620008636200079d565b50500190565b61251d80620008796000396000f3fe6080604052600436106102ff5760003560e01c806353aeea1e11610190578063acb2ad6f116100dc578063d240663c11610095578063e6a6dcce1161006f578063e6a6dcce146109d2578063e8d2c8c1146109f2578063f3e4df0614610a12578063fa82e8c514610a3257600080fd5b8063d240663c14610955578063dd62ed3e14610975578063e674a0bd146109bf57600080fd5b8063acb2ad6f146108ad578063ad046ddf146108c2578063b7a8807c146108e2578063bd77ac2c146108f7578063be459f6214610917578063c5f956af1461093757600080fd5b8063788bff68116101495780638f02bb5b116101235780638f02bb5b1461082057806395d89b4114610840578063a8b089821461086f578063a9059cbb1461088d57600080fd5b8063788bff68146107c65780638d8474c8146107e45780638da5cb5b1461080257600080fd5b806353aeea1e146106d557806357f6b812146106f55780635bf8633a1461074a578063699ea5831461076857806370a082311461078657806372ded8f3146107a657600080fd5b8063313ce5671161024f578063472d35b9116102085780634b6753bc116101e25780634b6753bc1461066b5780634b89c41d14610680578063531bc097146106a0578063532b1ba8146106b557600080fd5b8063472d35b91461061657806347535d7b14610636578063479ba7ae1461064b57600080fd5b8063313ce5671461056557806332a7eb961461058c57806335faa416146105ac578063372500ab146105c15780634000aea0146105d657806342966c68146105f657600080fd5b80631c75f085116102bc57806328687cc71161029657806328687cc7146104e25780632bbf532a1461051b5780632eb4a7ab1461053b5780632f1c030d1461055057600080fd5b80631c75f085146104575780631e3c187f1461048957806323b872dd146104c257600080fd5b806306fdde0314610304578063095ea7b31461034e5780630a53669f1461037e57806312408c8e146103b957806313af40351461041657806318160ddd14610438575b600080fd5b34801561031057600080fd5b50610338604051806040016040528060088152602001673332b2b9973bba3360c11b81525081565b6040516103459190611e96565b60405180910390f35b34801561035a57600080fd5b5061036e610369366004611f00565b610a6b565b6040519015158152602001610345565b34801561038a57600080fd5b5061039e610399366004611f2c565b610a81565b60408051938452602084019290925290820152606001610345565b3480156103c557600080fd5b506103d96103d4366004611f50565b610ac1565b6040805197885260208801969096529315159486019490945290151560608501521515608084015260a083019190915260c082015260e001610345565b34801561042257600080fd5b50610436610431366004611f2c565b610b24565b005b34801561044457600080fd5b506003545b604051908152602001610345565b34801561046357600080fd5b50600e546001600160a01b03165b6040516001600160a01b039091168152602001610345565b34801561049557600080fd5b5061036e6104a4366004611f2c565b6001600160a01b031660009081526008602052604090205460ff1690565b3480156104ce57600080fd5b5061036e6104dd366004611f80565b610b5d565b3480156104ee57600080fd5b5061036e6104fd366004611f2c565b6001600160a01b031660009081526009602052604090205460ff1690565b34801561052757600080fd5b5061036e610536366004611f2c565b610bea565b34801561054757600080fd5b50600054610449565b34801561055c57600080fd5b50610436610c0b565b34801561057157600080fd5b5061057a601281565b60405160ff9091168152602001610345565b34801561059857600080fd5b5061036e6105a7366004611fc1565b610caf565b3480156105b857600080fd5b50610436610cf0565b3480156105cd57600080fd5b50610436610d33565b3480156105e257600080fd5b5061036e6105f1366004611fda565b610dc8565b34801561060257600080fd5b50610436610611366004611fc1565b610e94565b34801561062257600080fd5b50610436610631366004611f2c565b610f44565b34801561064257600080fd5b5061036e610f7d565b34801561065757600080fd5b50610449610666366004611f2c565b610f9c565b34801561067757600080fd5b50600254610449565b34801561068c57600080fd5b5061043661069b366004611fc1565b610fe8565b3480156106ac57600080fd5b50601454610449565b3480156106c157600080fd5b506104366106d0366004612063565b611004565b3480156106e157600080fd5b506104366106f0366004611fc1565b61118f565b34801561070157600080fd5b50610715610710366004611f2c565b611202565b604080519788526020880196909652948601939093526060850191909152608084015260a083015260c082015260e001610345565b34801561075657600080fd5b50600d546001600160a01b0316610471565b34801561077457600080fd5b506011546001600160a01b0316610471565b34801561079257600080fd5b506104496107a1366004611f2c565b6113d6565b3480156107b257600080fd5b506104366107c1366004612063565b6113f1565b3480156107d257600080fd5b506010546001600160a01b0316610471565b3480156107f057600080fd5b506012546001600160a01b0316610471565b34801561080e57600080fd5b50600a546001600160a01b0316610471565b34801561082c57600080fd5b5061043661083b366004611fc1565b6114cb565b34801561084c57600080fd5b50610338604051806040016040528060038152602001622baa2360e91b81525081565b34801561087b57600080fd5b50600c546001600160a01b0316610471565b34801561089957600080fd5b5061036e6108a8366004611f00565b6114f5565b3480156108b957600080fd5b50601354610449565b3480156108ce57600080fd5b506104496108dd366004611f2c565b611502565b3480156108ee57600080fd5b50600154610449565b34801561090357600080fd5b50610436610912366004611fc1565b611534565b34801561092357600080fd5b5061036e610932366004611fc1565b611580565b34801561094357600080fd5b50600f546001600160a01b0316610471565b34801561096157600080fd5b50610436610970366004612063565b6115c1565b34801561098157600080fd5b506104496109903660046120ee565b6001600160a01b0391821660009081526007602090815260408083209390941682526001909201909152205490565b6104366109cd3660046120ee565b6115df565b3480156109de57600080fd5b506104366109ed36600461212a565b61178f565b3480156109fe57600080fd5b50610436610a0d366004611fc1565b611820565b348015610a1e57600080fd5b50610449610a2d366004611fc1565b61184a565b348015610a3e57600080fd5b50610449610a4d366004611f2c565b6001600160a01b031660009081526007602052604090206003015490565b6000610a78338484611876565b90505b92915050565b6000806000610a8f846113d6565b6001600160a01b038516600090815260076020526040902060030154610ab486611502565b9250925092509193909250565b6000806000806000806000610ad560015490565b9650610ae060025490565b9550610aeb88610bea565b9450610af689610caf565b9350610b0189611580565b9250610b0d6000611202565b509b9e9a9d50989b50969950949794965050505050565b600a546001600160a01b03163314610b3b57600080fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038316600090815260076020908152604080832033845260010190915281205482811015610b9157600080fd5b6000198114610bd6576001600160a01b038516600090815260076020908152604080832033845260010190915281208054859290610bd090849061218b565b90915550505b610be18585856118e2565b95945050505050565b6001600160a01b031660009081526007602052604090206004015460ff1690565b306000610c1782610f9c565b90508015610cab57610c2d600160401b826121a2565b6001600160a01b03831660009081526007602052604081206002018054909190610c589084906121c1565b90915550610c67905081611b97565b816001600160a01b03167f1f89f96333d3133000ee447473151fa9606543368f02271c9d95ae14f13bcc6782604051610ca291815260200190565b60405180910390a25b5050565b600080610cbe61010084612218565b90506000610cce6101008561222c565b60009283526005602052604090922054600190921b9182169091149392505050565b4715610d3157600e546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610d2f573d6000803e3d6000fd5b505b565b610d3b610c0b565b6000610d4633610f9c565b90508015610d2f57610d5c600160401b826121a2565b3360009081526007602052604081206002018054909190610d7e9084906121c1565b90915550610d8f90503033836118e2565b5060405181815233907f1f89f96333d3133000ee447473151fa9606543368f02271c9d95ae14f13bcc679060200160405180910390a250565b600080610dd4866113d6565b9050610de13387876118e2565b50600081610dee886113d6565b610df8919061218b565b9050863b63ffffffff811615610e8657604051636be32e7360e01b81526001600160a01b03891690636be32e7390610e3a90339086908b908b90600401612240565b6020604051808303816000875af1158015610e59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7d9190612288565b610e8657600080fd5b506001979650505050505050565b80610e9e336113d6565b1015610ea957600080fd5b8060006003016000828254610ebe919061218b565b90915550503360009081526007602052604081208054839290610ee290849061218b565b9091555050600454610ef490826121a2565b3360009081526007602052604081206002018054909190610f169084906122a5565b909155505060405181815260009033906000805160206124c88339815191529060200160405180910390a350565b600a546001600160a01b03163314610f5b57600080fd5b601280546001600160a01b0319166001600160a01b0392909216919091179055565b6000610f8860015490565b42118015610f97575060025442105b905090565b6001600160a01b038116600090815260076020526040812060020154600160401b90610fc7846113d6565b600454610fd491906121a2565b610fde91906122a5565b610a7b9190612218565b600a546001600160a01b03163314610fff57600080fd5b600255565b61100c610f7d565b61101557600080fd5b61101e84610bea565b61102757600080fd5b823561103281611580565b1561103c57600080fd5b6110a083838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604051611085925089915088906020016122fa565b60405160208183030381529060405280519060200120611c05565b6110a957600080fd5b60006110b761010083612218565b905060006110c76101008461222c565b6000838152600660205260409081902080546001841b179055600d54815163a46a932f60e01b81526001600160a01b038b81166004830152928a0135602482015260608a0135604482015260808a0135606482015260a08a0135608482015260c08a013560a482015260e08a013560c48201526101008a013560e4820152929350169063a46a932f9061010401600060405180830381600087803b15801561116e57600080fd5b505af1158015611182573d6000803e3d6000fd5b5050505050505050505050565b336000908152600760205260409020600301548181106111ae57600080fd5b6000815b838110156111e1576111c38161184a565b6111cd908361232a565b9150806111d981612342565b9150506111b2565b506111eb81610e94565b505033600090815260076020526040902060030155565b600080600080600080600061121660035490565b600c54604080516318160ddd60e01b815290519299506001600160a01b03909116916318160ddd916004808201926020929091908290030181865afa158015611263573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611287919061235d565b600c5460408051630240bc6b60e21b8152905192985060009283926001600160a01b031691630902f1ac9160048083019260609291908290030181865afa1580156112d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fa9190612392565b50600c546001600160701b03928316945091169150600160a01b900460ff166113235780611325565b815b600c54909750600160a01b900460ff1661133f5781611341565b805b955061134c8a6113d6565b94506113578a610f9c565b600c546040516370a0823160e01b81526001600160a01b038d811660048301529296509116906370a0823190602401602060405180830381865afa1580156113a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c7919061235d565b92505050919395979092949650565b6001600160a01b031660009081526007602052604090205490565b6113f9610f7d565b61140257600080fd5b61140b84610bea565b61141457600080fd5b8235602084013561142482610caf565b1561142e57600080fd5b6114778484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060405161108592508a915089906020016122fa565b61148057600080fd5b600061148e61010084612218565b9050600061149e6101008561222c565b600083815260056020526040902080546001831b17905590506114c18884611cb5565b5050505050505050565b600a546001600160a01b031633146114e257600080fd5b60648111156114f057600080fd5b601355565b6000610a783384846118e2565b6001600160a01b03811660009081526007602052604081206003015461152990600161232a565b610a7b90600a6121a2565b6000811161154157600080fd5b600061154c306113d6565b90506115593330846118e2565b50600081611566306113d6565b611570919061218b565b905061157b81611b97565b505050565b60008061158f61010084612218565b9050600061159f6101008561222c565b60009283526006602052604090922054600190921b9182169091149392505050565b6115cd848484846113f1565b6115d984848484611004565b50505050565b60025442106115ed57600080fd5b6115f682610bea565b1561160057600080fd5b662386f26fc10000341461161357600080fd5b60006001600160a01b038216156116b757606461162f83611502565b61164090662386f26fc100006121a2565b61164a9190612218565b6040519091506001600160a01b0383169082156108fc029083906000818181858888f1935050505050816001600160a01b03167f4b8126d2c8cfe6526bd9f134921855f9c6076a52dd74535c1bf55d59a778edc8826040516116ae91815260200190565b60405180910390a25b60006116ca82662386f26fc1000061218b565b90506116de600e546001600160a01b031690565b6001600160a01b03166108fc829081150290604051600060405180830381858888f19350505050158015611716573d6000803e3d6000fd5b50600e546001600160a01b03166001600160a01b03167f4b8126d2c8cfe6526bd9f134921855f9c6076a52dd74535c1bf55d59a778edc88260405161175d91815260200190565b60405180910390a25050506001600160a01b03166000908152600760205260409020600401805460ff19166001179055565b600a546001600160a01b031633146117a657600080fd5b6001600160a01b0383166000818152600960209081526040808320805487151560ff199182168117909255600884529382902080548715159516851790558151908152918201929092527f855852ede06df792cbe12bbb8b292fd0d251a1dcfea1f072d5793f1930568ebf910160405180910390a2505050565b600a546001600160a01b0316331461183757600080fd5b606481111561184557600080fd5b601455565b60006004821061185957600080fd5b61186482600a6124bb565b610a7b90678ac7230489e800006121a2565b6001600160a01b0383811660008181526007602090815260408083209487168084526001909501825280832086905551858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060019392505050565b6000816118ee856113d6565b10156118f957600080fd5b6001600160a01b0384166000908152600760205260408120805484929061192190849061218b565b909155505060045461193390836121a2565b6001600160a01b0385166000908152600760205260408120600201805490919061195e9084906122a5565b90915550600090506119708585611d6c565b611a3a576103e861198060135490565b61198a90856121a2565b6119949190612218565b30600081815260076020526040812080549394509192849291906119b990849061232a565b90915550506004546119cb90836121a2565b6001600160a01b038216600090815260076020526040812060020180549091906119f69084906121c1565b92505081905550806001600160a01b0316866001600160a01b03166000805160206124c883398151915284604051611a3091815260200190565b60405180910390a3505b6000611a46828561218b565b6001600160a01b038616600090815260076020526040812080549293508392909190611a7390849061232a565b9091555050600454611a8590826121a2565b6001600160a01b03861660009081526007602052604081206002018054909190611ab09084906121c1565b92505081905550846001600160a01b0316866001600160a01b03166000805160206124c883398151915283604051611aea91815260200190565b60405180910390a38115611b8b5760006064611b0560145490565b611b0f90856121a2565b611b199190612218565b9050611b29600160401b826121a2565b60076000611b3f6012546001600160a01b031690565b6001600160a01b03166001600160a01b031681526020019081526020016000206002016000828254611b7191906122a5565b90915550611b899050611b84828561218b565b611b97565b505b50600195945050505050565b8015610d2f57600354611bae600160401b836121a2565b611bb89190612218565b60048054600090611bca90849061232a565b90915550506040518181527f3ac0594a85a20354f9dc74f33728416d19ce00d04a406c108cc2dcf2cecea1349060200160405180910390a150565b600081815b8451811015611ca9576000858281518110611c2757611c276122e4565b60200260200101519050808311611c69576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250611c96565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080611ca181612342565b915050611c0a565b50600054149392505050565b8060006003016000828254611cca919061232a565b90915550506001600160a01b03821660009081526007602052604081208054839290611cf790849061232a565b9091555050600454611d0990826121a2565b6001600160a01b03831660009081526007602052604081206002018054909190611d349084906121c1565b90915550506040518181526001600160a01b038316906000906000805160206124c88339815191529060200160405180910390a35050565b6001600160a01b03821660009081526009602052604081205460ff1680611dab57506001600160a01b03821660009081526008602052604090205460ff165b80611dbe57506001600160a01b03831630145b80611dd157506001600160a01b03821630145b80611de957506012546001600160a01b038481169116145b80611e0157506012546001600160a01b038381169116145b80611e195750600f546001600160a01b038481169116145b80611e315750600f546001600160a01b038381169116145b80611e4957506010546001600160a01b038481169116145b80611e6157506010546001600160a01b038381169116145b80611e7957506011546001600160a01b038481169116145b80610a785750506011546001600160a01b03918216911614919050565b600060208083528351808285015260005b81811015611ec357858101830151858201604001528201611ea7565b81811115611ed5576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b0381168114610d2f57600080fd5b60008060408385031215611f1357600080fd5b8235611f1e81611eeb565b946020939093013593505050565b600060208284031215611f3e57600080fd5b8135611f4981611eeb565b9392505050565b60008060408385031215611f6357600080fd5b823591506020830135611f7581611eeb565b809150509250929050565b600080600060608486031215611f9557600080fd5b8335611fa081611eeb565b92506020840135611fb081611eeb565b929592945050506040919091013590565b600060208284031215611fd357600080fd5b5035919050565b60008060008060608587031215611ff057600080fd5b8435611ffb81611eeb565b935060208501359250604085013567ffffffffffffffff8082111561201f57600080fd5b818701915087601f83011261203357600080fd5b81358181111561204257600080fd5b88602082850101111561205457600080fd5b95989497505060200194505050565b600080600080610160858703121561207a57600080fd5b843561208581611eeb565b935061014085018681111561209957600080fd5b6020860193503567ffffffffffffffff808211156120b657600080fd5b818701915087601f8301126120ca57600080fd5b8135818111156120d957600080fd5b8860208260051b850101111561205457600080fd5b6000806040838503121561210157600080fd5b823561210c81611eeb565b91506020830135611f7581611eeb565b8015158114610d2f57600080fd5b60008060006060848603121561213f57600080fd5b833561214a81611eeb565b9250602084013561215a8161211c565b9150604084013561216a8161211c565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b60008282101561219d5761219d612175565b500390565b60008160001904831182151516156121bc576121bc612175565b500290565b600080821280156001600160ff1b03849003851316156121e3576121e3612175565b600160ff1b83900384128116156121fc576121fc612175565b50500190565b634e487b7160e01b600052601260045260246000fd5b60008261222757612227612202565b500490565b60008261223b5761223b612202565b500690565b6001600160a01b0385168152602081018490526060604082018190528101829052818360808301376000818301608090810191909152601f909201601f191601019392505050565b60006020828403121561229a57600080fd5b8151611f498161211c565b60008083128015600160ff1b8501841216156122c3576122c3612175565b6001600160ff1b03840183138116156122de576122de612175565b50500390565b634e487b7160e01b600052603260045260246000fd5b6bffffffffffffffffffffffff198360601b16815261012082601483013760006101349190910190815292915050565b6000821982111561233d5761233d612175565b500190565b600060001982141561235657612356612175565b5060010190565b60006020828403121561236f57600080fd5b5051919050565b80516001600160701b038116811461238d57600080fd5b919050565b6000806000606084860312156123a757600080fd5b6123b084612376565b92506123be60208501612376565b9150604084015163ffffffff8116811461216a57600080fd5b600181815b808511156124125781600019048211156123f8576123f8612175565b8085161561240557918102915b93841c93908002906123dc565b509250929050565b60008261242957506001610a7b565b8161243657506000610a7b565b816001811461244c576002811461245657612472565b6001915050610a7b565b60ff84111561246757612467612175565b50506001821b610a7b565b5060208310610133831016604e8410600b8410161715612495575081810a610a7b565b61249f83836123d7565b80600019048211156124b3576124b3612175565b029392505050565b6000610a78838361241a56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220773c3bc5c1b52ba29c8531e661ad2f452c8d85e666bc98dcb001458ff10a7c9664736f6c634300080b0033608060405234801561001057600080fd5b503060405161001e90610156565b6001600160a01b039091168152602001604051809103906000f08015801561004a573d6000803e3d6000fd5b50600380546001600160a01b03929092166001600160a01b0319928316179055600480548216331790556005805490911673dee79ed62b42e30ea7ebb6f1b7a3f04143d18b7f17905560066020527f477a984de5936bcb02475f64e0ea676103106ac0785c67bf7e9e846450b51ef6805460ff1990811660019081179092557fd544553a2e70858ffdf1e1169f6f124859d29ddf2686bcabf4e6f71bc630442280548216831790557fcc41b8fe3dd37df8e4a56c49f4e83a8fb6899f1fe8f1ddc40678281e8ec62212805482168317905563780e9d6360e01b6000527fa99870648958e45dc5b37a02b811cf5f899ba384167c205b3dcb1f6df5e4737280549091169091179055610164565b612da180620021d083390190565b61205c80620001746000396000f3fe608060405234801561001057600080fd5b50600436106102275760003560e01c8063767bbd5b11610130578063b0467deb116100b8578063e4b50cb81161007c578063e4b50cb81461051a578063e985e9c51461053d578063f00637951461057a578063f3cb83851461059f578063f5fe58b8146105b257600080fd5b8063b0467deb146104bb578063b3a7eb59146104ce578063b88d4fde146104e1578063c87b56dd146104f4578063dfe6e5121461050757600080fd5b8063a22cb465116100ff578063a22cb4651461044f578063a3739f7114610462578063a46a932f14610475578063a9e566c014610488578063ab2a1941146104a857600080fd5b8063767bbd5b14610410578063773c02d4146104235780638da5cb5b1461043657806395d89b411461044757600080fd5b806332ba0a1e116101b35780636352211e116101825780636352211e1461038c5780636bd5ff2f1461039f5780636eb3500d146103c55780636ff92f50146103d657806370a08231146103e757600080fd5b806332ba0a1e1461031b57806342842e0e1461033e5780634f6ccce71461035157806357f6b8121461036457600080fd5b8063113f2d9e116101fa578063113f2d9e146102b957806313af4035146102da57806318160ddd146102ed57806323b872dd146102f55780632f745c591461030857600080fd5b806301ffc9a71461022c57806306fdde0314610264578063081812fc14610279578063095ea7b3146102a4575b600080fd5b61024f61023a3660046117ca565b60066020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61026c6105c5565b60405161025b9190611843565b61028c610287366004611856565b61063c565b6040516001600160a01b03909116815260200161025b565b6102b76102b2366004611884565b61066a565b005b6102cc6102c7366004611856565b6106ec565b60405190815260200161025b565b6102b76102e83660046118b0565b610721565b6000546102cc565b6102b76103033660046118cd565b61075a565b6102cc610316366004611884565b61076a565b61032e610329366004611954565b6107bd565b60405161025b9493929190611a9a565b6102b761034c3660046118cd565b6109b5565b6102cc61035f366004611856565b6109d0565b6103776103723660046118b0565b6109e3565b6040805192835260208301919091520161025b565b61028c61039a366004611856565b610a11565b6103b26103ad366004611b07565b610a40565b60405161025b9796959493929190611b6c565b6003546001600160a01b031661028c565b6004546001600160a01b031661028c565b6102cc6103f53660046118b0565b6001600160a01b031660009081526002602052604090205490565b6102cc61041e366004611856565b610bcb565b6102cc6104313660046118b0565b610c00565b6005546001600160a01b031661028c565b61026c610c38565b6102b761045d366004611be4565b610c82565b6102cc610470366004611856565b610cef565b6102b7610483366004611c19565b610d1d565b61049b610496366004611856565b611035565b60405161025b9190611c77565b6102cc6104b6366004611856565b6110a1565b61028c6104c9366004611856565b6110d6565b6102cc6104dc366004611856565b611101565b6102b76104ef366004611cac565b611136565b61026c610502366004611856565b6111e7565b6102cc610515366004611856565b611259565b61052d610528366004611856565b611287565b60405161025b9493929190611d5a565b61024f61054b366004611d91565b6001600160a01b0391821660009081526002602081815260408084209490951683529201909152205460ff1690565b61058d610588366004611dca565b6112c7565b60405161025b96959493929190611e12565b6102b76105ad3660046118b0565b611468565b6102cc6105c0366004611856565b6114a1565b600354604080516306fdde0360e01b815290516060926001600160a01b0316916306fdde039160048083019260009291908290030181865afa15801561060f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526106379190810190611e75565b905090565b60008054821061064b57600080fd5b506000908152600160205260409020600201546001600160a01b031690565b61067381610a11565b6001600160a01b0316336001600160a01b03161461069057600080fd5b60008181526001602052604080822060020180546001600160a01b0319166001600160a01b0386169081179091559051839233917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259190a45050565b6000805482106106fb57600080fd5b50600090815260016020526040902060050154600160c01b90046001600160401b031690565b6005546001600160a01b0316331461073857600080fd5b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6107658383836114cf565b505050565b6001600160a01b038216600090815260026020526040812054821061078e57600080fd5b506001600160a01b03821660009081526002602090815260408083208484526001019091529020545b92915050565b606080606080600085519050806001600160401b038111156107e1576107e161190e565b60405190808252806020026020018201604052801561080a578160200160208202803683370190505b509450806001600160401b038111156108255761082561190e565b60405190808252806020026020018201604052801561084e578160200160208202803683370190505b509350806001600160401b038111156108695761086961190e565b604051908082528060200260200182016040528015610892578160200160208202803683370190505b509250806001600160401b038111156108ad576108ad61190e565b6040519080825280602002602001820160405280156108e657816020015b6108d3611793565b8152602001906001900390816108cb5790505b50915060005b818110156109ac5761091687828151811061090957610909611ee2565b6020026020010151611287565b89858151811061092857610928611ee2565b6020026020010189868151811061094157610941611ee2565b6020026020010189878151811061095a5761095a611ee2565b6020026020010189888151811061097357610973611ee2565b60209081029190910101939093526001600160a01b039384169092529282169052919091169052806109a481611f0e565b9150506108ec565b50509193509193565b61076583838360405180602001604052806000815250611136565b6000805482106109df57600080fd5b5090565b6000806109ef60005490565b6001600160a01b03841660009081526002602052604090205491509150915091565b600080548210610a2057600080fd5b50600090815260016020819052604090912001546001600160a01b031690565b606080606080606060008060008a11610a5857600080fd5b60005491508115610b9a57610a6d8a83611f3f565b15610a79576001610a7c565b60005b60ff16610a898b84611f53565b610a939190611f67565b9050808910610aa157600080fd5b6000610aad8a8c611f7f565b9050610aba600183611f9e565b8a148015610ad05750610acd8b84611f3f565b15155b15610ae257610adf8b84611f3f565b9a505b8a6001600160401b03811115610afa57610afa61190e565b604051908082528060200260200182016040528015610b23578160200160208202803683370190505b50975060005b8b811015610b9357610b648a610b5a57600182610b468588611f9e565b610b509190611f9e565b61035f9190611f9e565b61035f8284611f67565b898281518110610b7657610b76611ee2565b602090810291909101015280610b8b81611f0e565b915050610b29565b5050610bae565b506040805160008082526020820190925296505b610bb7876107bd565b999d929c50909a5098509195509350915050565b600080548210610bda57600080fd5b50600090815260016020526040902060030154600160801b90046001600160801b031690565b6001600160a01b03811660009081526002602052604081206004015480610c2657600080fd5b610c31600182611f9e565b9392505050565b600354604080516395d89b4160e01b815290516060926001600160a01b0316916395d89b419160048083019260009291908290030181865afa15801561060f573d6000803e3d6000fd5b3360008181526002602081815260408084206001600160a01b0388168086529301825292839020805460ff191686151590811790915592519283529092917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b600080548210610cfe57600080fd5b506000908152600160205260409020600501546001600160801b031690565b6004546001600160a01b03163314610d3457600080fd5b600080548180610d4383611f0e565b919050559050610d5260005490565b600060020160008b6001600160a01b03166001600160a01b031681526020019081526020016000206004018190555060008060010160008381526020019081526020016000209050898160000160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550898160010160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550888160030160006101000a8154816001600160801b0302191690836001600160801b03160217905550878160030160106101000a8154816001600160801b0302191690836001600160801b03160217905550868160040160006101000a8154816001600160801b0302191690836001600160801b03160217905550858160040160106101000a8154816001600160801b0302191690836001600160801b03160217905550848160050160006101000a8154816001600160801b0302191690836001600160801b03160217905550838160050160106101000a8154816001600160401b0302191690836001600160401b03160217905550828160050160186101000a8154816001600160401b0302191690836001600160401b0316021790555060008060020160008c6001600160a01b03166001600160a01b031681526020019081526020016000206000016000815480929190610f4890611f0e565b909155509050610f59816001611f67565b6001600160a01b038c166000818152600260209081526040808320888452600381018352818420959095558583526001909401905282812086905591518592907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a4604080518b8152602081018b9052908101899052606081018890526080810187905260a0810186905260c0810185905283906001600160a01b038d16907f7cc62fff527c1d370281620d7f175585dac25557e85f8bedc8e74b984e3bf2e79060e00160405180910390a35050505050505050505050565b61103d611793565b611046826114a1565b815261105182610bcb565b602082015261105f82611259565b604082015261106d82611101565b606082015261107b82610cef565b6080820152611089826110a1565b60a0820152611097826106ec565b60c0820152919050565b6000805482106110b057600080fd5b50600090815260016020526040902060050154600160801b90046001600160401b031690565b6000805482106110e557600080fd5b506000908152600160205260409020546001600160a01b031690565b60008054821061111057600080fd5b50600090815260016020526040902060040154600160801b90046001600160801b031690565b6111418484846114cf565b823b63ffffffff8116156111e057604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611181903390899088908890600401611fb5565b6020604051808303816000875af11580156111a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111c49190611ff2565b6001600160e01b03191663150b7a0260e01b146111e057600080fd5b5050505050565b60035460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd90602401600060405180830381865afa158015611231573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107b79190810190611e75565b60008054821061126857600080fd5b506000908152600160205260409020600401546001600160801b031690565b6000806000611294611793565b61129d85610a11565b6112a68661063c565b6112af876110d6565b6112b888611035565b93509350935093509193509193565b606080606080600080600089116112dd57600080fd5b6001600160a01b038a1660009081526002602052604090205491508115611436576113088983611f3f565b15611314576001611317565b60005b60ff166113248a84611f53565b61132e9190611f67565b905080881061133c57600080fd5b6000611348898b611f7f565b9050611355600183611f9e565b8914801561136b57506113688a84611f3f565b15155b1561137d5761137a8a84611f3f565b99505b896001600160401b038111156113955761139561190e565b6040519080825280602002602001820160405280156113be578160200160208202803683370190505b50965060005b8a81101561142f576114008c8a6113f6576001836113e28689611f9e565b6113ec9190611f9e565b6103169190611f9e565b6103168385611f67565b88828151811061141257611412611ee2565b60209081029190910101528061142781611f0e565b9150506113c4565b505061144a565b506040805160008082526020820190925295505b611453866107bd565b989d919c509a50969850919650949350505050565b6005546001600160a01b0316331461147f57600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6000805482106114b057600080fd5b506000908152600160205260409020600301546001600160801b031690565b60006114da82610a11565b905060006114e78361063c565b9050816001600160a01b0316856001600160a01b03161461150757600080fd5b336001600160a01b03831614806115265750336001600160a01b038216145b8061155657506001600160a01b0382166000908152600260208181526040808420338552909201905290205460ff165b61155f57600080fd5b60008381526001602081905260409091200180546001600160a01b0319166001600160a01b03868116919091179091558116156115e25760008381526001602052604080822060020180546001600160a01b03191690555184919081907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908290a45b6001600160a01b038516600090815260026020908152604080832086845260030190915281205461161590600190611f9e565b6001600160a01b03871660009081526002602052604081208054929350909160019182019183916116469190611f9e565b815260208082019290925260409081016000908120546001600160a01b038b168252600284528282208683526001908101909452919020819055915061168d908390611f67565b6001600160a01b038816600081815260026020818152604080842087855260038101835290842095909555928252909152815491906116cb8361200f565b90915550506001600160a01b0380881660009081526002602081815260408084208a85526003018252808420849055938a168352529081208054908261171083611f0e565b909155509050611721816001611f67565b6001600160a01b0380891660008181526002602090815260408083208c845260038101835281842096909655868352600190950190528381208a90559251899391928c16917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a45050505050505050565b6040518060e001604052806007906020820280368337509192915050565b6001600160e01b0319811681146117c757600080fd5b50565b6000602082840312156117dc57600080fd5b8135610c31816117b1565b60005b838110156118025781810151838201526020016117ea565b83811115611811576000848401525b50505050565b6000815180845261182f8160208601602086016117e7565b601f01601f19169290920160200192915050565b602081526000610c316020830184611817565b60006020828403121561186857600080fd5b5035919050565b6001600160a01b03811681146117c757600080fd5b6000806040838503121561189757600080fd5b82356118a28161186f565b946020939093013593505050565b6000602082840312156118c257600080fd5b8135610c318161186f565b6000806000606084860312156118e257600080fd5b83356118ed8161186f565b925060208401356118fd8161186f565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b038111828210171561194c5761194c61190e565b604052919050565b6000602080838503121561196757600080fd5b82356001600160401b038082111561197e57600080fd5b818501915085601f83011261199257600080fd5b8135818111156119a4576119a461190e565b8060051b91506119b5848301611924565b81815291830184019184810190888411156119cf57600080fd5b938501935b838510156119ed578435825293850193908501906119d4565b98975050505050505050565b600081518084526020808501945080840160005b83811015611a325781516001600160a01b031687529582019590820190600101611a0d565b509495945050505050565b8060005b6007811015611811578151845260209384019390910190600101611a41565b600081518084526020808501945080840160005b83811015611a3257611a87878351611a3d565b60e0969096019590820190600101611a74565b608081526000611aad60808301876119f9565b8281036020840152611abf81876119f9565b90508281036040840152611ad381866119f9565b90508281036060840152611ae78185611a60565b979650505050505050565b80358015158114611b0257600080fd5b919050565b600080600060608486031215611b1c57600080fd5b8335925060208401359150611b3360408501611af2565b90509250925092565b600081518084526020808501945080840160005b83811015611a3257815187529582019590820190600101611b50565b60e081526000611b7f60e083018a611b3c565b8281036020840152611b91818a6119f9565b90508281036040840152611ba581896119f9565b90508281036060840152611bb981886119f9565b90508281036080840152611bcd8187611a60565b60a0840195909552505060c0015295945050505050565b60008060408385031215611bf757600080fd5b8235611c028161186f565b9150611c1060208401611af2565b90509250929050565b600080600080600080600080610100898b031215611c3657600080fd5b8835611c418161186f565b9a60208a01359a5060408a013599606081013599506080810135985060a0810135975060c0810135965060e00135945092505050565b60e081016107b78284611a3d565b60006001600160401b03821115611c9e57611c9e61190e565b50601f01601f191660200190565b60008060008060808587031215611cc257600080fd5b8435611ccd8161186f565b93506020850135611cdd8161186f565b92506040850135915060608501356001600160401b03811115611cff57600080fd5b8501601f81018713611d1057600080fd5b8035611d23611d1e82611c85565b611924565b818152886020838501011115611d3857600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6001600160a01b0385811682528481166020830152831660408201526101408101611d886060830184611a3d565b95945050505050565b60008060408385031215611da457600080fd5b8235611daf8161186f565b91506020830135611dbf8161186f565b809150509250929050565b60008060008060808587031215611de057600080fd5b8435611deb8161186f565b93506020850135925060408501359150611e0760608601611af2565b905092959194509250565b60c081526000611e2560c0830189611b3c565b8281036020840152611e3781896119f9565b90508281036040840152611e4b81886119f9565b90508281036060840152611e5f8187611a60565b6080840195909552505060a00152949350505050565b600060208284031215611e8757600080fd5b81516001600160401b03811115611e9d57600080fd5b8201601f81018413611eae57600080fd5b8051611ebc611d1e82611c85565b818152856020838501011115611ed157600080fd5b611d888260208301602086016117e7565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415611f2257611f22611ef8565b5060010190565b634e487b7160e01b600052601260045260246000fd5b600082611f4e57611f4e611f29565b500690565b600082611f6257611f62611f29565b500490565b60008219821115611f7a57611f7a611ef8565b500190565b6000816000190483118215151615611f9957611f99611ef8565b500290565b600082821015611fb057611fb0611ef8565b500390565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090611fe890830184611817565b9695505050505050565b60006020828403121561200457600080fd5b8151610c31816117b1565b60008161201e5761201e611ef8565b50600019019056fea264697066735822122012b4dd25fc2261f595a9d722f269b7d04e7f63401ca7c429ef3f73854b39eb7764736f6c634300080b003360c0604052600c60808190526b1999595ccb9ddd198813919560a21b60a09081526200002f9160009190620000d5565b50604080518082019091526008808252673332b2b9973bba3360c11b60209092019182526200006191600191620000d5565b503480156200006f57600080fd5b5060405162002da138038062002da183398101604081905262000092916200017b565b600280546001600160a01b039092166001600160a01b03199283161790556003805490911673e89b5b2770aa1a6bcfac6f3517510ab8e9146651179055620001ea565b828054620000e390620001ad565b90600052602060002090601f01602090048101928262000107576000855562000152565b82601f106200012257805160ff191683800117855562000152565b8280016001018555821562000152579182015b828111156200015257825182559160200191906001019062000135565b506200016092915062000164565b5090565b5b8082111562000160576000815560010162000165565b6000602082840312156200018e57600080fd5b81516001600160a01b0381168114620001a657600080fd5b9392505050565b600181811c90821680620001c257607f821691505b60208210811415620001e457634e487b7160e01b600052602260045260246000fd5b50919050565b612ba780620001fa6000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80637dc0d1d0116100665780637dc0d1d01461010957806395d89b411461011c578063be985ac914610124578063c1be1fc714610137578063c87b56dd1461014a57600080fd5b806306fdde031461009857806347ccca02146100b6578063530e784f146100e157806375f6b112146100f6575b600080fd5b6100a061015d565b6040516100ad91906115be565b60405180910390f35b6002546100c9906001600160a01b031681565b6040516001600160a01b0390911681526020016100ad565b6100f46100ef366004611609565b6101eb565b005b6100a0610104366004611626565b6102a1565b6003546100c9906001600160a01b031681565b6100a06108a7565b6100a061013236600461167b565b6108b4565b6100a0610145366004611694565b6109c9565b6100a061015836600461167b565b610cdb565b6000805461016a906116fc565b80601f0160208091040260200160405190810160405280929190818152602001828054610196906116fc565b80156101e35780601f106101b8576101008083540402835291602001916101e3565b820191906000526020600020905b8154815290600101906020018083116101c657829003601f168201915b505050505081565b600260009054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561023e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102629190611731565b6001600160a01b0316336001600160a01b03161461027f57600080fd5b600380546001600160a01b0319166001600160a01b0392909216919091179055565b606060405160200161035c907f3c73766720786d6c6e733d27687474703a2f2f7777772e77332e6f72672f323081527f30302f737667272076657273696f6e3d27312e3127207072657365727665417360208201527f70656374526174696f3d27784d6964594d6964206d656574272076696577426f60408201527f783d273020302035313220353132272077696474683d2731303025272068656960608201526a33b43a1e9398981812939f60a91b6080820152608b0190565b60405160208183030381529060405290508060405160200161037e919061174e565b6040516020818303038152906040529050806040516020016103a09190611814565b6040516020818303038152906040529050806040516020016103c29190611870565b60408051601f198184030181529190529050881561065057806103ec8a6012600560016000610e20565b6040516020016103fd929190611923565b60405160208183030381529060405290508060405160200161041f91906119b9565b6040516020818303038152906040529050806040516020016104419190611a16565b60408051601f19818403018152919052905080610480670de0b6b3a764000061046a858d611a84565b6104749190611ab9565b60126002600180610e20565b604051602001610491929190611acd565b6040516020818303038152906040529050806104b38860008060016000610e20565b6040516020016104c4929190611b43565b6040516020818303038152906040529050806104e68560008060016000610e20565b6040516020016104f7929190611bc7565b6040516020818303038152906040529050808460011461053057604051806040016040528060018152602001607360f81b815250610541565b604051806020016040528060008152505b604051602001610552929190611c4e565b604051602081830303815290604052905080610575876009600360016000610e20565b604051602001610586929190611cd1565b6040516020818303038152906040529050806105a88460008060016000610e20565b6040516020016105b9929190611d5b565b60405160208183030381529060405290508088600014610608576105e4896012600560016000610e20565b6040516020016105f49190611ddd565b604051602081830303815290604052610629565b604051806040016040528060078152602001666e6f7468696e6760c81b8152505b60405160200161063a929190611e08565b6040516020818303038152906040529050610673565b806040516020016106619190611e9c565b60405160208183030381529060405290505b84156108795760005b61069661068f655af3107a400088611ab9565b600a611163565b81116108775760005b6004811015610864576000600282106106d357604051806040016040528060038152602001621a1c9b60e91b8152506106ef565b60405180604001604052806002815260200161189b60f11b8152505b6106fa600284611ef9565b15610720576040518060400160405280600381526020016206872760eb1b81525061073c565b60405180604001604052806002815260200161062760f31b8152505b60405160200161074d929190611f0d565b604051602081830303815290604052905083816002841061078757604051806040016040528060018152602001602d60f81b815250610798565b604051806020016040528060008152505b6107b16107a6876010611a84565b600080600080610e20565b6040516020016107c49493929190611f9b565b60408051601f19818403018152919052935082156108515783816107e9600285611ef9565b1561080d57604051806040016040528060018152602001602d60f81b81525061081e565b604051806020016040528060008152505b61082c6107a6876010611a84565b60405160200161083f9493929190612016565b60405160208183030381529060405293505b508061085c816120a4565b91505061069f565b508061086f816120a4565b91505061067c565b505b8060405160200161088a91906120bf565b604051602081830303815290604052905098975050505050505050565b6001805461016a906116fc565b6002546040516302a7959b60e61b8152600481018390526060916000916001600160a01b039091169063a9e566c09060240160e060405180830381865afa158015610903573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109279190612244565b80516020808301516040808501516060860151608087015160a088015160c08901516003548651634c6afee560e11b815296519a9b506109c29a9798959794969395929491936001600160a01b03909116926398d5fdca926004838101938290030181865afa15801561099e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101049190612276565b9392505050565b606060006109d88b60066111ad565b6109e18c61131d565b6109ea8d61131d565b6040516020016109fc9392919061228f565b604051602081830303815290604052905080610a26610a218c8c8c8c8c8c8c8c6102a1565b61142a565b604051602001610a37929190612389565b60408051601f1981840301815291905290508915610bfd5780610a618b6012600560006001610e20565b604051602001610a7292919061240b565b604051602081830303815290604052905080610a958a6012600560006001610e20565b604051602001610aa692919061247e565b604051602081830303815290604052905080610ac789600080600080610e20565b604051602001610ad89291906124d7565b604051602081830303815290604052905080610afb886009600560006001610e20565b604051602001610b0c929190612530565b604051602081830303815290604052905080610b2d86600080600080610e20565b604051602001610b3e9291906125a6565b604051602081830303815290604052905080610b5f85600080600080610e20565b604051602001610b70929190612622565b60408051601f19818403018152919052905080610ba06107a6610b996509184e72a0008e611ab9565b6002611163565b604051602001610bb192919061269f565b60408051601f19818403018152919052905080610bda6107a6610b996509184e72a0008d611ab9565b604051602001610beb92919061272c565b60405160208183030381529060405290505b8515610c81578060008b11610c215760405180602001604052806000815250610c3c565b604051806040016040528060018152602001600b60fa1b8152505b610c5d610c5261068f655af3107a40008b611ab9565b6107a69060016127b9565b604051602001610c6f939291906127d1565b60405160208183030381529060405290505b80604051602001610c929190612874565b6040516020818303038152906040529050610cac8161142a565b604051602001610cbc919061289a565b6040516020818303038152906040529150509998505050505050505050565b600254604051631c96a19760e31b81526004810183905260609160009182916001600160a01b03169063e4b50cb89060240161014060405180830381865afa158015610d2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4f91906128df565b935093505050610e188282600060078110610d6c57610d6c612260565b6020020151836001602002015184600260200201518560036020020151866004602002015187600560200201518860066020020151600360009054906101000a90046001600160a01b03166001600160a01b03166398d5fdca6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101459190612276565b949350505050565b60606000848611610e315785610e33565b845b90506000818711610e45576000610e4f565b610e4f828861293d565b610e5a90600a612a3a565b610e649089611ab9565b905080610e8e57604051806040016040528060018152602001600360fc1b8152509250505061115a565b6001815b6009811115610eba57610ea6600a82611ab9565b905081610eb2816120a4565b925050610e92565b838211610ed157610ecc8460016127b9565b610ed3565b815b9050600086158015610eee5750610eeb8560016127b9565b82115b610ef9576000610f32565b846001610f06828561293d565b610f10919061293d565b11610f30576001610f21868461293d565b610f2b919061293d565b610f32565b845b905060005b610f41828461293d565b811015611153576000610f54858561293d565b8210610f9657600a6001610f68848761293d565b610f72919061293d565b610f7d90600a612a3a565b610f879088611ab9565b610f919190611ef9565b610f99565b60005b60408051600180825281830190925291925060009190602082018180368337019050509050610fc9826030612a46565b60f81b81600081518110610fdf57610fdf612260565b60200101906001600160f81b031916908160001a9053508881604051602001611009929190612a6b565b60408051601f1981840301815291905298506001611027898761293d565b611031919061293d565b83101561109c578a801561106f5750600361104c898761293d565b6110569190611ef9565b60036110638560016127b9565b61106d9190611ef9565b145b1561109757886040516020016110859190612a9a565b60405160208183030381529060405298505b61113e565b891580156110f257506001836110b2868861293d565b6110bc919061293d565b6110c6919061293d565b6110d190600a612a3a565b6110dc85600a612a3a565b6110e69089611ab9565b6110f09190611ef9565b155b156110fe575050611153565b600161110a898761293d565b611114919061293d565b83141561113e578860405160200161112c9190612abf565b60405160208183030381529060405298505b5050808061114b906120a4565b915050610f37565b5050505050505b95945050505050565b600080821161117157600080fd5b60005b61117f60018461293d565b8411156111a4576111908385611ab9565b93508061119c816120a4565b915050611174565b90505b92915050565b6060601482106111bc57600080fd5b50604080516020810190915260008082526111d68461131d565b905060006111e5846002611a84565b6111f09060026127b9565b905060005b611200856002611a84565b61120b9060026127b9565b811015611314576040805160018082528183019092526000916020820181803683370190505090508361123f8760026127b9565b8310611260578361125184602a6127b9565b61125b919061293d565b611262565b825b8151811061127257611272612260565b602001015160f81c60f81b8160008151811061129057611290612260565b60200101906001600160f81b031916908160001a90535084816040516020016112ba929190612a6b565b60408051601f1981840301815291905294506112d78660016127b9565b82141561130157846040516020016112ef9190612ae4565b60405160208183030381529060405294505b508061130c816120a4565b9150506111f5565b50505092915050565b604080518082019091526002815261060f60f31b602082015260005b6028811015611424576000601061135183602761293d565b61135c906004611a84565b856001600160a01b0316901c6113729190612b0b565b6040805160018082528183019092526001600160a01b0392909216925060009190602082018180368337019050509050600982116113b15760306113b4565b60575b6113be9083612a46565b60f81b816000815181106113d4576113d4612260565b60200101906001600160f81b031916908160001a90535083816040516020016113fe929190612a6b565b60405160208183030381529060405293505050808061141c906120a4565b915050611339565b50919050565b606081516000141561144a57505060408051602081019091526000815290565b6000604051806060016040528060408152602001612b32604091399050600060038451600261147991906127b9565b6114839190611ab9565b61148e906004611a84565b905061149b8160206127b9565b67ffffffffffffffff8111156114b3576114b36121b2565b6040519080825280601f01601f1916602001820160405280156114dd576020820181803683370190505b509250808352600182018485518101602086015b8183101561154b5760039283018051603f601282901c811687015160f890811b8552600c83901c8216880151811b6001860152600683901c8216880151811b60028601529116860151901b938201939093526004016114f1565b600388510660018114611565576002811461157657611582565b613d3d60f01b600119830152611582565b603d60f81b6000198301525b50505050505050919050565b60005b838110156115a9578181015183820152602001611591565b838111156115b8576000848401525b50505050565b60208152600082518060208401526115dd81604085016020870161158e565b601f01601f19169190910160400192915050565b6001600160a01b038116811461160657600080fd5b50565b60006020828403121561161b57600080fd5b81356111a4816115f1565b600080600080600080600080610100898b03121561164357600080fd5b505086359860208801359850604088013597606081013597506080810135965060a0810135955060c0810135945060e0013592509050565b60006020828403121561168d57600080fd5b5035919050565b60008060008060008060008060006101208a8c0312156116b357600080fd5b89356116be816115f1565b9b60208b01359b5060408b01359a60608101359a506080810135995060a0810135985060c0810135975060e081013596506101000135945092505050565b600181811c9082168061171057607f821691505b6020821081141561142457634e487b7160e01b600052602260045260246000fd5b60006020828403121561174357600080fd5b81516111a4816115f1565b6000825161176081846020870161158e565b7f3c646566733e3c7374796c6520747970653d27746578742f637373273e7465789201918252507f747b746578742d616e63686f723a6d6964646c653b616c69676e6d656e742d6260208201527f6173656c696e653a63656e7472616c3b7d747370616e3e747370616e7b66696c60408201527f6c3a233033613966343b666f6e742d7765696768743a3730303b7d3c2f73747960608201526936329f1e17b232b3399f60b11b6080820152608a01919050565b6000825161182681846020870161158e565b7f3c726563742077696474683d273130302527206865696768743d27313030252792019182525071103334b6361e93919919191919191390179f60711b6020820152603201919050565b6000825161188281846020870161158e565b7f3c7465787420783d27302720793d2732353627207472616e73666f726d3d27749201918252507f72616e736c6174652832353629272066696c6c3d27236630663866662720666f60208201527f6e742d66616d696c793d27417269616c2c73616e732d73657269662720666f6e60408201527f742d7765696768743d273630302720666f6e742d73697a653d273330273e00006060820152607e01919050565b6000835161193581846020880161158e565b80830190507f3c747370616e20783d2730272064793d272d313833273e596f75207370656e74815269101e3a39b830b71f674f60b11b6020820152835161198381602a84016020880161158e565b7f3c2f747370616e3e206f6e206761733c2f747370616e3e000000000000000000602a9290910191820152604101949350505050565b600082516119cb81846020870161158e565b7f3c747370616e20783d2730272064793d273335273e6265666f726520626c6f6392019182525072359018999c989b1a1a98171e17ba39b830b71f60691b6020820152603301919050565b60008251611a2881846020870161158e565b7f3c747370616e20783d2730272064793d273335273e5269676874206e6f772c209201918252506d3a3430ba13b99e17ba39b830b71f60911b6020820152602e01919050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615611a9e57611a9e611a6e565b500290565b634e487b7160e01b600052601260045260246000fd5b600082611ac857611ac8611aa3565b500490565b60008351611adf81846020880161158e565b7f3c747370616e20783d2730272064793d273335273e3c747370616e3e240000009083019081528351611b1981601d84016020880161158e565b701e17ba39b830b71f171e17ba39b830b71f60791b601d9290910191820152602e01949350505050565b60008351611b5581846020880161158e565b80830190507f3c747370616e20783d2730272064793d273730273e596f752075736564203c7481526439b830b71f60d91b60208201528351611b9e81602584016020880161158e565b6f1e17ba39b830b71f1e17ba39b830b71f60811b60259290910191820152603501949350505050565b60008351611bd981846020880161158e565b80830190507f3c747370616e20783d2730272064793d273335273e67617320746f2073656e64815267101e3a39b830b71f60c11b60208201528351611c2581602884016020880161158e565b6f1e17ba39b830b71f1e17ba39b830b71f60811b60289290910191820152603801949350505050565b60008351611c6081846020880161158e565b80830190507f3c747370616e20783d2730272064793d273335273e7472616e73616374696f6e81528351611c9b81602084016020880161158e565b7f2c207769746820616e20617665726167653c2f747370616e3e0000000000000060209290910191820152603901949350505050565b60008351611ce381846020880161158e565b80830190507f3c747370616e20783d2730272064793d273335273e7072696365206f66203c7481526439b830b71f60d91b60208201528351611d2c81602584016020880161158e565b751e17ba39b830b71f1023bbb2b4971e17ba39b830b71f60511b60259290910191820152603b01949350505050565b60008351611d6d81846020880161158e565b7f3c747370616e20783d2730272064793d273730273e3c747370616e3e000000009083019081528351611da781601c84016020880161158e565b7f3c2f747370616e3e206f66207468656d206661696c65642c3c2f747370616e3e601c9290910191820152603c01949350505050565b61674f60f11b81528151600090611dfb81600285016020870161158e565b9190910160020192915050565b60008351611e1a81846020880161158e565b80830190507f3c747370616e20783d2730272064793d273335273e636f7374696e6720796f75815267101e3a39b830b71f60c11b60208201528351611e6681602884016020880161158e565b7f3c2f747370616e3e2e3c2f747370616e3e3c2f746578743e000000000000000060289290910191820152604001949350505050565b60008251611eae81846020870161158e565b7f3c747370616e20783d2730272064793d2738273e446964206e6f74207175616c9201918252507234b33c971e17ba39b830b71f1e17ba32bc3a1f60691b6020820152603301919050565b600082611f0857611f08611aa3565b500690565b683c7465787420783d2760b81b815260008351611f3181600985016020880161158e565b642720793d2760d81b6009918401918201528351611f5681600e84016020880161158e565b7f2720666f6e742d73697a653d27313027207472616e73666f726d3d277472616e600e9290910191820152650e6d8c2e8ca560d31b602e820152603401949350505050565b60008551611fad818460208a0161158e565b855190830190611fc1818360208a0161158e565b8551910190611fd481836020890161158e565b8451910190611fe781836020880161158e565b6214939f60e91b91019081526c714ed277dc479e17ba32bc3a1f60991b60038201526010019695505050505050565b60008551612028818460208a0161158e565b85519083019061203c818360208a0161158e565b610c0b60f21b9101908152845161205a81600284016020890161158e565b845191019061207081600284016020880161158e565b6214939f60e91b600292909101918201526c714ed277dc479e17ba32bc3a1f60991b60058201526012019695505050505050565b60006000198214156120b8576120b8611a6e565b5060010190565b600082516120d181846020870161158e565b7f3c7465787420783d27302720793d2735303027207472616e73666f726d3d27749201918252507f72616e736c6174652832353629272066696c6c3d27236630663866662720666f60208201527f6e742d66616d696c793d27417269616c2c73616e732d73657269662720666f6e60408201527f742d7765696768743d273630302720666f6e742d73697a653d273130273e3c7460608201527f7370616e3e666565733c747370616e3e2e7774663c2f747370616e3e3c2f74736080820152703830b71f1e17ba32bc3a1f1e17b9bb339f60791b60a082015260b101919050565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126121d957600080fd5b60405160e0810181811067ffffffffffffffff8211171561220a57634e487b7160e01b600052604160045260246000fd5b6040528060e084018581111561221f57600080fd5b845b81811015612239578051835260209283019201612221565b509195945050505050565b600060e0828403121561225657600080fd5b6109c283836121c8565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561228857600080fd5b5051919050565b683d913730b6b2911d1160b91b815283516000906122b481600985016020890161158e565b7f222c226465736372697074696f6e223a225b666565732e7774665d28687474706009918401918201527f733a2f2f666565732e7774662920736e617073686f7420617420626c6f636b2060298201526d313339313634353020666f72205b60901b6049820152845161232e81605784016020890161158e565b7f5d2868747470733a2f2f65746865727363616e2e696f2f616464726573732f0060579290910191820152835161236c81607684016020880161158e565b620a488b60ea1b6076929091019182015260790195945050505050565b6000835161239b81846020880161158e565b80830190507f22696d616765223a22646174613a696d6167652f7376672b786d6c3b626173658152620d8d0b60ea1b602082015283516123e281602384016020880161158e565b6f222c2261747472696275746573223a5b60801b60239290910191820152603301949350505050565b6000835161241d81846020880161158e565b80830190507f7b2274726169745f74797065223a22546f74616c2046656573222c2276616c7581526232911d60e91b6020820152835161246481602384016020880161158e565b607d60f81b60239290910191820152602401949350505050565b6000835161249081846020880161158e565b80830190507f2c7b2274726169745f74797065223a224661696c2046656573222c2276616c7581526232911d60e91b6020820152835161246481602384016020880161158e565b600083516124e981846020880161158e565b80830190507f2c7b2274726169745f74797065223a22546f74616c20476173222c2276616c7581526232911d60e91b6020820152835161246481602384016020880161158e565b6000835161254281846020880161158e565b80830190507f2c7b2274726169745f74797065223a22417665726167652047776569222c227681526530b63ab2911d60d11b6020820152835161258c81602684016020880161158e565b607d60f81b60269290910191820152602701949350505050565b600083516125b881846020880161158e565b80830190507f2c7b2274726169745f74797065223a22546f74616c205472616e73616374696f81526b37399116113b30b63ab2911d60a11b6020820152835161260881602c84016020880161158e565b607d60f81b602c9290910191820152602d01949350505050565b6000835161263481846020880161158e565b80830190507f2c7b2274726169745f74797065223a224661696c6564205472616e736163746981526c37b7399116113b30b63ab2911d60991b6020820152835161268581602d84016020880161158e565b607d60f81b602d9290910191820152602e01949350505050565b600083516126b181846020880161158e565b80830190507f2c7b22646973706c61795f74797065223a226e756d626572222c22747261697481527f5f74797065223a225370656e646572204c6576656c222c2276616c7565223a006020820152835161271281603f84016020880161158e565b607d60f81b603f9290910191820152604001949350505050565b6000835161273e81846020880161158e565b80830190507f2c7b22646973706c61795f74797065223a226e756d626572222c22747261697481527f5f74797065223a224f6f66204c6576656c222c2276616c7565223a00000000006020820152835161279f81603b84016020880161158e565b607d60f81b603b9290910191820152603c01949350505050565b600082198211156127cc576127cc611a6e565b500190565b600084516127e381846020890161158e565b8451908301906127f781836020890161158e565b8082019150507f7b22646973706c61795f74797065223a226e756d626572222c2274726169745f81527f74797065223a22446f6e61746f72204c6576656c222c2276616c7565223a00006020820152835161285981603e84016020880161158e565b607d60f81b603e9290910191820152603f0195945050505050565b6000825161288681846020870161158e565b615d7d60f01b920191825250600201919050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516128d281601d85016020870161158e565b91909101601d0192915050565b60008060008061014085870312156128f657600080fd5b8451612901816115f1565b6020860151909450612912816115f1565b6040860151909350612923816115f1565b915061293286606087016121c8565b905092959194509250565b60008282101561294f5761294f611a6e565b500390565b600181600019825b808611156129905782820483111561297657612976611a6e565b8086161561298357928202925b94851c949180029161295c565b50509250929050565b6000826129a8575060016111a7565b816129b5575060006111a7565b81600181146129cb57600281146129d5576129f1565b60019150506111a7565b60ff8411156129e6576129e6611a6e565b50506001821b6111a7565b5060208310610133831016604e8410600b8410161715612a14575081810a6111a7565b612a1e8383612954565b8060001904821115612a3257612a32611a6e565b029392505050565b60006109c28383612999565b600060ff821660ff84168060ff03821115612a6357612a63611a6e565b019392505050565b60008351612a7d81846020880161158e565b835190830190612a9181836020880161158e565b01949350505050565b60008251612aac81846020870161158e565b600b60fa1b920191825250600101919050565b60008251612ad181846020870161158e565b601760f91b920191825250600101919050565b60008251612af681846020870161158e565b6271405360e91b920191825250600301919050565b60006001600160a01b0383811680612b2557612b25611aa3565b9216919091069291505056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212208e2b5e515fb02168298df9697376a6434523e033f88d7913a9684bb0cf33e5e964736f6c634300080b0033608060405234801561001057600080fd5b506101f9806100206000396000f3fe6080604052600436106100225760003560e01c806386d1a69f1461002e57600080fd5b3661002957005b600080fd5b34801561003a57600080fd5b50610043610045565b005b30803161005157600080fd5b736129e7bcb71c0d7d4580141c4e6a995f16293f426108fc61007e600a6001600160a01b038516316101a1565b6040518115909202916000818181858888f193505050501580156100a6573d6000803e3d6000fd5b5073c9aebdd8fd0d52c35a32fd9155467cf28ce474c36108fc6100d460036001600160a01b038516316101a1565b6040518115909202916000818181858888f193505050501580156100fc573d6000803e3d6000fd5b5073dee79ed62b42e30ea7ebb6f1b7a3f04143d18b7f6108fc61012a60026001600160a01b038516316101a1565b6040518115909202916000818181858888f19350505050158015610152573d6000803e3d6000fd5b5060405173575446aa9e9647c40edb7a467e45c5916add1538906001600160a01b0383163180156108fc02916000818181858888f1935050505015801561019d573d6000803e3d6000fd5b5050565b6000826101be57634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220fe3f3505f2bdd4705e1008de1d644cef4162746ee8a345c0e6b11248eafa64d564736f6c634300080b0033608060405234801561001057600080fd5b50600080546001600160a01b0319167365dd4990719be9b20322e4e8d3bd77a4401a03571790556100444262278d0061005e565b600155600280546001600160a01b03191633179055610084565b6000821982111561007f57634e487b7160e01b600052601160045260246000fd5b500190565b61043b806100936000396000f3fe60806040526004361061007f5760003560e01c80638da5cb5b1161004e5780638da5cb5b14610126578063a64b6e5f14610146578063ce0617ec14610166578063e52253811461018a57600080fd5b806313af40351461008b5780636ff92f50146100ad5780637b1a4909146100e45780638380edb71461010457600080fd5b3661008657005b600080fd5b34801561009757600080fd5b506100ab6100a6366004610352565b61019f565b005b3480156100b957600080fd5b506002546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100f057600080fd5b506100ab6100ff366004610376565b6101d8565b34801561011057600080fd5b50600154421160405190151581526020016100db565b34801561013257600080fd5b506000546100c7906001600160a01b031681565b34801561015257600080fd5b506100ab6101613660046103a2565b610238565b34801561017257600080fd5b5061017c60015481565b6040519081526020016100db565b34801561019657600080fd5b506100ab6102d6565b6000546001600160a01b031633146101b657600080fd5b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146101ef57600080fd5b60015442116101fd57600080fd5b6040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015610233573d6000803e3d6000fd5b505050565b6000546001600160a01b0316331461024f57600080fd5b600154421161025d57600080fd5b60405163a9059cbb60e01b81526001600160a01b0383811660048301526024820183905284169063a9059cbb906044016020604051808303816000875af11580156102ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102d091906103e3565b50505050565b600260009054906101000a90046001600160a01b03166001600160a01b031663372500ab6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561032657600080fd5b505af11580156102d0573d6000803e3d6000fd5b6001600160a01b038116811461034f57600080fd5b50565b60006020828403121561036457600080fd5b813561036f8161033a565b9392505050565b6000806040838503121561038957600080fd5b82356103948161033a565b946020939093013593505050565b6000806000606084860312156103b757600080fd5b83356103c28161033a565b925060208401356103d28161033a565b929592945050506040919091013590565b6000602082840312156103f557600080fd5b8151801515811461036f57600080fdfea264697066735822122053bbb900903fde8b2fb32ea2515decab31dd9e4b2aba80206c24f3e60eb9a87464736f6c634300080b0033608060405234801561001057600080fd5b5060405162001d4e38038062001d4e83398101604081905261003191610083565b60008390554282116100435742610045565b815b600181905560025560078054336001600160a01b031991821617909155600880549091166001600160a01b0392909216919091179055506100c99050565b60008060006060848603121561009857600080fd5b83516020850151604086015191945092506001600160a01b03811681146100be57600080fd5b809150509250925092565b611c7580620000d96000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c8063853828b6116100a2578063b6b55f2511610071578063b6b55f2514610279578063bd77ac2c1461028c578063efca2eed1461029f578063fdb5a03e146102a7578063ff50abdc146102af57600080fd5b8063853828b6146102505780639d76ea5814610258578063a2e6204514610269578063a9045fec1461027157600080fd5b806357f6b812116100e957806357f6b812146101715780635c99d8cc146101d75780636be32e73146102005780636ff92f501461022357806378e979251461024857600080fd5b80632e1a7d4d1461011b5780632f4f21e214610130578063479ba7ae146101435780634e71d92d14610169575b600080fd5b61012e6101293660046119e7565b6102b7565b005b61012e61013e366004611a1c565b61043c565b610156610151366004611a46565b6105c8565b6040519081526020015b60405180910390f35b61012e610614565b61018461017f366004611a46565b610714565b604080519b8c5260208c019a909a52988a01979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015261012083015261014082015261016001610160565b6101566101e5366004611a46565b6001600160a01b031660009081526006602052604090205490565b61021361020e366004611a61565b610932565b6040519015158152602001610160565b6007546001600160a01b03165b6040516001600160a01b039091168152602001610160565b600154610156565b61012e610985565b6008546001600160a01b0316610230565b61012e6109a4565b610156610b68565b61012e6102873660046119e7565b610bce565b61012e61029a3660046119e7565b610bd8565b610156610d5d565b61012e610d73565b600554610156565b6000811180156102d65750336000908152600660205260409020548111155b6102df57600080fd5b6102e76109a4565b80600060050160008282546102fc9190611afe565b90915550503360009081526006602052604081208054839290610320908490611afe565b90915550506004546103329082611b15565b3360009081526006602052604081206001018054909190610354908490611b34565b909155506000905061036582610e11565b6008549091506001600160a01b031663a9059cbb336103848486611afe565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af11580156103cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103f39190611b73565b506103fd81610e64565b604080518381526020810183905233917ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568910160405180910390a25050565b6000811161044957600080fd5b6104516109a4565b6008546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa15801561049a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104be9190611b95565b6008546040516323b872dd60e01b8152336004820152306024820152604481018590529192506001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610516573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061053a9190611b73565b506008546040516370a0823160e01b815230600482015260009183916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610588573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ac9190611b95565b6105b69190611afe565b90506105c28482610ea8565b50505050565b6001600160a01b038116600090815260066020526040812060018101549054600454600160401b92916105fa91611b15565b6106049190611b34565b61060e9190611bc4565b92915050565b61061c6109a4565b6000610627336105c8565b905080156107115761063d600160401b82611b15565b336000908152600660205260408120600101805490919061065f908490611be6565b909155505060075460405163a9059cbb60e01b8152336004820152602481018390526001600160a01b039091169063a9059cbb906044016020604051808303816000875af11580156106b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106d99190611b73565b5060405181815233907f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4906020015b60405180910390a25b50565b600080600080600080600080600080600061072e60015490565b9a50610738610d5d565b9950610742610b68565b985061075668056bc75e2d63100000610e11565b975061076160055490565b600254909750421161077457600061079f565b61079f610796610788600060020154610f9b565b61079142610f9b565b610ffb565b60005490611026565b6007546040516370a0823160e01b81526001600160a01b038f811660048301529298509116906370a0823190602401602060405180830381865afa1580156107eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080f9190611b95565b6008546040516370a0823160e01b81526001600160a01b038f811660048301529297509116906370a0823190602401602060405180830381865afa15801561085b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087f9190611b95565b600854604051636eb1769f60e11b81526001600160a01b038f8116600483015230602483015292965091169063dd62ed3e90604401602060405180830381865afa1580156108d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f59190611b95565b92506109168c6001600160a01b031660009081526006602052604090205490565b91506109218c6105c8565b905091939597999b90929496989a50565b600061093c611032565b801561095257506008546001600160a01b031633145b61095b57600080fd5b6000841161096857600080fd5b6109706109a4565b61097a8585610ea8565b506001949350505050565b33600090815260066020526040902054801561071157610711816102b7565b6002544290811180156109bf575060006109bd60055490565b115b156107115760006109e36107966109da600060020154610f9b565b61079185610f9b565b60035490915015610a03576003546109fb9082611c27565b600060035590505b6007546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610a4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a709190611b95565b6007546040805163372500ab60e01b815290519293506001600160a01b039091169163372500ab9160048082019260009290919082900301818387803b158015610ab957600080fd5b505af1158015610acd573d6000803e3d6000fd5b50506007546040516370a0823160e01b81523060048201528493506001600160a01b0390911691506370a0823190602401602060405180830381865afa158015610b1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3f9190611b95565b610b499190611afe565b610b539083611c27565b60028490559150610b6382611070565b505050565b6000610b7360015490565b421015610baf57610baa610796610b91610b8c60015490565b610f9b565b610791610b9d60015490565b610b8c9062015180611c27565b905090565b610baa610796610bbe42610f9b565b610791610b8c4262015180611c27565b610711338261043c565b60008111610be557600080fd5b610bed6109a4565b6007546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a0823190602401602060405180830381865afa158015610c36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c5a9190611b95565b6007546040516323b872dd60e01b8152336004820152306024820152604481018590529192506001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610cb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd69190611b73565b506007546040516370a0823160e01b815230600482015260009183916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610d24573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d489190611b95565b610d529190611afe565b9050610b6381610e64565b6000610baa610796610d6e42610f9b565b6110d8565b610d7b611032565b610d8457600080fd5b610d8c6109a4565b6000610d97336105c8565b9050801561071157610dad600160401b82611b15565b3360009081526006602052604081206001018054909190610dcf908490611be6565b90915550610ddf90503382610ea8565b60405181815233907fbd654390d0d973e8c8376ed6053be8658870df892687852cc5c914d700291b8790602001610708565b6000610e1b611032565b610e2657600061060e565b61060e610e35610d6e42610f9b565b610e4790670de0b6b3a7640000611afe565b6064610e54600586611b15565b610e5e9190611bc4565b90611026565b801561071157600154421080610e7a5750600554155b15610e9f578060006003016000828254610e949190611c27565b909155506107119050565b61071181611070565b6000610eb382610e11565b90506000610ec18284611afe565b90508060006005016000828254610ed89190611c27565b90915550506001600160a01b03841660009081526006602052604081208054839290610f05908490611c27565b9091555050600454610f179082611b15565b6001600160a01b03851660009081526006602052604081206001018054909190610f42908490611be6565b90915550610f51905082610e64565b60408051848152602081018490526001600160a01b038616917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a250505050565b600080610fa760015490565b905080831015610fba5750600092915050565b610ff4610fd262278d00670de0b6b3a7640000611b15565b610fdc8386611afe565b610fee90670de0b6b3a7640000611b15565b906110fc565b9392505050565b60008282101561100a57600080fd5b611013836110d8565b61101c836110d8565b610ff49190611afe565b6000610ff48383611111565b60006110466008546001600160a01b031690565b6001600160a01b03166110616007546001600160a01b031690565b6001600160a01b031614905090565b600554611081600160401b83611b15565b61108b9190611bc4565b6004805460009061109d908490611c27565b90915550506040518181527f3ac0594a85a20354f9dc74f33728416d19ce00d04a406c108cc2dcf2cecea1349060200160405180910390a150565b6000806110e4836111d8565b9050610ff481610fee670de0b6b3a764000082611afe565b6000610ff483670de0b6b3a76400008461121e565b60008080600019848609848602925082811083820303915050670de0b6b3a7640000811061115a5760405163698d9a0160e11b8152600481018290526024015b60405180910390fd5b600080670de0b6b3a76400008688099150506706f05b59d3b1ffff8111826111945780670de0b6b3a764000085040194505050505061060e565b620400008285030493909111909103600160ee1b02919091177faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac106690201905092915050565b6000680a688906bd8b000000821061120657604051634a4f26f160e01b815260048101839052602401611151565b670de0b6b3a7640000604083901b04610ff4816112eb565b6000808060001985870985870292508281108382030391505080600014156112595783828161124f5761124f611bae565b0492505050610ff4565b83811061128357604051631dcf306360e21b81526004810182905260248101859052604401611151565b600084868809600260036001881981018916988990049182028318808302840302808302840302808302840302808302840302808302840302918202909203026000889003889004909101858311909403939093029303949094049190911702949350505050565b600160bf1b67800000000000000082161561130f5768016a09e667f3bcc9090260401c5b67400000000000000082161561132e576801306fe0a31b7152df0260401c5b67200000000000000082161561134d576801172b83c7d517adce0260401c5b67100000000000000082161561136c5768010b5586cf9890f62a0260401c5b67080000000000000082161561138b576801059b0d31585743ae0260401c5b6704000000000000008216156113aa57680102c9a3e778060ee70260401c5b6702000000000000008216156113c95768010163da9fb33356d80260401c5b6701000000000000008216156113e857680100b1afa5abcbed610260401c5b66800000000000008216156114065768010058c86da1c09ea20260401c5b6640000000000000821615611424576801002c605e2e8cec500260401c5b662000000000000082161561144257680100162f3904051fa10260401c5b6610000000000000821615611460576801000b175effdc76ba0260401c5b660800000000000082161561147e57680100058ba01fb9f96d0260401c5b660400000000000082161561149c5768010002c5cc37da94920260401c5b66020000000000008216156114ba576801000162e525ee05470260401c5b66010000000000008216156114d85768010000b17255775c040260401c5b658000000000008216156114f5576801000058b91b5bc9ae0260401c5b6540000000000082161561151257680100002c5c89d5ec6d0260401c5b6520000000000082161561152f5768010000162e43f4f8310260401c5b6510000000000082161561154c57680100000b1721bcfc9a0260401c5b650800000000008216156115695768010000058b90cf1e6e0260401c5b65040000000000821615611586576801000002c5c863b73f0260401c5b650200000000008216156115a357680100000162e430e5a20260401c5b650100000000008216156115c0576801000000b1721835510260401c5b6480000000008216156115dc57680100000058b90c0b490260401c5b6440000000008216156115f85768010000002c5c8601cc0260401c5b642000000000821615611614576801000000162e42fff00260401c5b6410000000008216156116305768010000000b17217fbb0260401c5b64080000000082161561164c576801000000058b90bfce0260401c5b64040000000082161561166857680100000002c5c85fe30260401c5b6402000000008216156116845768010000000162e42ff10260401c5b6401000000008216156116a057680100000000b17217f80260401c5b63800000008216156116bb5768010000000058b90bfc0260401c5b63400000008216156116d6576801000000002c5c85fe0260401c5b63200000008216156116f157680100000000162e42ff0260401c5b631000000082161561170c576801000000000b17217f0260401c5b630800000082161561172757680100000000058b90c00260401c5b63040000008216156117425768010000000002c5c8600260401c5b630200000082161561175d576801000000000162e4300260401c5b63010000008216156117785768010000000000b172180260401c5b62800000821615611792576801000000000058b90c0260401c5b624000008216156117ac57680100000000002c5c860260401c5b622000008216156117c65768010000000000162e430260401c5b621000008216156117e057680100000000000b17210260401c5b620800008216156117fa5768010000000000058b910260401c5b62040000821615611814576801000000000002c5c80260401c5b6202000082161561182e57680100000000000162e40260401c5b62010000821615611848576801000000000000b1720260401c5b61800082161561186157680100000000000058b90260401c5b61400082161561187a5768010000000000002c5d0260401c5b612000821615611893576801000000000000162e0260401c5b6110008216156118ac5768010000000000000b170260401c5b6108008216156118c5576801000000000000058c0260401c5b6104008216156118de57680100000000000002c60260401c5b6102008216156118f757680100000000000001630260401c5b61010082161561191057680100000000000000b10260401c5b608082161561192857680100000000000000590260401c5b6040821615611940576801000000000000002c0260401c5b602082161561195857680100000000000000160260401c5b6010821615611970576801000000000000000b0260401c5b600882161561198857680100000000000000060260401c5b60048216156119a057680100000000000000030260401c5b60028216156119b857680100000000000000010260401c5b60018216156119d057680100000000000000010260401c5b670de0b6b3a76400000260409190911c60bf031c90565b6000602082840312156119f957600080fd5b5035919050565b80356001600160a01b0381168114611a1757600080fd5b919050565b60008060408385031215611a2f57600080fd5b611a3883611a00565b946020939093013593505050565b600060208284031215611a5857600080fd5b610ff482611a00565b60008060008060608587031215611a7757600080fd5b611a8085611a00565b935060208501359250604085013567ffffffffffffffff80821115611aa457600080fd5b818701915087601f830112611ab857600080fd5b813581811115611ac757600080fd5b886020828501011115611ad957600080fd5b95989497505060200194505050565b634e487b7160e01b600052601160045260246000fd5b600082821015611b1057611b10611ae8565b500390565b6000816000190483118215151615611b2f57611b2f611ae8565b500290565b60008083128015600160ff1b850184121615611b5257611b52611ae8565b6001600160ff1b0384018313811615611b6d57611b6d611ae8565b50500390565b600060208284031215611b8557600080fd5b81518015158114610ff457600080fd5b600060208284031215611ba757600080fd5b5051919050565b634e487b7160e01b600052601260045260246000fd5b600082611be157634e487b7160e01b600052601260045260246000fd5b500490565b600080821280156001600160ff1b0384900385131615611c0857611c08611ae8565b600160ff1b8390038412811615611c2157611c21611ae8565b50500190565b60008219821115611c3a57611c3a611ae8565b50019056fea264697066735822122085ab3ecdd07e5de48258a7e7b79867e88425d9b2f19e550dd19f024e9e9d633964736f6c634300080b0033608060405234801561001057600080fd5b50600080546001600160a01b03191633179055610597806100326000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636ff92f501461003b578063abc6fd0b1461005a575b600080fd5b600054604080516001600160a01b039092168252519081900360200190f35b610062610064565b005b600080546040805163372500ab60e01b815290516001600160a01b039092169263372500ab9260048084019382900301818387803b1580156100a557600080fd5b505af11580156100b9573d6000803e3d6000fd5b5050600080546040516370a0823160e01b81523060048201529193506001600160a01b031691506370a0823190602401602060405180830381865afa158015610106573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012a91906104a7565b905080156104a457600061013f6005836104c0565b905060008054906101000a90046001600160a01b03166001600160a01b031663c5f956af6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610192573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101b691906104e2565b6001600160a01b031663e52253816040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156101f057600080fd5b505af1158015610204573d6000803e3d6000fd5b50506000546040805163c5f956af60e01b815290516001600160a01b03909216935063a9059cbb9250839163c5f956af916004808201926020929091908290030181865afa15801561025a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061027e91906104e2565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018490526044016020604051808303816000875af11580156102cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ef9190610512565b5060008054906101000a90046001600160a01b03166001600160a01b031663788bff686040518163ffffffff1660e01b8152600401602060405180830381865afa158015610341573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061036591906104e2565b6001600160a01b031663bd77ac2c826040518263ffffffff1660e01b815260040161039291815260200190565b600060405180830381600087803b1580156103ac57600080fd5b505af11580156103c0573d6000803e3d6000fd5b5050505060008054906101000a90046001600160a01b03166001600160a01b031663699ea5836040518163ffffffff1660e01b8152600401602060405180830381865afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043991906104e2565b6001600160a01b031663bd77ac2c610452836003610534565b6040518263ffffffff1660e01b815260040161047091815260200190565b600060405180830381600087803b15801561048a57600080fd5b505af115801561049e573d6000803e3d6000fd5b50505050505b50565b6000602082840312156104b957600080fd5b5051919050565b6000826104dd57634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156104f457600080fd5b81516001600160a01b038116811461050b57600080fd5b9392505050565b60006020828403121561052457600080fd5b8151801515811461050b57600080fd5b600081600019048311821515161561055c57634e487b7160e01b600052601160045260246000fd5b50029056fea2646970667358221220e5ac48da7671a457bfe6d1b9084b6726f24f67032f91e821aa30da22b10e7ac364736f6c634300080b0033222c3138a2e91563a83c8e980c2eff17e14fbdd7f5071b3e80e6ff62941601210000000000000000000000000000000000000000000000000000000061e0bd000000000000000000000000000000000000000000000000000000000061e20e80

Deployed Bytecode

0x6080604052600436106102ff5760003560e01c806353aeea1e11610190578063acb2ad6f116100dc578063d240663c11610095578063e6a6dcce1161006f578063e6a6dcce146109d2578063e8d2c8c1146109f2578063f3e4df0614610a12578063fa82e8c514610a3257600080fd5b8063d240663c14610955578063dd62ed3e14610975578063e674a0bd146109bf57600080fd5b8063acb2ad6f146108ad578063ad046ddf146108c2578063b7a8807c146108e2578063bd77ac2c146108f7578063be459f6214610917578063c5f956af1461093757600080fd5b8063788bff68116101495780638f02bb5b116101235780638f02bb5b1461082057806395d89b4114610840578063a8b089821461086f578063a9059cbb1461088d57600080fd5b8063788bff68146107c65780638d8474c8146107e45780638da5cb5b1461080257600080fd5b806353aeea1e146106d557806357f6b812146106f55780635bf8633a1461074a578063699ea5831461076857806370a082311461078657806372ded8f3146107a657600080fd5b8063313ce5671161024f578063472d35b9116102085780634b6753bc116101e25780634b6753bc1461066b5780634b89c41d14610680578063531bc097146106a0578063532b1ba8146106b557600080fd5b8063472d35b91461061657806347535d7b14610636578063479ba7ae1461064b57600080fd5b8063313ce5671461056557806332a7eb961461058c57806335faa416146105ac578063372500ab146105c15780634000aea0146105d657806342966c68146105f657600080fd5b80631c75f085116102bc57806328687cc71161029657806328687cc7146104e25780632bbf532a1461051b5780632eb4a7ab1461053b5780632f1c030d1461055057600080fd5b80631c75f085146104575780631e3c187f1461048957806323b872dd146104c257600080fd5b806306fdde0314610304578063095ea7b31461034e5780630a53669f1461037e57806312408c8e146103b957806313af40351461041657806318160ddd14610438575b600080fd5b34801561031057600080fd5b50610338604051806040016040528060088152602001673332b2b9973bba3360c11b81525081565b6040516103459190611e96565b60405180910390f35b34801561035a57600080fd5b5061036e610369366004611f00565b610a6b565b6040519015158152602001610345565b34801561038a57600080fd5b5061039e610399366004611f2c565b610a81565b60408051938452602084019290925290820152606001610345565b3480156103c557600080fd5b506103d96103d4366004611f50565b610ac1565b6040805197885260208801969096529315159486019490945290151560608501521515608084015260a083019190915260c082015260e001610345565b34801561042257600080fd5b50610436610431366004611f2c565b610b24565b005b34801561044457600080fd5b506003545b604051908152602001610345565b34801561046357600080fd5b50600e546001600160a01b03165b6040516001600160a01b039091168152602001610345565b34801561049557600080fd5b5061036e6104a4366004611f2c565b6001600160a01b031660009081526008602052604090205460ff1690565b3480156104ce57600080fd5b5061036e6104dd366004611f80565b610b5d565b3480156104ee57600080fd5b5061036e6104fd366004611f2c565b6001600160a01b031660009081526009602052604090205460ff1690565b34801561052757600080fd5b5061036e610536366004611f2c565b610bea565b34801561054757600080fd5b50600054610449565b34801561055c57600080fd5b50610436610c0b565b34801561057157600080fd5b5061057a601281565b60405160ff9091168152602001610345565b34801561059857600080fd5b5061036e6105a7366004611fc1565b610caf565b3480156105b857600080fd5b50610436610cf0565b3480156105cd57600080fd5b50610436610d33565b3480156105e257600080fd5b5061036e6105f1366004611fda565b610dc8565b34801561060257600080fd5b50610436610611366004611fc1565b610e94565b34801561062257600080fd5b50610436610631366004611f2c565b610f44565b34801561064257600080fd5b5061036e610f7d565b34801561065757600080fd5b50610449610666366004611f2c565b610f9c565b34801561067757600080fd5b50600254610449565b34801561068c57600080fd5b5061043661069b366004611fc1565b610fe8565b3480156106ac57600080fd5b50601454610449565b3480156106c157600080fd5b506104366106d0366004612063565b611004565b3480156106e157600080fd5b506104366106f0366004611fc1565b61118f565b34801561070157600080fd5b50610715610710366004611f2c565b611202565b604080519788526020880196909652948601939093526060850191909152608084015260a083015260c082015260e001610345565b34801561075657600080fd5b50600d546001600160a01b0316610471565b34801561077457600080fd5b506011546001600160a01b0316610471565b34801561079257600080fd5b506104496107a1366004611f2c565b6113d6565b3480156107b257600080fd5b506104366107c1366004612063565b6113f1565b3480156107d257600080fd5b506010546001600160a01b0316610471565b3480156107f057600080fd5b506012546001600160a01b0316610471565b34801561080e57600080fd5b50600a546001600160a01b0316610471565b34801561082c57600080fd5b5061043661083b366004611fc1565b6114cb565b34801561084c57600080fd5b50610338604051806040016040528060038152602001622baa2360e91b81525081565b34801561087b57600080fd5b50600c546001600160a01b0316610471565b34801561089957600080fd5b5061036e6108a8366004611f00565b6114f5565b3480156108b957600080fd5b50601354610449565b3480156108ce57600080fd5b506104496108dd366004611f2c565b611502565b3480156108ee57600080fd5b50600154610449565b34801561090357600080fd5b50610436610912366004611fc1565b611534565b34801561092357600080fd5b5061036e610932366004611fc1565b611580565b34801561094357600080fd5b50600f546001600160a01b0316610471565b34801561096157600080fd5b50610436610970366004612063565b6115c1565b34801561098157600080fd5b506104496109903660046120ee565b6001600160a01b0391821660009081526007602090815260408083209390941682526001909201909152205490565b6104366109cd3660046120ee565b6115df565b3480156109de57600080fd5b506104366109ed36600461212a565b61178f565b3480156109fe57600080fd5b50610436610a0d366004611fc1565b611820565b348015610a1e57600080fd5b50610449610a2d366004611fc1565b61184a565b348015610a3e57600080fd5b50610449610a4d366004611f2c565b6001600160a01b031660009081526007602052604090206003015490565b6000610a78338484611876565b90505b92915050565b6000806000610a8f846113d6565b6001600160a01b038516600090815260076020526040902060030154610ab486611502565b9250925092509193909250565b6000806000806000806000610ad560015490565b9650610ae060025490565b9550610aeb88610bea565b9450610af689610caf565b9350610b0189611580565b9250610b0d6000611202565b509b9e9a9d50989b50969950949794965050505050565b600a546001600160a01b03163314610b3b57600080fd5b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b038316600090815260076020908152604080832033845260010190915281205482811015610b9157600080fd5b6000198114610bd6576001600160a01b038516600090815260076020908152604080832033845260010190915281208054859290610bd090849061218b565b90915550505b610be18585856118e2565b95945050505050565b6001600160a01b031660009081526007602052604090206004015460ff1690565b306000610c1782610f9c565b90508015610cab57610c2d600160401b826121a2565b6001600160a01b03831660009081526007602052604081206002018054909190610c589084906121c1565b90915550610c67905081611b97565b816001600160a01b03167f1f89f96333d3133000ee447473151fa9606543368f02271c9d95ae14f13bcc6782604051610ca291815260200190565b60405180910390a25b5050565b600080610cbe61010084612218565b90506000610cce6101008561222c565b60009283526005602052604090922054600190921b9182169091149392505050565b4715610d3157600e546040516001600160a01b03909116904780156108fc02916000818181858888f19350505050158015610d2f573d6000803e3d6000fd5b505b565b610d3b610c0b565b6000610d4633610f9c565b90508015610d2f57610d5c600160401b826121a2565b3360009081526007602052604081206002018054909190610d7e9084906121c1565b90915550610d8f90503033836118e2565b5060405181815233907f1f89f96333d3133000ee447473151fa9606543368f02271c9d95ae14f13bcc679060200160405180910390a250565b600080610dd4866113d6565b9050610de13387876118e2565b50600081610dee886113d6565b610df8919061218b565b9050863b63ffffffff811615610e8657604051636be32e7360e01b81526001600160a01b03891690636be32e7390610e3a90339086908b908b90600401612240565b6020604051808303816000875af1158015610e59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e7d9190612288565b610e8657600080fd5b506001979650505050505050565b80610e9e336113d6565b1015610ea957600080fd5b8060006003016000828254610ebe919061218b565b90915550503360009081526007602052604081208054839290610ee290849061218b565b9091555050600454610ef490826121a2565b3360009081526007602052604081206002018054909190610f169084906122a5565b909155505060405181815260009033906000805160206124c88339815191529060200160405180910390a350565b600a546001600160a01b03163314610f5b57600080fd5b601280546001600160a01b0319166001600160a01b0392909216919091179055565b6000610f8860015490565b42118015610f97575060025442105b905090565b6001600160a01b038116600090815260076020526040812060020154600160401b90610fc7846113d6565b600454610fd491906121a2565b610fde91906122a5565b610a7b9190612218565b600a546001600160a01b03163314610fff57600080fd5b600255565b61100c610f7d565b61101557600080fd5b61101e84610bea565b61102757600080fd5b823561103281611580565b1561103c57600080fd5b6110a083838080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604051611085925089915088906020016122fa565b60405160208183030381529060405280519060200120611c05565b6110a957600080fd5b60006110b761010083612218565b905060006110c76101008461222c565b6000838152600660205260409081902080546001841b179055600d54815163a46a932f60e01b81526001600160a01b038b81166004830152928a0135602482015260608a0135604482015260808a0135606482015260a08a0135608482015260c08a013560a482015260e08a013560c48201526101008a013560e4820152929350169063a46a932f9061010401600060405180830381600087803b15801561116e57600080fd5b505af1158015611182573d6000803e3d6000fd5b5050505050505050505050565b336000908152600760205260409020600301548181106111ae57600080fd5b6000815b838110156111e1576111c38161184a565b6111cd908361232a565b9150806111d981612342565b9150506111b2565b506111eb81610e94565b505033600090815260076020526040902060030155565b600080600080600080600061121660035490565b600c54604080516318160ddd60e01b815290519299506001600160a01b03909116916318160ddd916004808201926020929091908290030181865afa158015611263573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611287919061235d565b600c5460408051630240bc6b60e21b8152905192985060009283926001600160a01b031691630902f1ac9160048083019260609291908290030181865afa1580156112d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fa9190612392565b50600c546001600160701b03928316945091169150600160a01b900460ff166113235780611325565b815b600c54909750600160a01b900460ff1661133f5781611341565b805b955061134c8a6113d6565b94506113578a610f9c565b600c546040516370a0823160e01b81526001600160a01b038d811660048301529296509116906370a0823190602401602060405180830381865afa1580156113a3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c7919061235d565b92505050919395979092949650565b6001600160a01b031660009081526007602052604090205490565b6113f9610f7d565b61140257600080fd5b61140b84610bea565b61141457600080fd5b8235602084013561142482610caf565b1561142e57600080fd5b6114778484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505060405161108592508a915089906020016122fa565b61148057600080fd5b600061148e61010084612218565b9050600061149e6101008561222c565b600083815260056020526040902080546001831b17905590506114c18884611cb5565b5050505050505050565b600a546001600160a01b031633146114e257600080fd5b60648111156114f057600080fd5b601355565b6000610a783384846118e2565b6001600160a01b03811660009081526007602052604081206003015461152990600161232a565b610a7b90600a6121a2565b6000811161154157600080fd5b600061154c306113d6565b90506115593330846118e2565b50600081611566306113d6565b611570919061218b565b905061157b81611b97565b505050565b60008061158f61010084612218565b9050600061159f6101008561222c565b60009283526006602052604090922054600190921b9182169091149392505050565b6115cd848484846113f1565b6115d984848484611004565b50505050565b60025442106115ed57600080fd5b6115f682610bea565b1561160057600080fd5b662386f26fc10000341461161357600080fd5b60006001600160a01b038216156116b757606461162f83611502565b61164090662386f26fc100006121a2565b61164a9190612218565b6040519091506001600160a01b0383169082156108fc029083906000818181858888f1935050505050816001600160a01b03167f4b8126d2c8cfe6526bd9f134921855f9c6076a52dd74535c1bf55d59a778edc8826040516116ae91815260200190565b60405180910390a25b60006116ca82662386f26fc1000061218b565b90506116de600e546001600160a01b031690565b6001600160a01b03166108fc829081150290604051600060405180830381858888f19350505050158015611716573d6000803e3d6000fd5b50600e546001600160a01b03166001600160a01b03167f4b8126d2c8cfe6526bd9f134921855f9c6076a52dd74535c1bf55d59a778edc88260405161175d91815260200190565b60405180910390a25050506001600160a01b03166000908152600760205260409020600401805460ff19166001179055565b600a546001600160a01b031633146117a657600080fd5b6001600160a01b0383166000818152600960209081526040808320805487151560ff199182168117909255600884529382902080548715159516851790558151908152918201929092527f855852ede06df792cbe12bbb8b292fd0d251a1dcfea1f072d5793f1930568ebf910160405180910390a2505050565b600a546001600160a01b0316331461183757600080fd5b606481111561184557600080fd5b601455565b60006004821061185957600080fd5b61186482600a6124bb565b610a7b90678ac7230489e800006121a2565b6001600160a01b0383811660008181526007602090815260408083209487168084526001909501825280832086905551858152919392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060019392505050565b6000816118ee856113d6565b10156118f957600080fd5b6001600160a01b0384166000908152600760205260408120805484929061192190849061218b565b909155505060045461193390836121a2565b6001600160a01b0385166000908152600760205260408120600201805490919061195e9084906122a5565b90915550600090506119708585611d6c565b611a3a576103e861198060135490565b61198a90856121a2565b6119949190612218565b30600081815260076020526040812080549394509192849291906119b990849061232a565b90915550506004546119cb90836121a2565b6001600160a01b038216600090815260076020526040812060020180549091906119f69084906121c1565b92505081905550806001600160a01b0316866001600160a01b03166000805160206124c883398151915284604051611a3091815260200190565b60405180910390a3505b6000611a46828561218b565b6001600160a01b038616600090815260076020526040812080549293508392909190611a7390849061232a565b9091555050600454611a8590826121a2565b6001600160a01b03861660009081526007602052604081206002018054909190611ab09084906121c1565b92505081905550846001600160a01b0316866001600160a01b03166000805160206124c883398151915283604051611aea91815260200190565b60405180910390a38115611b8b5760006064611b0560145490565b611b0f90856121a2565b611b199190612218565b9050611b29600160401b826121a2565b60076000611b3f6012546001600160a01b031690565b6001600160a01b03166001600160a01b031681526020019081526020016000206002016000828254611b7191906122a5565b90915550611b899050611b84828561218b565b611b97565b505b50600195945050505050565b8015610d2f57600354611bae600160401b836121a2565b611bb89190612218565b60048054600090611bca90849061232a565b90915550506040518181527f3ac0594a85a20354f9dc74f33728416d19ce00d04a406c108cc2dcf2cecea1349060200160405180910390a150565b600081815b8451811015611ca9576000858281518110611c2757611c276122e4565b60200260200101519050808311611c69576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250611c96565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b5080611ca181612342565b915050611c0a565b50600054149392505050565b8060006003016000828254611cca919061232a565b90915550506001600160a01b03821660009081526007602052604081208054839290611cf790849061232a565b9091555050600454611d0990826121a2565b6001600160a01b03831660009081526007602052604081206002018054909190611d349084906121c1565b90915550506040518181526001600160a01b038316906000906000805160206124c88339815191529060200160405180910390a35050565b6001600160a01b03821660009081526009602052604081205460ff1680611dab57506001600160a01b03821660009081526008602052604090205460ff165b80611dbe57506001600160a01b03831630145b80611dd157506001600160a01b03821630145b80611de957506012546001600160a01b038481169116145b80611e0157506012546001600160a01b038381169116145b80611e195750600f546001600160a01b038481169116145b80611e315750600f546001600160a01b038381169116145b80611e4957506010546001600160a01b038481169116145b80611e6157506010546001600160a01b038381169116145b80611e7957506011546001600160a01b038481169116145b80610a785750506011546001600160a01b03918216911614919050565b600060208083528351808285015260005b81811015611ec357858101830151858201604001528201611ea7565b81811115611ed5576000604083870101525b50601f01601f1916929092016040019392505050565b6001600160a01b0381168114610d2f57600080fd5b60008060408385031215611f1357600080fd5b8235611f1e81611eeb565b946020939093013593505050565b600060208284031215611f3e57600080fd5b8135611f4981611eeb565b9392505050565b60008060408385031215611f6357600080fd5b823591506020830135611f7581611eeb565b809150509250929050565b600080600060608486031215611f9557600080fd5b8335611fa081611eeb565b92506020840135611fb081611eeb565b929592945050506040919091013590565b600060208284031215611fd357600080fd5b5035919050565b60008060008060608587031215611ff057600080fd5b8435611ffb81611eeb565b935060208501359250604085013567ffffffffffffffff8082111561201f57600080fd5b818701915087601f83011261203357600080fd5b81358181111561204257600080fd5b88602082850101111561205457600080fd5b95989497505060200194505050565b600080600080610160858703121561207a57600080fd5b843561208581611eeb565b935061014085018681111561209957600080fd5b6020860193503567ffffffffffffffff808211156120b657600080fd5b818701915087601f8301126120ca57600080fd5b8135818111156120d957600080fd5b8860208260051b850101111561205457600080fd5b6000806040838503121561210157600080fd5b823561210c81611eeb565b91506020830135611f7581611eeb565b8015158114610d2f57600080fd5b60008060006060848603121561213f57600080fd5b833561214a81611eeb565b9250602084013561215a8161211c565b9150604084013561216a8161211c565b809150509250925092565b634e487b7160e01b600052601160045260246000fd5b60008282101561219d5761219d612175565b500390565b60008160001904831182151516156121bc576121bc612175565b500290565b600080821280156001600160ff1b03849003851316156121e3576121e3612175565b600160ff1b83900384128116156121fc576121fc612175565b50500190565b634e487b7160e01b600052601260045260246000fd5b60008261222757612227612202565b500490565b60008261223b5761223b612202565b500690565b6001600160a01b0385168152602081018490526060604082018190528101829052818360808301376000818301608090810191909152601f909201601f191601019392505050565b60006020828403121561229a57600080fd5b8151611f498161211c565b60008083128015600160ff1b8501841216156122c3576122c3612175565b6001600160ff1b03840183138116156122de576122de612175565b50500390565b634e487b7160e01b600052603260045260246000fd5b6bffffffffffffffffffffffff198360601b16815261012082601483013760006101349190910190815292915050565b6000821982111561233d5761233d612175565b500190565b600060001982141561235657612356612175565b5060010190565b60006020828403121561236f57600080fd5b5051919050565b80516001600160701b038116811461238d57600080fd5b919050565b6000806000606084860312156123a757600080fd5b6123b084612376565b92506123be60208501612376565b9150604084015163ffffffff8116811461216a57600080fd5b600181815b808511156124125781600019048211156123f8576123f8612175565b8085161561240557918102915b93841c93908002906123dc565b509250929050565b60008261242957506001610a7b565b8161243657506000610a7b565b816001811461244c576002811461245657612472565b6001915050610a7b565b60ff84111561246757612467612175565b50506001821b610a7b565b5060208310610133831016604e8410600b8410161715612495575081810a610a7b565b61249f83836123d7565b80600019048211156124b3576124b3612175565b029392505050565b6000610a78838361241a56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220773c3bc5c1b52ba29c8531e661ad2f452c8d85e666bc98dcb001458ff10a7c9664736f6c634300080b0033

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

222c3138a2e91563a83c8e980c2eff17e14fbdd7f5071b3e80e6ff62941601210000000000000000000000000000000000000000000000000000000061e0bd000000000000000000000000000000000000000000000000000000000061e20e80

-----Decoded View---------------
Arg [0] : _merkleRoot (bytes32): 0x222c3138a2e91563a83c8e980c2eff17e14fbdd7f5071b3e80e6ff6294160121
Arg [1] : _openingTime (uint256): 1642118400
Arg [2] : _stakingRewardsStart (uint256): 1642204800

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 222c3138a2e91563a83c8e980c2eff17e14fbdd7f5071b3e80e6ff6294160121
Arg [1] : 0000000000000000000000000000000000000000000000000000000061e0bd00
Arg [2] : 0000000000000000000000000000000000000000000000000000000061e20e80


Deployed Bytecode Sourcemap

783:15667:6:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1272:40;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1272:40:6;;;;;;;;;;;;:::i;:::-;;;;;;;;8539:130;;;;;;;;;;-1:-1:-1;8539:130:6;;;;;:::i;:::-;;:::i;:::-;;;1237:14:8;;1230:22;1212:41;;1200:2;1185:18;8539:130:6;1072:187:8;12634:188:6;;;;;;;;;;-1:-1:-1;12634:188:6;;;;;:::i;:::-;;:::i;:::-;;;;1718:25:8;;;1774:2;1759:18;;1752:34;;;;1802:18;;;1795:34;1706:2;1691:18;12634:188:6;1516:319:8;12825:437:6;;;;;;;;;;-1:-1:-1;12825:437:6;;;;;:::i;:::-;;:::i;:::-;;;;2457:25:8;;;2513:2;2498:18;;2491:34;;;;2568:14;;2561:22;2541:18;;;2534:50;;;;2627:14;;2620:22;2615:2;2600:18;;2593:50;2687:14;2680:22;2674:3;2659:19;;2652:51;2734:3;2719:19;;2712:35;;;;2778:3;2763:19;;2756:35;2444:3;2429:19;12825:437:6;2160:637:8;3901:81:6;;;;;;;;;;-1:-1:-1;3901:81:6;;;;;:::i;:::-;;:::i;:::-;;11720:84;;;;;;;;;;-1:-1:-1;11784:16:6;;11720:84;;;2948:25:8;;;2936:2;2921:18;11720:84:6;2802:177:8;9597:103:6;;;;;;;;;;-1:-1:-1;9685:9:6;;-1:-1:-1;;;;;9685:9:6;9597:103;;;-1:-1:-1;;;;;3164:32:8;;;3146:51;;3134:2;3119:18;9597:103:6;2984:219:8;10493:111:6;;;;;;;;;;-1:-1:-1;10493:111:6;;;;;:::i;:::-;-1:-1:-1;;;;;10574:26:6;10557:4;10574:26;;;:16;:26;;;;;;;;;10493:111;8672:314;;;;;;;;;;-1:-1:-1;8672:314:6;;;;;:::i;:::-;;:::i;10375:115::-;;;;;;;;;;-1:-1:-1;10375:115:6;;;;;:::i;:::-;-1:-1:-1;;;;;10458:28:6;10441:4;10458:28;;;:18;:28;;;;;;;;;10375:115;10995:103;;;;;;;;;;-1:-1:-1;10995:103:6;;;;;:::i;:::-;;:::i;10607:82::-;;;;;;;;;;-1:-1:-1;10650:7:6;10670:15;10607:82;;7840:266;;;;;;;;;;;;;:::i;1355:35::-;;;;;;;;;;;;1388:2;1355:35;;;;;4023:4:8;4011:17;;;3993:36;;3981:2;3966:18;1355:35:6;3851:184:8;11101:306:6;;;;;;;;;;-1:-1:-1;11101:306:6;;;;;:::i;:::-;;:::i;5076:119::-;;;;;;;;;;;;;:::i;7542:295::-;;;;;;;;;;;;;:::i;8989:425::-;;;;;;;;;;-1:-1:-1;8989:425:6;;;;;:::i;:::-;;:::i;8109:302::-;;;;;;;;;;-1:-1:-1;8109:302:6;;;;;:::i;:::-;;:::i;3985:101::-;;;;;;;;;;-1:-1:-1;3985:101:6;;;;;:::i;:::-;;:::i;10866:126::-;;;;;;;;;;;;;:::i;11914:189::-;;;;;;;;;;-1:-1:-1;11914:189:6;;;;;:::i;:::-;;:::i;10779:84::-;;;;;;;;;;-1:-1:-1;10843:16:6;;10779:84;;4089:105;;;;;;;;;;-1:-1:-1;4089:105:6;;;;;:::i;:::-;;:::i;10276:96::-;;;;;;;;;;-1:-1:-1;10346:22:6;;10276:96;;6950:589;;;;;;;;;;-1:-1:-1;6950:589:6;;;;;:::i;:::-;;:::i;5198:332::-;;;;;;;;;;-1:-1:-1;5198:332:6;;;;;:::i;:::-;;:::i;13265:547::-;;;;;;;;;;-1:-1:-1;13265:547:6;;;;;:::i;:::-;;:::i;:::-;;;;6240:25:8;;;6296:2;6281:18;;6274:34;;;;6324:18;;;6317:34;;;;6382:2;6367:18;;6360:34;;;;6425:3;6410:19;;6403:35;6469:3;6454:19;;6447:35;6513:3;6498:19;;6491:35;6227:3;6212:19;13265:547:6;5925:607:8;9508:86:6;;;;;;;;;;-1:-1:-1;9581:8:6;;-1:-1:-1;;;;;9581:8:6;9508:86;;9909:110;;;;;;;;;;-1:-1:-1;9993:21:6;;-1:-1:-1;;;;;9993:21:6;9909:110;;11807:104;;;;;;;;;;-1:-1:-1;11807:104:6;;;;;:::i;:::-;;:::i;6397:550::-;;;;;;;;;;-1:-1:-1;6397:550:6;;;;;:::i;:::-;;:::i;9800:106::-;;;;;;;;;;-1:-1:-1;9882:19:6;;-1:-1:-1;;;;;9882:19:6;9800:106;;10022:89;;;;;;;;;;-1:-1:-1;10092:15:6;;-1:-1:-1;;;;;10092:15:6;10022:89;;10114:72;;;;;;;;;;-1:-1:-1;10172:10:6;;-1:-1:-1;;;;;10172:10:6;10114:72;;4197:147;;;;;;;;;;-1:-1:-1;4197:147:6;;;;;:::i;:::-;;:::i;1315:37::-;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;1315:37:6;;;;;9419:86;;;;;;;;;;-1:-1:-1;9491:9:6;;-1:-1:-1;;;;;9491:9:6;9419:86;;8414:122;;;;;;;;;;-1:-1:-1;8414:122:6;;;;;:::i;:::-;;:::i;10189:84::-;;;;;;;;;;-1:-1:-1;10253:16:6;;10189:84;;12358:114;;;;;;;;;;-1:-1:-1;12358:114:6;;;;;:::i;:::-;;:::i;10692:84::-;;;;;;;;;;-1:-1:-1;10756:16:6;;10692:84;;4798:275;;;;;;;;;;-1:-1:-1;4798:275:6;;;;;:::i;:::-;;:::i;11410:306::-;;;;;;;;;;-1:-1:-1;11410:306:6;;;;;:::i;:::-;;:::i;9703:94::-;;;;;;;;;;-1:-1:-1;9779:13:6;;-1:-1:-1;;;;;9779:13:6;9703:94;;6103:290;;;;;;;;;;-1:-1:-1;6103:290:6;;;;;:::i;:::-;;:::i;12106:134::-;;;;;;;;;;-1:-1:-1;12106:134:6;;;;;:::i;:::-;-1:-1:-1;;;;;12199:17:6;;;12179:7;12199:17;;;:10;:17;;;;;;;;:37;;;;;;:27;;;;:37;;;;;;12106:134;5533:566;;;;;;:::i;:::-;;:::i;4517:277::-;;;;;;;;;;-1:-1:-1;4517:277:6;;;;;:::i;:::-;;:::i;4347:167::-;;;;;;;;;;-1:-1:-1;4347:167:6;;;;;:::i;:::-;;:::i;12475:156::-;;;;;;;;;;-1:-1:-1;12475:156:6;;;;;:::i;:::-;;:::i;12243:112::-;;;;;;;;;;-1:-1:-1;12243:112:6;;;;;:::i;:::-;-1:-1:-1;;;;;12321:17:6;12301:7;12321:17;;;:10;:17;;;;;:30;;;;12243:112;8539:130;8609:4;8626:39;8635:10;8647:8;8657:7;8626:8;:39::i;:::-;8619:46;;8539:130;;;;;:::o;12634:188::-;12696:15;12713:13;12728:15;12757:16;12767:5;12757:9;:16::i;:::-;-1:-1:-1;;;;;12321:17:6;;12301:7;12321:17;;;:10;:17;;;;;:30;;;12796:21;12811:5;12796:14;:21::i;:::-;12749:69;;;;;;12634:188;;;;;:::o;12825:437::-;12901:16;12919:17;12938:13;12953:15;12970;12987:19;13008:18;13043:13;10756:16;;;10692:84;13043:13;13032:24;;13072:13;10843:16;;;10779:84;13072:13;13060:25;;13100:17;13111:5;13100:10;:17::i;:::-;13089:28;;13134:20;13147:6;13134:12;:20::i;:::-;13121:33;;13171:20;13184:6;13171:12;:20::i;:::-;13158:33;;13234:24;13253:3;13234:10;:24::i;:::-;-1:-1:-1;12825:437:6;;;;-1:-1:-1;12825:437:6;;-1:-1:-1;12825:437:6;;-1:-1:-1;12825:437:6;;13195:63;;-1:-1:-1;;;;;12825:437:6:o;3901:81::-;10172:10;;-1:-1:-1;;;;;10172:10:6;2607;:21;2599:30;;;;;;3959:10:::1;:19:::0;;-1:-1:-1;;;;;;3959:19:6::1;-1:-1:-1::0;;;;;3959:19:6;;;::::1;::::0;;;::::1;::::0;;3901:81::o;8672:314::-;-1:-1:-1;;;;;12199:17:6;;8757:4;12199:17;;;:10;:17;;;;;;;;8805:10;12199:37;;:27;;:37;;;;;;8842:7;8828:10;:21;;8820:30;;;;;;-1:-1:-1;;8858:10:6;:22;8854:88;;-1:-1:-1;;;;;8887:17:6;;:4;:17;;;:10;:17;;;;;;;;8915:10;8887:39;;:27;;:39;;;;;:50;;8930:7;;8887:4;:50;;8930:7;;8887:50;:::i;:::-;;;;-1:-1:-1;;8854:88:6;8952:30;8962:5;8969:3;8974:7;8952:9;:30::i;:::-;8945:37;8672:314;-1:-1:-1;;;;;8672:314:6:o;10995:103::-;-1:-1:-1;;;;;11068:17:6;11051:4;11068:17;;;:10;:17;;;;;:26;;;;;;10995:103::o;7840:266::-;7899:4;7875:13;7927:16;7899:4;7927:9;:16::i;:::-;7908:35;-1:-1:-1;7951:12:6;;7947:156;;8011:23;-1:-1:-1;;;8011:8:6;:23;:::i;:::-;-1:-1:-1;;;;;7970:17:6;;:4;:17;;;:10;:17;;;;;:30;;:65;;:30;;:4;:65;;;;;:::i;:::-;;;;-1:-1:-1;8040:19:6;;-1:-1:-1;8050:8:6;8040:9;:19::i;:::-;8082:5;-1:-1:-1;;;;;8069:29:6;;8089:8;8069:29;;;;2948:25:8;;2936:2;2921:18;;2802:177;8069:29:6;;;;;;;;7947:156;7871:235;;7840:266::o;11101:306::-;11160:4;;11198:12;11207:3;11198:6;:12;:::i;:::-;11170:40;-1:-1:-1;11214:24:6;11241:12;11250:3;11241:6;:12;:::i;:::-;11257:20;11280:40;;;:21;:40;;;;;;;11341:1;:21;;;11374:20;;;:29;;;;11101:306;-1:-1:-1;;;11101:306:6:o;5076:119::-;5110:21;:25;5106:86;;9685:9;;5142:45;;-1:-1:-1;;;;;9685:9:6;;;;5165:21;5142:45;;;;;;;;;5165:21;9685:9;5142:45;;;;;;;;;;;;;;;;;;;;;5106:86;5076:119::o;7542:295::-;7579:14;:12;:14::i;:::-;7597:16;7616:21;7626:10;7616:9;:21::i;:::-;7597:40;-1:-1:-1;7645:12:6;;7641:193;;7710:23;-1:-1:-1;;;7710:8:6;:23;:::i;:::-;7675:10;7664:4;:22;;;:10;:22;;;;;:35;;:70;;:35;;:4;:70;;;;;:::i;:::-;;;;-1:-1:-1;7739:46:6;;-1:-1:-1;7757:4:6;7764:10;7776:8;7739:9;:46::i;:::-;-1:-1:-1;7795:34:6;;2948:25:8;;;7808:10:6;;7795:34;;2936:2:8;2921:18;7795:34:6;;;;;;;7575:262;7542:295::o;8989:425::-;9084:4;9094:22;9119:14;9129:3;9119:9;:14::i;:::-;9094:39;;9137:35;9147:10;9159:3;9164:7;9137:9;:35::i;:::-;;9176:23;9219:14;9202;9212:3;9202:9;:14::i;:::-;:31;;;;:::i;:::-;9176:57;-1:-1:-1;9276:16:6;;9303:9;;;;9299:97;;9327:63;;-1:-1:-1;;;9327:63:6;;-1:-1:-1;;;;;9327:27:6;;;;;:63;;9355:10;;9367:15;;9384:5;;;;9327:63;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9319:72;;;;;;-1:-1:-1;9406:4:6;;8989:425;-1:-1:-1;;;;;;;8989:425:6:o;8109:302::-;8184:7;8159:21;8169:10;8159:9;:21::i;:::-;:32;;8151:41;;;;;;8216:7;8196:4;:16;;;:27;;;;;;;:::i;:::-;;;;-1:-1:-1;;8238:10:6;8227:4;:22;;;:10;:22;;;;;:41;;8261:7;;8227:4;:41;;8261:7;;8227:41;:::i;:::-;;;;-1:-1:-1;;8328:26:6;;8318:36;;:7;:36;:::i;:::-;8283:10;8272:4;:22;;;:10;:22;;;;;:35;;:83;;:35;;:4;:83;;;;;:::i;:::-;;;;-1:-1:-1;;8364:43:6;;2948:25:8;;;8393:3:6;;8373:10;;-1:-1:-1;;;;;;;;;;;8364:43:6;2936:2:8;2921:18;8364:43:6;;;;;;;8109:302;:::o;3985:101::-;10172:10;;-1:-1:-1;;;;;10172:10:6;2607;:21;2599:30;;;;;;4053:15:::1;:29:::0;;-1:-1:-1;;;;;;4053:29:6::1;-1:-1:-1::0;;;;;4053:29:6;;;::::1;::::0;;;::::1;::::0;;3985:101::o;10866:126::-;10905:4;10940:13;10756:16;;;10692:84;10940:13;10922:15;:31;:66;;;;-1:-1:-1;10843:16:6;;10957:15;:31;10922:66;10915:73;;10866:126;:::o;11914:189::-;-1:-1:-1;;;;;12053:17:6;;11969:7;12053:17;;;:10;:17;;;;;:30;;;-1:-1:-1;;;840:5:6;12033:16;12064:5;12033:9;:16::i;:::-;12004:26;;:45;;;;:::i;:::-;11997:86;;;;:::i;:::-;11989:110;;;;:::i;4089:105::-;10172:10;;-1:-1:-1;;;;;10172:10:6;2607;:21;2599:30;;;;;;4159:16:::1;:31:::0;4089:105::o;6950:589::-;7059:8;:6;:8::i;:::-;7051:17;;;;;;7080:20;7091:8;7080:10;:20::i;:::-;7072:29;;;;;;7122:8;;7143:20;7122:8;7143:12;:20::i;:::-;7142:21;7134:30;;;;;;7176:61;7184:6;;7176:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;7202:33:6;;;;-1:-1:-1;7219:8:6;;-1:-1:-1;7229:5:6;;7202:33;;;:::i;:::-;;;;;;;;;;;;;7192:44;;;;;;7176:7;:61::i;:::-;7168:70;;;;;;7242:25;7270:12;7279:3;7270:6;:12;:::i;:::-;7242:40;-1:-1:-1;7286:24:6;7313:12;7322:3;7313:6;:12;:::i;:::-;7372:4;:40;;;:21;:40;;;;;;;;;7416:1;:21;;7372:66;7329:109;;7442:8;;:93;;-1:-1:-1;;;7442:93:6;;-1:-1:-1;;;;;11247:32:8;;;7492:1:6;7442:93;;11229:51:8;7466:8:6;;;;11296:18:8;;;11289:34;7476:8:6;;;;11339:18:8;;;11332:34;7486:8:6;;;;11382:18:8;;;11375:34;7496:8:6;;;;11425:19:8;;;11418:35;7506:8:6;;;;11469:19:8;;;11462:35;7516:8:6;;;;11513:19:8;;;11506:35;7526:8:6;;;;11557:19:8;;;11550:35;7416:21:6;;-1:-1:-1;7442:8:6;;:13;;11201:19:8;;7442:93:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7047:492;;;6950:589;;;;:::o;5198:332::-;5290:10;5253:21;12321:17;;;:10;:17;;;;;:30;;;5313:24;;;5305:33;;;;;;5342:18;5385:13;5368:89;5404:8;5400:1;:12;5368:89;;;5438:14;5450:1;5438:11;:14::i;:::-;5424:28;;;;:::i;:::-;;-1:-1:-1;5414:3:6;;;;:::i;:::-;;;;5368:89;;;;5460:16;5465:10;5460:4;:16::i;:::-;-1:-1:-1;;5491:10:6;5480:4;:22;;;:10;:22;;;;;:35;;:46;5198:332::o;13265:547::-;13321:19;13342:21;13365:19;13386:18;13406:19;13427;13448:21;13489:13;11784:16;;;11720:84;13489:13;13522:9;;:23;;;-1:-1:-1;;;13522:23:6;;;;13475:27;;-1:-1:-1;;;;;;13522:9:6;;;;:21;;:23;;;;;;;;;;;;;;;:9;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13584:9;;:23;;;-1:-1:-1;;;13584:23:6;;;;13506:39;;-1:-1:-1;13550:13:6;;;;-1:-1:-1;;;;;13584:9:6;;:21;;:23;;;;;;;;;;;;;;:9;:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;13625:10:6;;-1:-1:-1;;;;;13549:58:6;;;;-1:-1:-1;13549:58:6;;;-1:-1:-1;;;;13625:10:6;;;;:26;;13646:5;13625:26;;;13638:5;13625:26;13668:10;;13611:40;;-1:-1:-1;;;;13668:10:6;;;;:26;;13689:5;13668:26;;;13681:5;13668:26;13655:39;;13712:16;13722:5;13712:9;:16::i;:::-;13698:30;;13746:16;13756:5;13746:9;:16::i;:::-;13782:9;;:26;;-1:-1:-1;;;13782:26:6;;-1:-1:-1;;;;;3164:32:8;;;13782:26:6;;;3146:51:8;13732:30:6;;-1:-1:-1;13782:9:6;;;:19;;3119:18:8;;13782:26:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;13766:42;;13471:341;;13265:547;;;;;;;;;:::o;11807:104::-;-1:-1:-1;;;;;11882:17:6;11862:7;11882:17;;;:10;:17;;;;;:25;;11807:104::o;6397:550::-;6506:8;:6;:8::i;:::-;6498:17;;;;;;6527:20;6538:8;6527:10;:20::i;:::-;6519:29;;;;;;6569:8;;;6599;;;6620:20;6569:8;6620:12;:20::i;:::-;6619:21;6611:30;;;;;;6653:61;6661:6;;6653:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6679:33:6;;;;-1:-1:-1;6696:8:6;;-1:-1:-1;6706:5:6;;6679:33;;;:::i;6653:61::-;6645:70;;;;;;6719:25;6747:12;6756:3;6747:6;:12;:::i;:::-;6719:40;-1:-1:-1;6763:24:6;6790:12;6799:3;6790:6;:12;:::i;:::-;6849:4;:40;;;:21;:40;;;;;;;6893:1;:21;;6849:66;6806:109;;6763:39;-1:-1:-1;6919:24:6;6925:8;6935:7;6919:5;:24::i;:::-;6494:453;;;;6397:550;;;;:::o;4197:147::-;10172:10;;-1:-1:-1;;;;;10172:10:6;2607;:21;2599:30;;;;;;4291:3:::1;4275:12;:19;;4267:28;;;::::0;::::1;;4309:16;:31:::0;4197:147::o;8414:122::-;8480:4;8497:35;8507:10;8519:3;8524:7;8497:9;:35::i;12358:114::-;-1:-1:-1;;;;;12321:17:6;;12418:7;12321:17;;;:10;:17;;;;;:30;;;12444:23;;12466:1;12444:23;:::i;:::-;12438:30;;:2;:30;:::i;4798:275::-;4864:1;4854:7;:11;4846:20;;;;;;4870:22;4895:24;4913:4;4895:9;:24::i;:::-;4870:49;;4923:45;4933:10;4953:4;4960:7;4923:9;:45::i;:::-;;4972:23;5025:14;4998:24;5016:4;4998:9;:24::i;:::-;:41;;;;:::i;:::-;4972:67;;5043:26;5053:15;5043:9;:26::i;:::-;4842:231;;4798:275;:::o;11410:306::-;11469:4;;11507:12;11516:3;11507:6;:12;:::i;:::-;11479:40;-1:-1:-1;11523:24:6;11550:12;11559:3;11550:6;:12;:::i;:::-;11566:20;11589:40;;;:21;:40;;;;;;;11650:1;:21;;;11683:20;;;:29;;;;11410:306;-1:-1:-1;;;11410:306:6:o;6103:290::-;6319:33;6328:8;6338:5;6345:6;;6319:8;:33::i;:::-;6356;6365:8;6375:5;6382:6;;6356:8;:33::i;:::-;6103:290;;;;:::o;5533:566::-;10843:16;;5623:15;:31;5615:40;;;;;;5668:20;5679:8;5668:10;:20::i;:::-;5667:21;5659:30;;;;;;1258:10;5701:9;:24;5693:33;;;;;;5730:15;-1:-1:-1;;;;;5757:25:6;;;5753:169;;5841:3;5813:25;5828:9;5813:14;:25::i;:::-;5799:39;;1258:10;5799:39;:::i;:::-;:45;;;;:::i;:::-;5850:23;;5789:55;;-1:-1:-1;;;;;;5850:14:6;;;:23;;;;;5789:55;;5850:23;;;;5789:55;5850:14;:23;;;;;;;5849:24;5898:9;-1:-1:-1;;;;;5883:34:6;;5909:7;5883:34;;;;2948:25:8;;2936:2;2921:18;;2802:177;5883:34:6;;;;;;;;5753:169;5925:18;5946:21;5960:7;1258:10;5946:21;:::i;:::-;5925:42;;5971:13;9685:9;;-1:-1:-1;;;;;9685:9:6;;9597:103;5971:13;-1:-1:-1;;;;;5971:22:6;:34;5994:10;5971:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9685:9:6;;-1:-1:-1;;;;;9685:9:6;-1:-1:-1;;;;;6014:41:6;;6044:10;6014:41;;;;2948:25:8;;2936:2;2921:18;;2802:177;6014:41:6;;;;;;;;-1:-1:-1;;;;;;;;6059:20:6;:4;:20;;;:10;:20;;;;;:29;;:36;;-1:-1:-1;;6059:36:6;6091:4;6059:36;;;5533:566::o;4517:277::-;10172:10;;-1:-1:-1;;;;;10172:10:6;2607;:21;2599:30;;;;;;-1:-1:-1;;;;;4627:28:6;::::1;:4;:28:::0;;;:18:::1;:28;::::0;;;;;;;:47;;;::::1;;-1:-1:-1::0;;4627:47:6;;::::1;::::0;::::1;::::0;;;4678:16:::1;:26:::0;;;;;;:43;;;::::1;;::::0;::::1;::::0;::::1;::::0;;4730:60;;12868:41:8;;;12925:18;;;12918:50;;;;4730:60:6::1;::::0;12841:18:8;4730:60:6::1;;;;;;;4517:277:::0;;;:::o;4347:167::-;10172:10;;-1:-1:-1;;;;;10172:10:6;2607;:21;2599:30;;;;;;4459:3:::1;4437:18;:25;;4429:34;;;::::0;::::1;;4467:22;:43:::0;4347:167::o;12475:156::-;12540:7;12577:1;12561:13;:17;12553:26;;;;;;12610:17;12614:13;12610:2;:17;:::i;:::-;12590:37;;1202:4;12590:37;:::i;14092:208::-;-1:-1:-1;;;;;14189:18:6;;;14179:4;14189:18;;;:10;:18;;;;;;;;:38;;;;;;:28;;;;:38;;;;;:48;;;14246:35;2948:25:8;;;14179:4:6;;14189:38;:18;14246:35;;2921:18:8;14246:35:6;;;;;;;-1:-1:-1;14292:4:6;14092:208;;;;;:::o;14304:1015::-;14386:4;14424:7;14404:16;14414:5;14404:9;:16::i;:::-;:27;;14396:36;;;;;;-1:-1:-1;;;;;14436:17:6;;:4;:17;;;:10;:17;;;;;:36;;14465:7;;14436:4;:36;;14465:7;;14436:36;:::i;:::-;;;;-1:-1:-1;;14527:26:6;;14517:36;;:7;:36;:::i;:::-;-1:-1:-1;;;;;14476:17:6;;:4;:17;;;:10;:17;;;;;:30;;:78;;:30;;:4;:78;;;;;:::i;:::-;;;;-1:-1:-1;14558:12:6;;-1:-1:-1;14583:30:6;14602:5;14609:3;14583:18;:30::i;:::-;14578:288;;950:4;14637:13;10253:16;;;10189:84;14637:13;14627:23;;:7;:23;:::i;:::-;:44;;;;:::i;:::-;14700:4;14676:13;14710:17;;;:10;:17;;;;;:33;;14620:51;;-1:-1:-1;14700:4:6;;14620:51;;14710:17;14676:13;14710:33;;14620:51;;14710:33;:::i;:::-;;;;-1:-1:-1;;14796:26:6;;14789:33;;:4;:33;:::i;:::-;-1:-1:-1;;;;;14748:17:6;;:4;:17;;;:10;:17;;;;;:30;;:75;;:30;;:4;:75;;;;;:::i;:::-;;;;;;;;14849:5;-1:-1:-1;;;;;14833:28:6;14842:5;-1:-1:-1;;;;;14833:28:6;-1:-1:-1;;;;;;;;;;;14856:4:6;14833:28;;;;2948:25:8;;2936:2;2921:18;;2802:177;14833:28:6;;;;;;;;14615:251;14578:288;14869:20;14892:14;14902:4;14892:7;:14;:::i;:::-;-1:-1:-1;;;;;14910:15:6;;:4;:15;;;:10;:15;;;;;:39;;14869:37;;-1:-1:-1;14869:37:6;;14910:15;;:4;:39;;14869:37;;14910:39;:::i;:::-;;;;-1:-1:-1;;15007:26:6;;14992:41;;:12;:41;:::i;:::-;-1:-1:-1;;;;;14953:15:6;;:4;:15;;;:10;:15;;;;;:28;;:81;;:28;;:4;:81;;;;;:::i;:::-;;;;;;;;15059:3;-1:-1:-1;;;;;15043:34:6;15052:5;-1:-1:-1;;;;;15043:34:6;-1:-1:-1;;;;;;;;;;;15064:12:6;15043:34;;;;2948:25:8;;2936:2;2921:18;;2802:177;15043:34:6;;;;;;;;15085:8;;15081:220;;15100:26;15158:3;15136:19;10346:22;;;10276:96;15136:19;15129:26;;:4;:26;:::i;:::-;:32;;;;:::i;:::-;15100:61;-1:-1:-1;15221:33:6;-1:-1:-1;;;15100:61:6;15221:33;:::i;:::-;15166:10;:4;15177:19;10092:15;;-1:-1:-1;;;;;10092:15:6;;10022:89;15177:19;-1:-1:-1;;;;;15166:31:6;-1:-1:-1;;;;;15166:31:6;;;;;;;;;;;;:44;;;:89;;;;;;;:::i;:::-;;;;-1:-1:-1;15260:36:6;;-1:-1:-1;15270:25:6;15277:18;15270:4;:25;:::i;:::-;15260:9;:36::i;:::-;15095:206;15081:220;-1:-1:-1;15311:4:6;;14304:1015;-1:-1:-1;;;;;14304:1015:6:o;15322:172::-;15375:11;;15371:120;;11784:16;;15423:22;-1:-1:-1;;;15423:7:6;:22;:::i;:::-;:38;;;;:::i;:::-;15393:26;:68;;:4;;:68;;;;;:::i;:::-;;;;-1:-1:-1;;15471:15:6;;2948:25:8;;;15471:15:6;;2936:2:8;2921:18;15471:15:6;;;;;;;15322:172;:::o;15979:469::-;16059:4;16093:5;16059:4;16102:303;16126:6;:13;16122:1;:17;16102:303;;;16151:21;16175:6;16182:1;16175:9;;;;;;;;:::i;:::-;;;;;;;16151:33;;16210:13;16193;:30;16189:212;;16257:46;;;;;;14510:19:8;;;14545:12;;;14538:28;;;14582:12;;16257:46:6;;;;;;;;;;;;16247:57;;;;;;16231:73;;16189:212;;;16348:46;;;;;;14510:19:8;;;14545:12;;;14538:28;;;14582:12;;16348:46:6;;;;;;;;;;;;16338:57;;;;;;16322:73;;16189:212;-1:-1:-1;16141:3:6;;;;:::i;:::-;;;;16102:303;;;-1:-1:-1;10650:7:6;10670:15;16415:29;;15979:469;-1:-1:-1;;;15979:469:6:o;13816:272::-;13899:7;13879:4;:16;;;:27;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;13910:20:6;;:4;:20;;;:10;:20;;;;;:39;;13942:7;;13910:4;:39;;13942:7;;13910:39;:::i;:::-;;;;-1:-1:-1;;14007:26:6;;13997:36;;:7;:36;:::i;:::-;-1:-1:-1;;;;;13953:20:6;;:4;:20;;;:10;:20;;;;;:33;;:81;;:33;;:4;:81;;;;;:::i;:::-;;;;-1:-1:-1;;14043:41:6;;2948:25:8;;;-1:-1:-1;;;;;14043:41:6;;;14060:3;;-1:-1:-1;;;;;;;;;;;14043:41:6;2936:2:8;2921:18;14043:41:6;;;;;;;13816:272;;:::o;15498:477::-;-1:-1:-1;;;;;10458:28:6;;15577:4;10458:28;;;:18;:28;;;;;;;;15594:48;;;-1:-1:-1;;;;;;10574:26:6;;10557:4;10574:26;;;:16;:26;;;;;;;;15622:20;15594:77;;;-1:-1:-1;;;;;;15649:22:6;;15666:4;15649:22;15594:77;:101;;;-1:-1:-1;;;;;;15675:20:6;;15690:4;15675:20;15594:101;:136;;;-1:-1:-1;10092:15:6;;-1:-1:-1;;;;;15702:28:6;;;10092:15;;15702:28;15594:136;:166;;;-1:-1:-1;10092:15:6;;-1:-1:-1;;;;;15734:26:6;;;10092:15;;15734:26;15594:166;:199;;;-1:-1:-1;9779:13:6;;-1:-1:-1;;;;;15767:26:6;;;9779:13;;15767:26;15594:199;:227;;;-1:-1:-1;9779:13:6;;-1:-1:-1;;;;;15797:24:6;;;9779:13;;15797:24;15594:227;:266;;;-1:-1:-1;9882:19:6;;-1:-1:-1;;;;;15828:32:6;;;9882:19;;15828:32;15594:266;:300;;;-1:-1:-1;9882:19:6;;-1:-1:-1;;;;;15864:30:6;;;9882:19;;15864:30;15594:300;:341;;;-1:-1:-1;9993:21:6;;-1:-1:-1;;;;;15901:34:6;;;9993:21;;15901:34;15594:341;:377;;;-1:-1:-1;;9993:21:6;;-1:-1:-1;;;;;15939:32:6;;;9993:21;;15939:32;;15498:477;-1:-1:-1;15498:477:6:o;14:597:8:-;126:4;155:2;184;173:9;166:21;216:6;210:13;259:6;254:2;243:9;239:18;232:34;284:1;294:140;308:6;305:1;302:13;294:140;;;403:14;;;399:23;;393:30;369:17;;;388:2;365:26;358:66;323:10;;294:140;;;452:6;449:1;446:13;443:91;;;522:1;517:2;508:6;497:9;493:22;489:31;482:42;443:91;-1:-1:-1;595:2:8;574:15;-1:-1:-1;;570:29:8;555:45;;;;602:2;551:54;;14:597;-1:-1:-1;;;14:597:8:o;616:131::-;-1:-1:-1;;;;;691:31:8;;681:42;;671:70;;737:1;734;727:12;752:315;820:6;828;881:2;869:9;860:7;856:23;852:32;849:52;;;897:1;894;887:12;849:52;936:9;923:23;955:31;980:5;955:31;:::i;:::-;1005:5;1057:2;1042:18;;;;1029:32;;-1:-1:-1;;;752:315:8:o;1264:247::-;1323:6;1376:2;1364:9;1355:7;1351:23;1347:32;1344:52;;;1392:1;1389;1382:12;1344:52;1431:9;1418:23;1450:31;1475:5;1450:31;:::i;:::-;1500:5;1264:247;-1:-1:-1;;;1264:247:8:o;1840:315::-;1908:6;1916;1969:2;1957:9;1948:7;1944:23;1940:32;1937:52;;;1985:1;1982;1975:12;1937:52;2021:9;2008:23;1998:33;;2081:2;2070:9;2066:18;2053:32;2094:31;2119:5;2094:31;:::i;:::-;2144:5;2134:15;;;1840:315;;;;;:::o;3208:456::-;3285:6;3293;3301;3354:2;3342:9;3333:7;3329:23;3325:32;3322:52;;;3370:1;3367;3360:12;3322:52;3409:9;3396:23;3428:31;3453:5;3428:31;:::i;:::-;3478:5;-1:-1:-1;3535:2:8;3520:18;;3507:32;3548:33;3507:32;3548:33;:::i;:::-;3208:456;;3600:7;;-1:-1:-1;;;3654:2:8;3639:18;;;;3626:32;;3208:456::o;4040:180::-;4099:6;4152:2;4140:9;4131:7;4127:23;4123:32;4120:52;;;4168:1;4165;4158:12;4120:52;-1:-1:-1;4191:23:8;;4040:180;-1:-1:-1;4040:180:8:o;4225:794::-;4313:6;4321;4329;4337;4390:2;4378:9;4369:7;4365:23;4361:32;4358:52;;;4406:1;4403;4396:12;4358:52;4445:9;4432:23;4464:31;4489:5;4464:31;:::i;:::-;4514:5;-1:-1:-1;4566:2:8;4551:18;;4538:32;;-1:-1:-1;4621:2:8;4606:18;;4593:32;4644:18;4674:14;;;4671:34;;;4701:1;4698;4691:12;4671:34;4739:6;4728:9;4724:22;4714:32;;4784:7;4777:4;4773:2;4769:13;4765:27;4755:55;;4806:1;4803;4796:12;4755:55;4846:2;4833:16;4872:2;4864:6;4861:14;4858:34;;;4888:1;4885;4878:12;4858:34;4933:7;4928:2;4919:6;4915:2;4911:15;4907:24;4904:37;4901:57;;;4954:1;4951;4944:12;4901:57;4225:794;;;;-1:-1:-1;;4985:2:8;4977:11;;-1:-1:-1;;;4225:794:8:o;5024:896::-;5153:6;5161;5169;5177;5230:3;5218:9;5209:7;5205:23;5201:33;5198:53;;;5247:1;5244;5237:12;5198:53;5286:9;5273:23;5305:31;5330:5;5305:31;:::i;:::-;5355:5;-1:-1:-1;5394:3:8;5379:19;;5410:15;;;5407:35;;;5438:1;5435;5428:12;5407:35;5476:2;5461:18;;;-1:-1:-1;5502:16:8;5537:18;5567:14;;;5564:34;;;5594:1;5591;5584:12;5564:34;5632:6;5621:9;5617:22;5607:32;;5677:7;5670:4;5666:2;5662:13;5658:27;5648:55;;5699:1;5696;5689:12;5648:55;5739:2;5726:16;5765:2;5757:6;5754:14;5751:34;;;5781:1;5778;5771:12;5751:34;5834:7;5829:2;5819:6;5816:1;5812:14;5808:2;5804:23;5800:32;5797:45;5794:65;;;5855:1;5852;5845:12;6745:388;6813:6;6821;6874:2;6862:9;6853:7;6849:23;6845:32;6842:52;;;6890:1;6887;6880:12;6842:52;6929:9;6916:23;6948:31;6973:5;6948:31;:::i;:::-;6998:5;-1:-1:-1;7055:2:8;7040:18;;7027:32;7068:33;7027:32;7068:33;:::i;7539:118::-;7625:5;7618:13;7611:21;7604:5;7601:32;7591:60;;7647:1;7644;7637:12;7662:517;7733:6;7741;7749;7802:2;7790:9;7781:7;7777:23;7773:32;7770:52;;;7818:1;7815;7808:12;7770:52;7857:9;7844:23;7876:31;7901:5;7876:31;:::i;:::-;7926:5;-1:-1:-1;7983:2:8;7968:18;;7955:32;7996:30;7955:32;7996:30;:::i;:::-;8045:7;-1:-1:-1;8104:2:8;8089:18;;8076:32;8117:30;8076:32;8117:30;:::i;:::-;8166:7;8156:17;;;7662:517;;;;;:::o;8184:127::-;8245:10;8240:3;8236:20;8233:1;8226:31;8276:4;8273:1;8266:15;8300:4;8297:1;8290:15;8316:125;8356:4;8384:1;8381;8378:8;8375:34;;;8389:18;;:::i;:::-;-1:-1:-1;8426:9:8;;8316:125::o;8446:168::-;8486:7;8552:1;8548;8544:6;8540:14;8537:1;8534:21;8529:1;8522:9;8515:17;8511:45;8508:71;;;8559:18;;:::i;:::-;-1:-1:-1;8599:9:8;;8446:168::o;8619:265::-;8658:3;8686:9;;;8711:10;;-1:-1:-1;;;;;8730:27:8;;;8723:35;;8707:52;8704:78;;;8762:18;;:::i;:::-;-1:-1:-1;;;8809:19:8;;;8802:27;;8794:36;;8791:62;;;8833:18;;:::i;:::-;-1:-1:-1;;8869:9:8;;8619:265::o;8889:127::-;8950:10;8945:3;8941:20;8938:1;8931:31;8981:4;8978:1;8971:15;9005:4;9002:1;8995:15;9021:120;9061:1;9087;9077:35;;9092:18;;:::i;:::-;-1:-1:-1;9126:9:8;;9021:120::o;9146:112::-;9178:1;9204;9194:35;;9209:18;;:::i;:::-;-1:-1:-1;9243:9:8;;9146:112::o;9263:559::-;-1:-1:-1;;;;;9476:32:8;;9458:51;;9540:2;9525:18;;9518:34;;;9588:2;9583;9568:18;;9561:30;;;9607:18;;9600:34;;;9627:6;9677;9671:3;9656:19;;9643:49;9742:1;9712:22;;;9736:3;9708:32;;;9701:43;;;;9805:2;9784:15;;;-1:-1:-1;;9780:29:8;9765:45;9761:55;;9263:559;-1:-1:-1;;;9263:559:8:o;9827:245::-;9894:6;9947:2;9935:9;9926:7;9922:23;9918:32;9915:52;;;9963:1;9960;9953:12;9915:52;9995:9;9989:16;10014:28;10036:5;10014:28;:::i;10077:267::-;10116:4;10145:9;;;10170:10;;-1:-1:-1;;;10189:19:8;;10182:27;;10166:44;10163:70;;;10213:18;;:::i;:::-;-1:-1:-1;;;;;10260:27:8;;10253:35;;10245:44;;10242:70;;;10292:18;;:::i;:::-;-1:-1:-1;;10329:9:8;;10077:267::o;10349:127::-;10410:10;10405:3;10401:20;10398:1;10391:31;10441:4;10438:1;10431:15;10465:4;10462:1;10455:15;10481:400;10723:26;10719:31;10710:6;10706:2;10702:15;10698:53;10693:3;10686:66;10796:6;10788;10783:2;10778:3;10774:12;10761:42;10668:3;10831;10822:13;;;;10844;;;10822;10481:400;-1:-1:-1;;10481:400:8:o;11596:128::-;11636:3;11667:1;11663:6;11660:1;11657:13;11654:39;;;11673:18;;:::i;:::-;-1:-1:-1;11709:9:8;;11596:128::o;11729:135::-;11768:3;-1:-1:-1;;11789:17:8;;11786:43;;;11809:18;;:::i;:::-;-1:-1:-1;11856:1:8;11845:13;;11729:135::o;11869:184::-;11939:6;11992:2;11980:9;11971:7;11967:23;11963:32;11960:52;;;12008:1;12005;11998:12;11960:52;-1:-1:-1;12031:16:8;;11869:184;-1:-1:-1;11869:184:8:o;12058:188::-;12137:13;;-1:-1:-1;;;;;12179:42:8;;12169:53;;12159:81;;12236:1;12233;12226:12;12159:81;12058:188;;;:::o;12251:450::-;12338:6;12346;12354;12407:2;12395:9;12386:7;12382:23;12378:32;12375:52;;;12423:1;12420;12413:12;12375:52;12446:40;12476:9;12446:40;:::i;:::-;12436:50;;12505:49;12550:2;12539:9;12535:18;12505:49;:::i;:::-;12495:59;;12597:2;12586:9;12582:18;12576:25;12641:10;12634:5;12630:22;12623:5;12620:33;12610:61;;12667:1;12664;12657:12;12979:422;13068:1;13111:5;13068:1;13125:270;13146:7;13136:8;13133:21;13125:270;;;13205:4;13201:1;13197:6;13193:17;13187:4;13184:27;13181:53;;;13214:18;;:::i;:::-;13264:7;13254:8;13250:22;13247:55;;;13284:16;;;;13247:55;13363:22;;;;13323:15;;;;13125:270;;;13129:3;12979:422;;;;;:::o;13406:806::-;13455:5;13485:8;13475:80;;-1:-1:-1;13526:1:8;13540:5;;13475:80;13574:4;13564:76;;-1:-1:-1;13611:1:8;13625:5;;13564:76;13656:4;13674:1;13669:59;;;;13742:1;13737:130;;;;13649:218;;13669:59;13699:1;13690:10;;13713:5;;;13737:130;13774:3;13764:8;13761:17;13758:43;;;13781:18;;:::i;:::-;-1:-1:-1;;13837:1:8;13823:16;;13852:5;;13649:218;;13951:2;13941:8;13938:16;13932:3;13926:4;13923:13;13919:36;13913:2;13903:8;13900:16;13895:2;13889:4;13886:12;13882:35;13879:77;13876:159;;;-1:-1:-1;13988:19:8;;;14020:5;;13876:159;14067:34;14092:8;14086:4;14067:34;:::i;:::-;14137:6;14133:1;14129:6;14125:19;14116:7;14113:32;14110:58;;;14148:18;;:::i;:::-;14186:20;;13406:806;-1:-1:-1;;;13406:806:8:o;14217:131::-;14277:5;14306:36;14333:8;14327:4;14306:36;:::i

Swarm Source

ipfs://e5ac48da7671a457bfe6d1b9084b6726f24f67032f91e821aa30da22b10e7ac3
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.