ETH Price: $3,439.10 (+3.28%)
Gas: 9.28 Gwei

Automatons xNFT (AUTO)
 

Overview

TokenID

6481

Total Transfers

-

Market

Onchain Market Cap

$0.00

Circulating Supply Market Cap

-
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:
Automatons

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 3 : Automatons.sol
//
// Automatons xNFT (AUTO)
// The first collection to use the xNFT hybrid standard.
// Created by the CellMates team.
//
// - 4096 total supply
// - 3 LPs created on deployment:
//  - 256 AUTO + 4 ETH v2 liquidity
//  - 256 AUTO + 0 wCELL v3 single sided LP
//  - 1280 AUTO + 0 ETH v3 single sided LP
// - 1792 AUTO free airdrop claim for CELL/wCELL holders
// - 512 AUTO @ 0.1 ETH public mint from contract price
// - sellable on both Uniswap and Opensea
// - fully on-chain artwork based on cellular automata
//
// https://auto.cellmates.io
// https://discord.com/invite/cellmates
// https://twitter.com/CellMatesERC
//

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "./xNFT.sol";
import "./Metadata.sol";

interface RouterV2 {
	function factory() external pure returns (address);
	function addLiquidityETH(address, uint256, uint256, uint256, address, uint256) external payable returns (uint256, uint256, uint256);
}

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

interface PairV2 {
	function sync() external;
}

interface RouterV3 {
	function factory() external view returns (address);
	function positionManager() external view returns (address);
	function WETH9() external view returns (address);
}

interface FactoryV3 {
	function createPool(address _tokenA, address _tokenB, uint24 _fee) external returns (address);
}

interface PoolV3 {
	function slot0() external view returns (uint160, int24, uint16, uint16, uint16, uint8, bool);
	function initialize(uint160 _sqrtPriceX96) external;
}

interface PositionManager {
	struct MintParams {
		address token0;
		address token1;
		uint24 fee;
		int24 tickLower;
		int24 tickUpper;
		uint256 amount0Desired;
		uint256 amount1Desired;
		uint256 amount0Min;
		uint256 amount1Min;
		address recipient;
		uint256 deadline;
	}
	struct CollectParams {
		uint256 tokenId;
		address recipient;
		uint128 amount0Max;
		uint128 amount1Max;
	}
	function mint(MintParams calldata) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
	function collect(CollectParams calldata) external payable returns (uint256 amount0, uint256 amount1);
}

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

interface IWETH is ERC20 {
	function withdraw(uint256) external;
}


contract Team {

	RouterV3 constant private ROUTER = RouterV3(0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45);
	ERC20 constant private WCELL = ERC20(0x18E5F92103d1B34623738Ee79214B1659f2eE109);

	struct Share {
		address payable user;
		uint256 shares;
	}
	Share[] public shares;
	uint256 public totalShares;
	ERC20 immutable public token;


	constructor() {
		token = ERC20(msg.sender);
		_addShare(0xFaDED72464D6e76e37300B467673b36ECc4d2ccF, 4);
		_addShare(0xEC513e5959dBB02F314fc2F30041FCA2685119F3, 1);
	}

	receive() external payable {}

	function withdrawETH() public {
		uint256 _balance = address(this).balance;
		if (_balance > 0) {
			for (uint256 i = 0; i < shares.length; i++) {
				Share memory _share = shares[i];
				!_share.user.send(_balance * _share.shares / totalShares);
			}
		}
	}

	function withdrawToken(ERC20 _token) public {
		IWETH _weth = IWETH(ROUTER.WETH9());
		if (address(_token) == address(_weth)) {
			_weth.withdraw(_weth.balanceOf(address(this)));
			withdrawETH();
		} else {
			uint256 _balance = _token.balanceOf(address(this));
			if (_balance > 0) {
				if (_token == token) {
					_token.transfer(shares[0].user, _balance);
				} else {
					for (uint256 i = 0; i < shares.length; i++) {
						Share memory _share = shares[i];
						_token.transfer(_share.user, _balance * _share.shares / totalShares);
					}
				}
			}
		}
	}

	function withdrawWETH() public {
		withdrawToken(ERC20(ROUTER.WETH9()));
	}

	function withdrawFees() external {
		withdrawWETH();
		withdrawToken(WCELL);
		withdrawToken(token);
	}


	function _addShare(address _user, uint256 _shares) internal {
		shares.push(Share(payable(_user), _shares));
		totalShares += _shares;
	}
}


contract Automatons is xNFT {

	uint256 constant private TOTAL_SUPPLY = 4096;
	uint256 constant private V2_LIQUIDITY_TOKENS = 256;
	uint256 constant private V3_WCELL_LIQUIDITY_TOKENS = 256;
	uint256 constant private V3_WETH_LIQUIDITY_TOKENS = 1280;
	RouterV2 constant private ROUTER_V2 = RouterV2(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
	RouterV3 constant private ROUTER_V3 = RouterV3(0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45);
	PoolV3 constant private WCELL_POOL_V3 = PoolV3(0x685c401540C103631A0ba7f14A3d16Ae3cB4E50B);
	address constant private WCELL = 0x18E5F92103d1B34623738Ee79214B1659f2eE109;
	uint256 immutable private ETH_WCELL_RATIO;
	uint256 immutable private LP_INITIAL_ETH;
	uint256 constant private LP_UPPER_ETH = 1e8 ether;
	int24 constant private MIN_TICK = -887272;
	int24 constant private MAX_TICK = -MIN_TICK;
	uint160 constant private MIN_SQRT_RATIO = 4295128739;
	uint160 constant private MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;
	uint128 constant private UINT128_MAX = type(uint128).max;
	bytes32 constant private MERKLE_ROOT = 0x3f856c8d1611023aaa9915c692b07293eea0d4dd7c26df3914d5bfbd430ce84c;

	Metadata public metadata;
	Team immutable public team;
	PoolV3 immutable public wcellPoolV3;
	PoolV3 immutable public wethPoolV3;
	uint256 public wcellPositionId;
	uint256 public wethPositionId;
	PairV2 public pairV2;
	bytes32 public salt;
	mapping(address => bool) public hasClaimedAirdrop;
	uint256 public mintable = 512;
	uint256 constant public mintCost = 0.1 ether;

	event Claim(address indexed account, uint256 tokens);


	constructor() xNFT(address(this), TOTAL_SUPPLY) payable {
		require(msg.value > 0);
		info.owner = 0xFaDED72464D6e76e37300B467673b36ECc4d2ccF;
		team = new Team();
		metadata = new Metadata();
		LP_INITIAL_ETH = totalSupply * msg.value / V2_LIQUIDITY_TOKENS;
		address _this = address(this);
		address _weth = ROUTER_V3.WETH9();
		(uint160 _initialSqrtPrice, ) = _getPriceAndTickFromValues(_weth < _this, TOTAL_SUPPLY, LP_INITIAL_ETH);
		wethPoolV3 = PoolV3(FactoryV3(ROUTER_V3.factory()).createPool(_this, _weth, 10000));
		wethPoolV3.initialize(_initialSqrtPrice);
		(uint256 _wcellSqrtPrice, , , , , , ) = WCELL_POOL_V3.slot0();
		ETH_WCELL_RATIO = (_wcellSqrtPrice * _wcellSqrtPrice * 1e18) >> 192;
		(_initialSqrtPrice, ) = _getPriceAndTickFromValues(WCELL < _this, TOTAL_SUPPLY, 1e18 * LP_INITIAL_ETH / ETH_WCELL_RATIO);
		wcellPoolV3 = PoolV3(FactoryV3(ROUTER_V3.factory()).createPool(_this, WCELL, 10000));
		wcellPoolV3.initialize(_initialSqrtPrice);
		salt = keccak256(abi.encodePacked("Salt:", blockhash(block.number - 1)));
	}

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


	function initialize() external _withoutEventEmits {
		require(address(pairV2) == address(0x0));
		address _this = address(this);
		address _weth = ROUTER_V3.WETH9();
		_approveERC20(_this, address(ROUTER_V2), V2_LIQUIDITY_TOKENS);
		pairV2 = PairV2(FactoryV2(ROUTER_V2.factory()).createPair(_weth, _this));
		ROUTER_V2.addLiquidityETH{value:_this.balance}(_this, V2_LIQUIDITY_TOKENS, 0, 0, owner(), block.timestamp);
		PositionManager _pm = PositionManager(ROUTER_V3.positionManager());
		_approveERC20(_this, address(_pm), V3_WCELL_LIQUIDITY_TOKENS + V3_WETH_LIQUIDITY_TOKENS);
		bool _weth0 = _weth < _this;
		( , int24 _minTick) = _getPriceAndTickFromValues(_weth0, TOTAL_SUPPLY, LP_INITIAL_ETH);
		( , int24 _maxTick) = _getPriceAndTickFromValues(_weth0, TOTAL_SUPPLY, LP_UPPER_ETH);
		(wethPositionId, , , ) = _pm.mint(PositionManager.MintParams({
			token0: _weth0 ? _weth : _this,
			token1: !_weth0 ? _weth : _this,
			fee: 10000,
			tickLower: _weth0 ? _maxTick : _minTick,
			tickUpper: !_weth0 ? _maxTick : _minTick,
			amount0Desired: _weth0 ? 0 : V3_WETH_LIQUIDITY_TOKENS,
			amount1Desired: !_weth0 ? 0 : V3_WETH_LIQUIDITY_TOKENS,
			amount0Min: 0,
			amount1Min: 0,
			recipient: _this,
			deadline: block.timestamp
		}));
		_weth0 = WCELL < _this;
		( , _minTick) = _getPriceAndTickFromValues(_weth0, TOTAL_SUPPLY, 1e18 * LP_INITIAL_ETH / ETH_WCELL_RATIO);
		( , _maxTick) = _getPriceAndTickFromValues(_weth0, TOTAL_SUPPLY, 1e18 * LP_UPPER_ETH / ETH_WCELL_RATIO);
		(wcellPositionId, , , ) = _pm.mint(PositionManager.MintParams({
			token0: _weth0 ? WCELL : _this,
			token1: !_weth0 ? WCELL : _this,
			fee: 10000,
			tickLower: _weth0 ? _maxTick : _minTick,
			tickUpper: !_weth0 ? _maxTick : _minTick,
			amount0Desired: _weth0 ? 0 : V3_WCELL_LIQUIDITY_TOKENS,
			amount1Desired: !_weth0 ? 0 : V3_WCELL_LIQUIDITY_TOKENS,
			amount0Min: 0,
			amount1Min: 0,
			recipient: _this,
			deadline: block.timestamp
		}));
	}

	function collectAllTradingFees() external {
		collectTradingFees(UINT128_MAX, UINT128_MAX, UINT128_MAX, UINT128_MAX);
	}

	function collectTradingFees(uint128 _wethAmount0Max, uint128 _wethAmount1Max, uint128 _wcellAmount0Max, uint128 _wcellAmount1Max) public {
		PositionManager _pm = PositionManager(ROUTER_V3.positionManager());
		_pm.collect(PositionManager.CollectParams({
			tokenId: wethPositionId,
			recipient: address(team),
			amount0Max: _wethAmount0Max,
			amount1Max: _wethAmount1Max
		}));
		_pm.collect(PositionManager.CollectParams({
			tokenId: wcellPositionId,
			recipient: address(team),
			amount0Max: _wcellAmount0Max,
			amount1Max: _wcellAmount1Max
		}));
		team.withdrawFees();
	}

	function claim(address _account, uint256 _tokens, bytes32[] calldata _proof) external {
		require(!hasClaimedAirdrop[_account]);
		require(_verify(_proof, keccak256(abi.encodePacked(_account, _tokens))));
		hasClaimedAirdrop[_account] = true;
		_transferERC20(address(this), _account, _tokens);
		emit Claim(_account, _tokens);
	}

	function mint(uint256 _tokens) external payable {
		require(_tokens <= mintable);
		uint256 _cost = _tokens * mintCost;
		require(msg.value >= _cost);
		mintable -= _tokens;
		_transferERC20(address(this), msg.sender, _tokens);
		payable(team).transfer(_cost);
		if (msg.value > _cost) {
			payable(msg.sender).transfer(msg.value - _cost);
		}
	}


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

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

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


	function _initialize() internal override _withoutEventEmits {
		super._initialize();
	}


	function _getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
		unchecked {
			uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
			require(absTick <= uint256(int256(MAX_TICK)), 'T');

			uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;
			if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
			if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
			if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
			if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
			if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
			if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
			if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
			if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
			if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
			if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
			if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
			if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
			if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
			if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
			if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
			if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
			if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
			if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
			if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;

			if (tick > 0) ratio = type(uint256).max / ratio;

			sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
		}
	}

	function _getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
		unchecked {
			require(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO, 'R');
			uint256 ratio = uint256(sqrtPriceX96) << 32;

			uint256 r = ratio;
			uint256 msb = 0;

			assembly {
				let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
				msb := or(msb, f)
				r := shr(f, r)
			}
			assembly {
				let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
				msb := or(msb, f)
				r := shr(f, r)
			}
			assembly {
				let f := shl(5, gt(r, 0xFFFFFFFF))
				msb := or(msb, f)
				r := shr(f, r)
			}
			assembly {
				let f := shl(4, gt(r, 0xFFFF))
				msb := or(msb, f)
				r := shr(f, r)
			}
			assembly {
				let f := shl(3, gt(r, 0xFF))
				msb := or(msb, f)
				r := shr(f, r)
			}
			assembly {
				let f := shl(2, gt(r, 0xF))
				msb := or(msb, f)
				r := shr(f, r)
			}
			assembly {
				let f := shl(1, gt(r, 0x3))
				msb := or(msb, f)
				r := shr(f, r)
			}
			assembly {
				let f := gt(r, 0x1)
				msb := or(msb, f)
			}

			if (msb >= 128) r = ratio >> (msb - 127);
			else r = ratio << (127 - msb);

			int256 log_2 = (int256(msb) - 128) << 64;

			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(63, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(62, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(61, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(60, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(59, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(58, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(57, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(56, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(55, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(54, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(53, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(52, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(51, f))
				r := shr(f, r)
			}
			assembly {
				r := shr(127, mul(r, r))
				let f := shr(128, r)
				log_2 := or(log_2, shl(50, f))
			}

			int256 log_sqrt10001 = log_2 * 255738958999603826347141;

			int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
			int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);

			tick = tickLow == tickHi ? tickLow : _getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
		}
	}

	function _sqrt(uint256 _n) internal pure returns (uint256 result) {
		unchecked {
			uint256 _tmp = (_n + 1) / 2;
			result = _n;
			while (_tmp < result) {
				result = _tmp;
				_tmp = (_n / _tmp + _tmp) / 2;
			}
		}
	}

	function _getPriceAndTickFromValues(bool _weth0, uint256 _tokens, uint256 _weth) internal pure returns (uint160 price, int24 tick) {
		uint160 _tmpPrice = uint160(_sqrt(2**192 / (!_weth0 ? _tokens : _weth) * (_weth0 ? _tokens : _weth)));
		tick = _getTickAtSqrtRatio(_tmpPrice);
		tick = tick - (tick % 200);
		price = _getSqrtRatioAtTick(tick);
	}

	function _verify(bytes32[] memory _proof, bytes32 _leaf) internal pure 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 == MERKLE_ROOT;
	}
}


contract Deploy {

	Automatons immutable public automatons;
	address constant private weth = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

	constructor() payable {
		automatons = new Automatons{ value: msg.value, salt: _findSaltForWETH0() }();
		automatons.initialize();
	}

	function _findSaltForWETH0() internal view returns (bytes32) {
		bytes32 _codehash = keccak256(type(Automatons).creationCode);
		uint256 _salt = 0;
		address _predicted;
		do {
			_salt++;
			_predicted = address(uint160(uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), bytes32(_salt), _codehash)))));
		} while (_predicted < weth);
		return bytes32(_salt);
	}
}

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

interface AUTO {
	function salt() external view returns (bytes32);
}

contract Metadata {
	
	string public name = "Automatons xNFT";
	string public symbol = "AUTO";

	uint256 constant private TARGET_BIT_COUNT = 13;
	string constant private TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

	struct Size {
		uint248 size;
		uint8 chance;
	}
	Size[] private sizes;

	struct Color {
		bytes3 backgroundColor;
		bytes3 foregroundColor;
		uint16 chance;
		string name;
	}
	Color[] private colors;

	struct Reflection {
		uint8 chance;
		string name;
	}
	Reflection[] private reflections;

	AUTO immutable public automatons;


	constructor() {
		automatons = AUTO(msg.sender);

		// sizes
		sizes.push(Size(16, 20));
		sizes.push(Size(32, 200));
		sizes.push(Size(48, 120));
		sizes.push(Size(64, 50));
		sizes.push(Size(96, 10));
		sizes.push(Size(128, 1));
		
		// colors
		colors.push(Color(0xffffff, 0x000000, 3200, "Clean White"));
		colors.push(Color(0x000000, 0xffffff, 800, "Deep Black"));
		colors.push(Color(0x179629, 0x15491f, 100, "Slimy Green"));
		colors.push(Color(0xc9a91c, 0x5f5120, 75, "Pacific Blue"));
		colors.push(Color(0x009fff, 0x144d79, 55, "Orange Peel"));
		colors.push(Color(0x3bb5cf, 0x235763, 35, "Old Gold"));
		colors.push(Color(0x908070, 0x463f38, 25, "Slate Gray"));
		colors.push(Color(0xac8fe6, 0x53466d, 15, "Charm Pink"));
		colors.push(Color(0x2b2ca6, 0x191d52, 10, "Metallic Red"));
		colors.push(Color(0xa95178, 0x522b3d, 5, "Royal Purple"));

		// reflections
		reflections.push(Reflection(40, "None"));
		reflections.push(Reflection(20, "Rotation"));
		reflections.push(Reflection(10, "Single"));
		reflections.push(Reflection(5, "Double"));
	}

	function tokenURI(uint256 _tokenId) external view returns (string memory) {
		unchecked {
			( , , uint256 _size, uint256 _colorIndex, uint256 _reflectionIndex) = getTokenInfo(_tokenId);
			string memory _json = string(abi.encodePacked('{"name":"AUTO #', _uint2str(_tokenId), '","description":"The first collection to use the xNFT hybrid standard. Created by the CellMates team.",'));
			_json = string(abi.encodePacked(_json, '"image":"', svgURI(_tokenId), '","attributes":['));
			_json = string(abi.encodePacked(_json, '{"trait_type":"Size","value":"', _uint2str(_size), '"},'));
			_json = string(abi.encodePacked(_json, '{"trait_type":"Color","value":"', colors[_colorIndex].name, '"},'));
			_json = string(abi.encodePacked(_json, '{"trait_type":"Reflection","value":"', reflections[_reflectionIndex].name, '"}'));
			_json = string(abi.encodePacked(_json, ']}'));
			return string(abi.encodePacked('data:application/json;base64,', _encode(bytes(_json))));
		}
	}

	function svgURI(uint256 _tokenId) public view returns (string memory) {
		return string(abi.encodePacked('data:image/svg+xml;base64,', _encode(bytes(getSVG(_tokenId)))));
	}
	
	function bmpURI(uint256 _tokenId) public view returns (string memory) {
		return string(abi.encodePacked('data:image/bmp;base64,', _encode(getBMP(_tokenId))));
	}

	function getSVG(uint256 _tokenId) public view returns (string memory) {
		( , , , uint256 _colorIndex, ) = getTokenInfo(_tokenId);
		return 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%"><defs><style type="text/css">svg{image-rendering:optimizeSpeed;image-rendering:-moz-crisp-edges;image-rendering:-o-crisp-edges;image-rendering:-webkit-optimize-contrast;image-rendering:pixelated;image-rendering:optimize-contrast;-ms-interpolation-mode:nearest-neighbor;background-color:', _col2str(colors[_colorIndex].backgroundColor), ';background-image:url(', bmpURI(_tokenId), ');background-repeat:no-repeat;background-size:contain;background-position:50% 50%;}</style></defs></svg>'));
	}
	
	function getBMP(uint256 _tokenId) public view returns (bytes memory) {
		(bytes32 _seed, uint32 _rule, uint256 _size, uint256 _colorIndex, uint256 _reflectionIndex) = getTokenInfo(_tokenId);
		return _getBMP(_makePalette(colors[_colorIndex].backgroundColor, colors[_colorIndex].foregroundColor), _convertToColors(_generate(_seed, _rule, _size, _reflectionIndex)), _size + 2 * _getPadding(_size));
	}
	
	function getTokenInfo(uint256 _tokenId) public view returns (bytes32 seed, uint32 rule, uint256 size, uint256 colorIndex, uint256 reflectionIndex) {
		unchecked {
			seed = keccak256(abi.encodePacked("Seed:", _tokenId, automatons.salt()));
			uint256[32] memory _bitIndexes;
			for (uint256 i = 0; i < _bitIndexes.length; i++) {
				_bitIndexes[i] = i;
			}
			for (uint256 i = 0; i < TARGET_BIT_COUNT; i++) {
				uint256 _index = i + uint256(keccak256(abi.encodePacked("Shuffle:", i, seed))) % (_bitIndexes.length - i);
				uint256 tmp = _bitIndexes[_index];
				_bitIndexes[_index] = _bitIndexes[i];
				_bitIndexes[i] = tmp;
			}
			for (uint256 i = 0; i < TARGET_BIT_COUNT; i++) {
				rule |= uint32(1 << _bitIndexes[i]);
			}
			size = _sampleSize(seed);
			colorIndex = _sampleColor(seed);
			reflectionIndex = _sampleReflection(seed);
		}
	}


	function _sampleSize(bytes32 _seed) internal view returns (uint256 size) {
		unchecked {
			uint256 _total = 0;
			for (uint256 i = 0; i < sizes.length; i++) {
				_total += sizes[i].chance;
			}
			uint256 _target = uint256(keccak256(abi.encodePacked("Size:", _seed))) % _total;
			_total = 0;
			for (uint256 i = 0; i < sizes.length; i++) {
				_total += sizes[i].chance;
				if (_target < _total) {
					return sizes[i].size;
				}
			}
		}
	}

	function _sampleColor(bytes32 _seed) internal view returns (uint256 colorIndex) {
		unchecked {
			uint256 _total = 0;
			for (uint256 i = 0; i < colors.length; i++) {
				_total += colors[i].chance;
			}
			uint256 _target = uint256(keccak256(abi.encodePacked("Color:", _seed))) % _total;
			_total = 0;
			for (uint256 i = 0; i < colors.length; i++) {
				_total += colors[i].chance;
				if (_target < _total) {
					return i;
				}
			}
		}
	}

	function _sampleReflection(bytes32 _seed) internal view returns (uint256 reflectionIndex) {
		unchecked {
			uint256 _total = 0;
			for (uint256 i = 0; i < reflections.length; i++) {
				_total += reflections[i].chance;
			}
			uint256 _target = uint256(keccak256(abi.encodePacked("Reflection:", _seed))) % _total;
			_total = 0;
			for (uint256 i = 0; i < reflections.length; i++) {
				_total += reflections[i].chance;
				if (_target < _total) {
					return i;
				}
			}
		}
	}

	function _getPadding(uint256 _size) internal pure returns (uint256) {
		return _size / 8;
	}
	
	function _generate(bytes32 _seed, uint32 _rule, uint256 _size, uint256 _reflectionIndex) internal pure returns (uint8[][] memory state) {
		unchecked {
			uint256 _randomness = uint256(keccak256(abi.encodePacked("State:", _seed)));
			uint256 _xSize = _reflectionIndex == 0 ? _size : _size / 2;
			uint256 _ySize = _reflectionIndex == 3 ? _size / 2 : _size;
			uint256[] memory _rows = new uint256[](_ySize);
			for (uint256 y = 0; y < _ySize; y++) {
				if (y == 0) {
					_rows[y] = _randomness & ((1 << _xSize) - 1);
				} else {
					uint256 _row = 0;
					uint256 _lastRow = _rows[y - 1];
					_lastRow |= _lastRow << _xSize;
					_lastRow <<= 2;
					_lastRow |= (_lastRow >> _xSize) & 3;
					for (uint256 x = 0; x < _xSize; x++) {
						uint8 _config = uint8(_lastRow >> x) & 0x1f;
						_row |= uint256((_rule >> _config) & 1) << x;
					}
					_rows[y] = _row;
				}
			}
			uint256 _padding = _getPadding(_size);
			state = new uint8[][](_size + 2 * _padding);
			for (uint256 y = 0; y < state.length; y++) {
				state[y] = new uint8[](_size + 2 * _padding);
				if (y >= _padding && y < _size + _padding) {
					for (uint256 x = _padding; x < state[y].length - _padding; x++) {
						uint256 _xPos = x - _padding;
						uint256 _yPos = y - _padding;
						if (_reflectionIndex != 0 && x >= _xSize + _padding) {
							_xPos = _size + _padding - x - 1;
							if (_reflectionIndex == 1) {
								_yPos = _size + _padding - y - 1;
							}
						}
						if (_reflectionIndex == 3 && y >= _ySize + _padding) {
							_yPos = _size + _padding - y - 1;
						}
						state[y][x] = uint8(_rows[_yPos] >> (_xPos)) & 1;
					}
				}
			}
		}
	}

	function _convertToColors(uint8[][] memory _state) internal pure returns (bytes memory cols) {
		unchecked {
			uint256 _scanline = _state[0].length;
			if (_scanline % 4 != 0) {
				_scanline += 4 - (_scanline % 4);
			}
			cols = new bytes(_state.length * _scanline);
			for (uint256 y = 0; y < _state.length; y++) {
				for (uint256 x = 0; x < _state[y].length; x++) {
					cols[(_state.length - y - 1) * _scanline + x] = bytes1(_state[y][x]);
				}
			}
		}
	}
	
	function _makePalette(bytes3 _backgroundColor, bytes3 _foregroundColor) internal pure returns (bytes memory) {
		unchecked {
			return abi.encodePacked(_backgroundColor, bytes1(0), _foregroundColor, bytes1(0));
		}
	}

	function _getBMP(bytes memory _palette, bytes memory _colors, uint256 _size) internal pure returns (bytes memory) {
		unchecked {
			uint32 _bufSize = 14 + 40 + uint32(_palette.length);
			bytes memory _buf = new bytes(_bufSize - _palette.length);
			_buf[0] = 0x42;
			_buf[1] = 0x4d;
			uint32 _tmp = _bufSize + uint32(_colors.length);
			uint32 b;
			for (uint i = 2; i < 6; i++) {
				assembly {
					b := and(_tmp, 0xff)
					_tmp := shr(8, _tmp)
				}
				_buf[i] = bytes1(uint8(b));
			}
			_tmp = _bufSize;
			for (uint i = 10; i < 14; i++) {
				assembly {
					b := and(_tmp, 0xff)
					_tmp := shr(8, _tmp)
				}
				_buf[i] = bytes1(uint8(b));
			}
			_buf[14] = 0x28;
			_tmp = uint32(_size);
			for (uint i = 18; i < 22; i++) {
				assembly {
					b := and(_tmp, 0xff)
					_tmp := shr(8, _tmp)
				}
				_buf[i] = bytes1(uint8(b));
				_buf[i + 4] = bytes1(uint8(b));
			}
			_buf[26] = 0x01;
			_buf[28] = 0x08;
			_tmp = uint32(_colors.length);
			for (uint i = 34; i < 38; i++) {
				assembly {
					b := and(_tmp, 0xff)
					_tmp := shr(8, _tmp)
				}
				_buf[i] = bytes1(uint8(b));
			}
			_tmp = uint32(_palette.length / 4);
			for (uint i = 46; i < 50; i++) {
				assembly {
					b := and(_tmp, 0xff)
					_tmp := shr(8, _tmp)
				}
				_buf[i] = bytes1(uint8(b));
				_buf[i + 4] = bytes1(uint8(b));
			}
			return abi.encodePacked(_buf, _palette, _colors);
		}
	}

	function _uint2str(uint256 _value) internal pure returns (string memory) {
		unchecked {
			uint256 _digits = 1;
			uint256 _n = _value;
			while (_n > 9) {
				_n /= 10;
				_digits++;
			}
			bytes memory _out = new bytes(_digits);
			for (uint256 i = 0; i < _out.length; i++) {
				uint256 _dec = (_value / (10**(_out.length - i - 1))) % 10;
				_out[i] = bytes1(uint8(_dec) + 48);
			}
			return string(_out);
		}
	}

	function _col2str(bytes3 _col) internal pure returns (string memory str) {
		unchecked {
			str = "#";
			for (uint256 i = 0; i < 6; i++) {
				uint256 _hex = (uint24(_col) >> (4 * (i + 1 - 2 * (i % 2)))) % 16;
				bytes memory _char = new bytes(1);
				_char[0] = bytes1(uint8(_hex) + (_hex > 9 ? 87 : 48));
				str = string(abi.encodePacked(str, string(_char)));
			}
		}
	}

	function _encode(bytes memory _data) internal pure returns (string memory result) {
		unchecked {
			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 3 : xNFT.sol
//
// ██   ██ ███    ██ ███████ ████████ 
//  ██ ██  ████   ██ ██         ██    
//   ███   ██ ██  ██ █████      ██    
//  ██ ██  ██  ██ ██ ██         ██    
// ██   ██ ██   ████ ██         ██    
//
// xNFT - Exchangeable Non-Fungible Tokens
// An experimental hybrid of ERC-20 & ERC-721.
//
// - Easily inheritable
// - Extremely gas efficient
// - Logically coherent single contract hybrid
//
//
// !!! Important Caveats !!!
// - `ownerOf()` is unbounded in gas usage due to loops, as such, all contract
//   calls are blocked to it to prevent high transaction fees.
//   !! This will break external contracts that use `ownerOf()` !!
//   For new implementations, use the `isOwnerOf()` method to check ownership.
//   Queries outside of the blockchain should not be effected.
// - `transferFrom()` can behave unexpectedly due to how the function needs to
//   be overloaded to work for both ERC-20 & ERC-721 applications.
//   !! Any contract that does not wrap `transferFrom()` with a before/after
//   balance check has the potential to be exploited !!
//
// WARNING - Hybrid NFT standards are universally new, and inherently DANGEROUS,
// no systems have been built with these use cases in mind, and there are a number of 
// ways that experimental, complex contracts can lead to unforseen consequences.
// INTERACT WITH EXPERIMENTAL SMART CONTRACTS AT YOUR OWN RISK

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

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

abstract contract xNFT {

	uint256 constant internal MASK_SIZE = 256;
	uint256 constant internal MAX_ALLOWED_SUPPLY = 57344;
	uint256 constant internal UINT_MAX = type(uint256).max;
	uint256 constant internal M1 = 0x5555555555555555555555555555555555555555555555555555555555555555;
	uint256 constant internal M2 = 0x3333333333333333333333333333333333333333333333333333333333333333;
	uint256 constant internal M4 = 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;
	uint256 constant internal H01 = 0x0101010101010101010101010101010101010101010101010101010101010101;
	bytes32 constant internal TRANSFER_TOPIC = keccak256(bytes("Transfer(address,address,uint256)"));
	bytes32 constant internal APPROVAL_TOPIC = keccak256(bytes("Approval(address,address,uint256)"));

	uint8 constant public decimals = 0;
	uint256 immutable public totalSupply;
	uint256 immutable internal maskDepth;
	bool internal skipEventEmits = false;

	struct User {
		uint16 balance;
		uint16 approvedCount;
		bytes28 activeMasks;
		mapping(uint256 => bytes32) masks;
		mapping(address => uint256) allowance;
		mapping(address => bool) approved;
	}

	struct Info {
		address owner;
		mapping(address => User) users;
		mapping(uint256 => address) approved;
		address[] holders;
		mapping(address => uint256) indexOf;
	}
	Info internal info;

	mapping(bytes4 => bool) public supportsInterface;


	event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
	event ERC20Transfer(bytes32 indexed topic0, address indexed from, address indexed to, uint256 tokens) anonymous;
	event Approval(address indexed owner, address indexed spender, uint256 indexed tokenId);
	event ERC20Approval(bytes32 indexed topic0, address indexed owner, address indexed spender, uint256 tokens) anonymous;
	event ApprovalForAll(address indexed owner, address indexed operator, bool approved);


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

	modifier _withoutEventEmits() {
		skipEventEmits = true;
		_;
		skipEventEmits = false;
	}


	constructor(address _owner, uint256 _totalSupply) {
		require(_totalSupply > 0 && _totalSupply <= MAX_ALLOWED_SUPPLY);
		info.owner = _owner;
		totalSupply = _totalSupply;
		maskDepth = ((totalSupply - 1) / MASK_SIZE) + 1;
		supportsInterface[0x01ffc9a7] = true; // ERC-165
		supportsInterface[0x80ac58cd] = true; // ERC-721
		supportsInterface[0x5b5e139f] = true; // Metadata
		supportsInterface[0x780e9d63] = true; // Enumerable
		_initialize();
	}

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


	function approve(address _spender, uint256 _tokens) external returns (bool) {
		unchecked {
			if (_tokens > totalSupply && _tokens <= 2 * totalSupply) {
				_approveNFT(_spender, _tokens);
			} else {
				_approveERC20(msg.sender, _spender, _tokens);
			}
			return true;	
		}
	}

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

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

	function transferFrom(address _from, address _to, uint256 _tokens) external returns (bool) {
		unchecked {
			if (_tokens > totalSupply && _tokens <= 2 * totalSupply) {
				_transferNFT(_from, _to, _tokens);
			} else {
				uint256 _allowance = allowance(_from, msg.sender);
				require(_allowance >= _tokens);
				if (_allowance != UINT_MAX) {
					info.users[_from].allowance[msg.sender] -= _tokens;
				}
				_transferERC20(_from, _to, _tokens);
			}
			return true;
		}
	}

	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 {
		_transferNFT(_from, _to, _tokenId);
		uint32 _size;
		assembly {
			_size := extcodesize(_to)
		}
		if (_size > 0) {
			require(Receiver(_to).onERC721Received(msg.sender, _from, _tokenId, _data) == Receiver.onERC721Received.selector);
		}
	}

	function bulkTransfer(address _to, uint256[] memory _tokenIds) external {
		_transferNFTs(_to, _tokenIds);
	}
	

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

	function holders() external view returns (address[] memory) {
		return info.holders;
	}

	function name() external virtual view returns (string memory);

	function symbol() external virtual view returns (string memory);

	function tokenURI(uint256 _tokenId) public virtual view returns (string memory);

	function maskAtIndexOf(uint256 _index, address _user) public view returns (bytes32) {
		unchecked {
			require(_index < maskDepth);
			return info.users[_user].masks[_index];
		}
	}

	function masksOf(address _user) external view returns (bytes32[] memory masks) {
		unchecked {
			masks = new bytes32[](maskDepth);
			for (uint256 i = 0; i < masks.length; i++) {
				masks[i] = maskAtIndexOf(i, _user);
			}
		}
	}

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

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

	// !!! Important !!!
	// To save gas on bulk ERC-20 & ERC-721 transfers, this method has been written in a way
	// that doesn't individually update a storage slot for each token owner but instead loops
	// through an array of holders in order to find a match.
	// As such it costs approximately 5k gas per loop (1 block = 30m gas = 6k loops) so having
	// another contract call this method could result in very large transaction fees. To prevent
	// this from happening, this method will block and revert if the caller is a contract.
	// !! This will break external contracts that use `ownerOf()` but queries outside of the
	// blockchain should not be effected !!
	//
	// If you need to externally check if a token is owned by a certain address, use the
	// new `isOwnerOf(address _user, uint256 _tokenId)` method instead.
	// Most current NFT based contracts don't use `ownerOf()` and assume that if a call
	// to `transferFrom()` was successful then `_from` was in fact the owner.
	function ownerOf(uint256 _tokenId) public view returns (address) {
		unchecked {
			uint32 _size;
			assembly {
				_size := caller()
			}
			require(_size == 0);
			require(_tokenId > totalSupply && _tokenId <= 2 * totalSupply);
			(uint256 _maskIndex, bytes32 _mask) = _tokenIdToMask(_tokenId);
			uint256 _holdersLength = info.holders.length;
			for (uint256 i = 0; i < _holdersLength; i++) {
				address _holder = info.holders[i];
				if (maskAtIndexOf(_maskIndex, _holder) & _mask == _mask) {
					return _holder;
				}
			}
			return address(0x0);
		}
	}

	function getApproved(uint256 _tokenId) public view returns (address) {
		unchecked {
			require(_tokenId > totalSupply && _tokenId <= 2 * totalSupply);
			return info.approved[_tokenId];
		}
	}

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

	function isOwnerOf(address _user, uint256 _tokenId) external view returns (bool) {
		unchecked {
			require(_tokenId > totalSupply && _tokenId <= 2 * totalSupply);
			(uint256 _maskIndex, bytes32 _mask) = _tokenIdToMask(_tokenId);
			return maskAtIndexOf(_maskIndex, _user) & _mask == _mask;
		}
	}

	function tokenByIndex(uint256 _index) external view returns (uint256) {
		unchecked {
			require(_index < totalSupply);
			return totalSupply + _index + 1;
		}
	}

	function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256 tokenId) {
		unchecked {
			require(_index < balanceOf(_owner));
			uint256 _count = 0;
			uint256 _activeMasks = uint224(info.users[_owner].activeMasks);
			while (_activeMasks > 0 && _count <= _index) {
				uint256 _activeIndex = _lsb(_activeMasks);
				_activeMasks ^= 1 << _activeIndex;
				bytes32 _mask = maskAtIndexOf(_activeIndex, _owner);
				uint256 _maskCount = _popcount(_mask);
				if (_count + _maskCount <= _index) {
					_count += _maskCount;
				} else {
					uint256 _n = uint256(_mask);
					while (_n > 0 && _count <= _index) {
						uint256 _pos = _lsb(_n);
						_n ^= 1 << _pos;
						_count++;
						if (_count == _index + 1) {
							return (MASK_SIZE * _activeIndex) + totalSupply + _pos + 1;
						}
					}
				}
			}
		}
	}

	function getToken(uint256 _tokenId, bool _getOwner) public view returns (address tokenOwner, address approved, string memory uri) {
		return (_getOwner ? ownerOf(_tokenId) : address(0x0), getApproved(_tokenId), tokenURI(_tokenId));
	}

	function getTokens(uint256[] memory _tokenIds, bool _getOwner) external view returns (address[] memory owners, address[] memory approveds, string[] memory uris) {
		uint256 _length = _tokenIds.length;
		owners = new address[](_length);
		approveds = new address[](_length);
		uris = new string[](_length);
		for (uint256 i = 0; i < _length; i++) {
			(owners[i], approveds[i], uris[i]) = getToken(_tokenIds[i], _getOwner);
		}
	}


	// Can be overridden by a parent contract if needed. Most of the logic inside this function is
	// essential for setting up the initial supply so be careful when altering it.
	// If all you want to do is save gas on deployment by preventing all the NFT `Transfer()` events
	// from emitting, use this in your parent contract:
	// `function _initialize() internal override _withoutEventEmits { super._initialize(); }`
	function _initialize() internal virtual {
		unchecked {
			for (uint256 i = 0; i < maskDepth; i++) {
				if (i == maskDepth - 1 && totalSupply % MASK_SIZE != 0) {
					info.users[owner()].masks[i] = bytes32(UINT_MAX) >> (MASK_SIZE - (totalSupply % MASK_SIZE));
				} else {
					info.users[owner()].masks[i] = bytes32(UINT_MAX);
				}
			}
			info.users[owner()].balance = uint16(totalSupply);
			info.users[owner()].activeMasks = bytes28(uint224(2**maskDepth - 1));
			info.holders.push(owner());
			emit ERC20Transfer(TRANSFER_TOPIC, address(0x0), owner(), totalSupply);
			if (!skipEventEmits) {
				for (uint256 i = 0; i < totalSupply; i++) {
					emit Transfer(address(0x0), owner(), totalSupply + i + 1);
				}
			}
		}
	}
	
	function _approveERC20(address _owner, address _spender, uint256 _tokens) internal {
		info.users[_owner].allowance[_spender] = _tokens;
		emit ERC20Approval(APPROVAL_TOPIC, _owner, _spender, _tokens);
	}

	function _approveNFT(address _spender, uint256 _tokenId) internal {
		unchecked {
			(uint256 _maskIndex, bytes32 _mask) = _tokenIdToMask(_tokenId);
			require(maskAtIndexOf(_maskIndex, msg.sender) & _mask == _mask);
			info.approved[_tokenId] = _spender;
			info.users[msg.sender].approvedCount++;
			emit Approval(msg.sender, _spender, _tokenId);
		}
	}
	
	// Can be overridden by a parent contract to change how token ids are selected when performing
	// an ERC-20 transfer. It is not recommended to do this unless you're sure you know what
	// the outcome will be and test it to make sure your implementation works as expected.
	function _transferERC20(address _from, address _to, uint256 _tokens) internal virtual {
		unchecked {
			uint256 _count = 0;
			uint256[] memory _tokenIds = new uint256[](_tokens);
			bytes32[] memory _masks = new bytes32[](maskDepth);
			uint256 _activeMasks = uint224(info.users[_from].activeMasks);
			while (_activeMasks > 0 && _count < _tokens) {
				uint256 _activeIndex = _lsb(_activeMasks);
				_activeMasks ^= 1 << _activeIndex;
				bytes32 _mask = maskAtIndexOf(_activeIndex, _from);
				uint256 _n = uint256(_mask);
				while (_n > 0 && _count < _tokens) {
					uint256 _pos = _lsb(_n);
					bytes32 _tokenMask = bytes32(1 << _pos);
					_masks[_activeIndex] |= _tokenMask;
					_tokenIds[_count++] = (MASK_SIZE * _activeIndex) + totalSupply + _pos + 1;
					_n ^= uint256(_tokenMask);
				}
				require(_mask & _masks[_activeIndex] == _masks[_activeIndex]);
			}
			require(_count == _tokens);
			_transfer(_from, _to, _masks, _tokenIds);
		}
	}
	
	function _transferNFT(address _from, address _to, uint256 _tokenId) internal {
		unchecked {
			require(_tokenId > totalSupply && _tokenId <= 2 * totalSupply);
			(uint256 _maskIndex, bytes32 _mask) = _tokenIdToMask(_tokenId);
			require(maskAtIndexOf(_maskIndex, _from) & _mask == _mask);
			require(msg.sender == _from || msg.sender == getApproved(_tokenId) || isApprovedForAll(_from, msg.sender));
			bytes32[] memory _masks = new bytes32[](maskDepth);
			_masks[_maskIndex] = _mask;
			uint256[] memory _tokenIds = new uint256[](1);
			_tokenIds[0] = _tokenId;
			_transfer(_from, _to, _masks, _tokenIds);
		}
	}
	
	function _transferNFTs(address _to, uint256[] memory _tokenIds) internal {
		unchecked {
			bytes32[] memory _masks = new bytes32[](maskDepth);
			for (uint256 i = 0; i < _tokenIds.length; i++) {
				(uint256 _maskIndex, bytes32 _mask) = _tokenIdToMask(_tokenIds[i]);
				_masks[_maskIndex] |= _mask;
			}
			uint256 _count = 0;
			for (uint256 i = 0; i < _masks.length; i++) {
				if (_masks[i] != 0x0) {
					require(maskAtIndexOf(i, msg.sender) & _masks[i] == _masks[i]);
					_count += _popcount(_masks[i]);
				}
			}
			require(_count == _tokenIds.length);
			_transfer(msg.sender, _to, _masks, _tokenIds);
		}
	}

	// Can be overridden by a parent contract in order to add some logic before the transfer completes. The
	// code here is important for the ERC-721 side of things so unless you explicitly want to change how this
	// works, you should always use `super._beforeTransfer(...);` in your overridden function.
	function _beforeTransfer(address _from, address _to, bytes32[] memory, uint256[] memory _tokenIds) internal virtual {
		unchecked {
			bool _skip = skipEventEmits;
			bool _skipApproveds = info.users[_from].approvedCount == 0;
			if (!(_skipApproveds && _skip)) {
				for (uint256 i = 0; i < _tokenIds.length; i++) {
					if (!_skipApproveds && getApproved(_tokenIds[i]) != address(0x0)) {
						info.users[_from].approvedCount--;
						info.approved[_tokenIds[i]] = address(0x0);
						emit Approval(address(0x0), address(0x0), _tokenIds[i]);
					}
					if (!_skip) {
						emit Transfer(_from, _to, _tokenIds[i]);
					}
				}
			}
		}
	}

	function _transfer(address _from, address _to, bytes32[] memory _masks, uint256[] memory _tokenIds) internal {
		unchecked {
			require(_to != address(0x0));
			require(_tokenIds.length > 0);
			_beforeTransfer(_from, _to, _masks, _tokenIds);
			uint256 _fromActive = uint224(info.users[_from].activeMasks);
			uint256 _toActive = uint224(info.users[_to].activeMasks);
			for (uint256 i = 0; i < _masks.length; i++) {
				if (_masks[i] != bytes32(0x0)) {
					bytes32 _fromMask = maskAtIndexOf(i, _from);
					_fromMask ^= _masks[i];
					info.users[_from].masks[i] = _fromMask;
					bytes32 _toMask = maskAtIndexOf(i, _to);
					_toMask |= _masks[i];
					info.users[_to].masks[i] = _toMask;
					if (_fromMask == 0x0) {
						_fromActive ^= 1 << i;
					}
					_toActive |= 1 << i;
					require(_fromMask & _toMask == 0x0);
				}
			}
			uint256 _fromBalance = balanceOf(_from);
			_fromBalance -= _tokenIds.length;
			info.users[_from].balance = uint16(_fromBalance);
			info.users[_from].activeMasks = bytes28(uint224(_fromActive));
			uint256 _toBalance = balanceOf(_to);
			info.users[_to].balance = uint16(_toBalance + _tokenIds.length);
			info.users[_to].activeMasks = bytes28(uint224(_toActive));
			if (_fromBalance == 0) {
				uint256 _index = info.indexOf[_from];
				if (_toBalance == 0) {
					info.holders[_index] = _to;
					info.indexOf[_to] = _index;
				} else {
					address _moved = info.holders[info.holders.length - 1];
					info.holders[_index] = _moved;
					info.indexOf[_moved] = _index;
					info.holders.pop();
				}
				delete info.indexOf[_from];
			} else if (_toBalance == 0) {
				info.holders.push(_to);
				info.indexOf[_to] = info.holders.length - 1;
			}
			emit ERC20Transfer(TRANSFER_TOPIC, _from, _to, _tokenIds.length);
			_afterTransfer(_from, _to, _masks, _tokenIds);
		}
	}

	// Can be overridden by a parent contract and used as a way to execute extra code after a transfer has completed.
	function _afterTransfer(address _from, address _to, bytes32[] memory _masks, uint256[] memory _tokenIds) internal virtual {}


	function _tokenIdToMask(uint256 _tokenId) internal view returns (uint256 maskIndex, bytes32 mask) {
		unchecked {
			maskIndex = (_tokenId - totalSupply - 1) / MASK_SIZE;
			mask = bytes32(1 << (_tokenId - (MASK_SIZE * maskIndex) - totalSupply - 1));
		}
	}
	
	function _popcount(bytes32 _b) internal pure returns (uint256) {
		unchecked {
			uint256 _n = uint256(_b);
			if (_n == 0) {
				return 0;
			} else if (_n == UINT_MAX) {
				return MASK_SIZE;
			}
			_n -= (_n >> 1) & M1;
			_n = (_n & M2) + ((_n >> 2) & M2);
			_n = (_n + (_n >> 4)) & M4;
			_n = (_n * H01) >> 248;
			return _n;
		}
	}


	// An extremely gas efficient implementation of the least significant bit algorithm. Due to all of
	// the constants in the if/else binary search tree, this function does add approximately 1.1m gas
	// to the deployment cost (~0.022 ETH @ 20 Gwei) but the end users will save on transaction fees.
	// The 'break even' point is around 3,000 total transfer volume where by you spending the extra to
	// make it more efficient, you have saved your end users more than you initially paid.
	// If you would rather have cheaper deployment costs and slightly less efficient transfers, replace
	// the entire `_lsb()` function with the one commented below:
	// ```function _lsb(uint256 _n) internal pure returns (uint256 i) {
	// 	unchecked { uint256 _b = _n & ~(_n - 1); i = 0;
	// 	for (uint256 _s = 0x80; _s > 0; _s >>= 1) { if (_b >= (1 << _s)) { _b >>= _s; i |= _s; } } }
	// }```
	function _lsb(uint256 _n) internal pure returns (uint256 i) {
		unchecked {
			uint256 _b = _n & ~(_n - 1);
			if (_b < 0x0100000000000000000000000000000000)
				if (_b < 0x010000000000000000)
					if (_b < 0x0100000000)
						if (_b < 0x010000)
							if (_b < 0x0100)
								if (_b < 0x10)
									if (_b < 0x04)
										if (_b < 0x02) return 0; else return 1;
									else
										if (_b < 0x08) return 2; else return 3;
								else
									if (_b < 0x40)
										if (_b < 0x20) return 4; else return 5;
									else
										if (_b < 0x80) return 6; else return 7;
							else
								if (_b < 0x1000)
									if (_b < 0x0400)
										if (_b < 0x0200) return 8; else return 9;
									else
										if (_b < 0x0800) return 10; else return 11;
								else
									if (_b < 0x4000)
										if (_b < 0x2000) return 12; else return 13;
									else
										if (_b < 0x8000) return 14; else return 15;
						else
							if (_b < 0x01000000)
								if (_b < 0x100000)
									if (_b < 0x040000)
										if (_b < 0x020000) return 16; else return 17;
									else
										if (_b < 0x080000) return 18; else return 19;
								else
									if (_b < 0x400000)
										if (_b < 0x200000) return 20; else return 21;
									else
										if (_b < 0x800000) return 22; else return 23;
							else
								if (_b < 0x10000000)
									if (_b < 0x04000000)
										if (_b < 0x02000000) return 24; else return 25;
									else
										if (_b < 0x08000000) return 26; else return 27;
								else
									if (_b < 0x40000000)
										if (_b < 0x20000000) return 28; else return 29;
									else
										if (_b < 0x80000000) return 30; else return 31;
					else
						if (_b < 0x01000000000000)
							if (_b < 0x010000000000)
								if (_b < 0x1000000000)
									if (_b < 0x0400000000)
										if (_b < 0x0200000000) return 32; else return 33;
									else
										if (_b < 0x0800000000) return 34; else return 35;
								else
									if (_b < 0x4000000000)
										if (_b < 0x2000000000) return 36; else return 37;
									else
										if (_b < 0x8000000000) return 38; else return 39;
							else
								if (_b < 0x100000000000)
									if (_b < 0x040000000000)
										if (_b < 0x020000000000) return 40; else return 41;
									else
										if (_b < 0x080000000000) return 42; else return 43;
								else
									if (_b < 0x400000000000)
										if (_b < 0x200000000000) return 44; else return 45;
									else
										if (_b < 0x800000000000) return 46; else return 47;
						else
							if (_b < 0x0100000000000000)
								if (_b < 0x10000000000000)
									if (_b < 0x04000000000000)
										if (_b < 0x02000000000000) return 48; else return 49;
									else
										if (_b < 0x08000000000000) return 50; else return 51;
								else
									if (_b < 0x40000000000000)
										if (_b < 0x20000000000000) return 52; else return 53;
									else
										if (_b < 0x80000000000000) return 54; else return 55;
							else
								if (_b < 0x1000000000000000)
									if (_b < 0x0400000000000000)
										if (_b < 0x0200000000000000) return 56; else return 57;
									else
										if (_b < 0x0800000000000000) return 58; else return 59;
								else
									if (_b < 0x4000000000000000)
										if (_b < 0x2000000000000000) return 60; else return 61;
									else
										if (_b < 0x8000000000000000) return 62; else return 63;
				else
					if (_b < 0x01000000000000000000000000)
						if (_b < 0x0100000000000000000000)
							if (_b < 0x01000000000000000000)
								if (_b < 0x100000000000000000)
									if (_b < 0x040000000000000000)
										if (_b < 0x020000000000000000) return 64; else return 65;
									else
										if (_b < 0x080000000000000000) return 66; else return 67;
								else
									if (_b < 0x400000000000000000)
										if (_b < 0x200000000000000000) return 68; else return 69;
									else
										if (_b < 0x800000000000000000) return 70; else return 71;
							else
								if (_b < 0x10000000000000000000)
									if (_b < 0x04000000000000000000)
										if (_b < 0x02000000000000000000) return 72; else return 73;
									else
										if (_b < 0x08000000000000000000) return 74; else return 75;
								else
									if (_b < 0x40000000000000000000)
										if (_b < 0x20000000000000000000) return 76; else return 77;
									else
										if (_b < 0x80000000000000000000) return 78; else return 79;
						else
							if (_b < 0x010000000000000000000000)
								if (_b < 0x1000000000000000000000)
									if (_b < 0x0400000000000000000000)
										if (_b < 0x0200000000000000000000) return 80; else return 81;
									else
										if (_b < 0x0800000000000000000000) return 82; else return 83;
								else
									if (_b < 0x4000000000000000000000)
										if (_b < 0x2000000000000000000000) return 84; else return 85;
									else
										if (_b < 0x8000000000000000000000) return 86; else return 87;
							else
								if (_b < 0x100000000000000000000000)
									if (_b < 0x040000000000000000000000)
										if (_b < 0x020000000000000000000000) return 88; else return 89;
									else
										if (_b < 0x080000000000000000000000) return 90; else return 91;
								else
									if (_b < 0x400000000000000000000000)
										if (_b < 0x200000000000000000000000) return 92; else return 93;
									else
										if (_b < 0x800000000000000000000000) return 94; else return 95;
					else
						if (_b < 0x010000000000000000000000000000)
							if (_b < 0x0100000000000000000000000000)
								if (_b < 0x10000000000000000000000000)
									if (_b < 0x04000000000000000000000000)
										if (_b < 0x02000000000000000000000000) return 96; else return 97;
									else
										if (_b < 0x08000000000000000000000000) return 98; else return 99;
								else
									if (_b < 0x40000000000000000000000000)
										if (_b < 0x20000000000000000000000000) return 100; else return 101;
									else
										if (_b < 0x80000000000000000000000000) return 102; else return 103;
							else
								if (_b < 0x1000000000000000000000000000)
									if (_b < 0x0400000000000000000000000000)
										if (_b < 0x0200000000000000000000000000) return 104; else return 105;
									else
										if (_b < 0x0800000000000000000000000000) return 106; else return 107;
								else
									if (_b < 0x4000000000000000000000000000)
										if (_b < 0x2000000000000000000000000000) return 108; else return 109;
									else
										if (_b < 0x8000000000000000000000000000) return 110; else return 111;
						else
							if (_b < 0x01000000000000000000000000000000)
								if (_b < 0x100000000000000000000000000000)
									if (_b < 0x040000000000000000000000000000)
										if (_b < 0x020000000000000000000000000000) return 112; else return 113;
									else
										if (_b < 0x080000000000000000000000000000) return 114; else return 115;
								else
									if (_b < 0x400000000000000000000000000000)
										if (_b < 0x200000000000000000000000000000) return 116; else return 117;
									else
										if (_b < 0x800000000000000000000000000000) return 118; else return 119;
							else
								if (_b < 0x10000000000000000000000000000000)
									if (_b < 0x04000000000000000000000000000000)
										if (_b < 0x02000000000000000000000000000000) return 120; else return 121;
									else
										if (_b < 0x08000000000000000000000000000000) return 122; else return 123;
								else
									if (_b < 0x40000000000000000000000000000000)
										if (_b < 0x20000000000000000000000000000000) return 124; else return 125;
									else
										if (_b < 0x80000000000000000000000000000000) return 126; else return 127;
			else
				if (_b < 0x01000000000000000000000000000000000000000000000000)
					if (_b < 0x010000000000000000000000000000000000000000)
						if (_b < 0x01000000000000000000000000000000000000)
							if (_b < 0x010000000000000000000000000000000000)
								if (_b < 0x1000000000000000000000000000000000)
									if (_b < 0x0400000000000000000000000000000000)
										if (_b < 0x0200000000000000000000000000000000) return 128; else return 129;
									else
										if (_b < 0x0800000000000000000000000000000000) return 130; else return 131;
								else
									if (_b < 0x4000000000000000000000000000000000)
										if (_b < 0x2000000000000000000000000000000000) return 132; else return 133;
									else
										if (_b < 0x8000000000000000000000000000000000) return 134; else return 135;
							else
								if (_b < 0x100000000000000000000000000000000000)
									if (_b < 0x040000000000000000000000000000000000)
										if (_b < 0x020000000000000000000000000000000000) return 136; else return 137;
									else
										if (_b < 0x080000000000000000000000000000000000) return 138; else return 139;
								else
									if (_b < 0x400000000000000000000000000000000000)
										if (_b < 0x200000000000000000000000000000000000) return 140; else return 141;
									else
										if (_b < 0x800000000000000000000000000000000000) return 142; else return 143;
						else
							if (_b < uint160(0x0100000000000000000000000000000000000000))
								if (_b < 0x10000000000000000000000000000000000000)
									if (_b < 0x04000000000000000000000000000000000000)
										if (_b < 0x02000000000000000000000000000000000000) return 144; else return 145;
									else
										if (_b < 0x08000000000000000000000000000000000000) return 146; else return 147;
								else
									if (_b < 0x40000000000000000000000000000000000000)
										if (_b < 0x20000000000000000000000000000000000000) return 148; else return 149;
									else
										if (_b < 0x80000000000000000000000000000000000000) return 150; else return 151;
							else
								if (_b < uint160(0x1000000000000000000000000000000000000000))
									if (_b < uint160(0x0400000000000000000000000000000000000000))
										if (_b < uint160(0x0200000000000000000000000000000000000000)) return 152; else return 153;
									else
										if (_b < uint160(0x0800000000000000000000000000000000000000)) return 154; else return 155;
								else
									if (_b < uint160(0x4000000000000000000000000000000000000000))
										if (_b < uint160(0x2000000000000000000000000000000000000000)) return 156; else return 157;
									else
										if (_b < uint160(0x8000000000000000000000000000000000000000)) return 158; else return 159;
					else
						if (_b < 0x0100000000000000000000000000000000000000000000)
							if (_b < 0x01000000000000000000000000000000000000000000)
								if (_b < 0x100000000000000000000000000000000000000000)
									if (_b < 0x040000000000000000000000000000000000000000)
										if (_b < 0x020000000000000000000000000000000000000000) return 160; else return 161;
									else
										if (_b < 0x080000000000000000000000000000000000000000) return 162; else return 163;
								else
									if (_b < 0x400000000000000000000000000000000000000000)
										if (_b < 0x200000000000000000000000000000000000000000) return 164; else return 165;
									else
										if (_b < 0x800000000000000000000000000000000000000000) return 166; else return 167;
							else
								if (_b < 0x10000000000000000000000000000000000000000000)
									if (_b < 0x04000000000000000000000000000000000000000000)
										if (_b < 0x02000000000000000000000000000000000000000000) return 168; else return 169;
									else
										if (_b < 0x08000000000000000000000000000000000000000000) return 170; else return 171;
								else
									if (_b < 0x40000000000000000000000000000000000000000000)
										if (_b < 0x20000000000000000000000000000000000000000000) return 172; else return 173;
									else
										if (_b < 0x80000000000000000000000000000000000000000000) return 174; else return 175;
						else
							if (_b < 0x010000000000000000000000000000000000000000000000)
								if (_b < 0x1000000000000000000000000000000000000000000000)
									if (_b < 0x0400000000000000000000000000000000000000000000)
										if (_b < 0x0200000000000000000000000000000000000000000000) return 176; else return 177;
									else
										if (_b < 0x0800000000000000000000000000000000000000000000) return 178; else return 179;
								else
									if (_b < 0x4000000000000000000000000000000000000000000000)
										if (_b < 0x2000000000000000000000000000000000000000000000) return 180; else return 181;
									else
										if (_b < 0x8000000000000000000000000000000000000000000000) return 182; else return 183;
							else
								if (_b < 0x100000000000000000000000000000000000000000000000)
									if (_b < 0x040000000000000000000000000000000000000000000000)
										if (_b < 0x020000000000000000000000000000000000000000000000) return 184; else return 185;
									else
										if (_b < 0x080000000000000000000000000000000000000000000000) return 186; else return 187;
								else
									if (_b < 0x400000000000000000000000000000000000000000000000)
										if (_b < 0x200000000000000000000000000000000000000000000000) return 188; else return 189;
									else
										if (_b < 0x800000000000000000000000000000000000000000000000) return 190; else return 191;
				else
					if (_b < 0x0100000000000000000000000000000000000000000000000000000000)
						if (_b < 0x010000000000000000000000000000000000000000000000000000)
							if (_b < 0x0100000000000000000000000000000000000000000000000000)
								if (_b < 0x10000000000000000000000000000000000000000000000000)
									if (_b < 0x04000000000000000000000000000000000000000000000000)
										if (_b < 0x02000000000000000000000000000000000000000000000000) return 192; else return 193;
									else
										if (_b < 0x08000000000000000000000000000000000000000000000000) return 194; else return 195;
								else
									if (_b < 0x40000000000000000000000000000000000000000000000000)
										if (_b < 0x20000000000000000000000000000000000000000000000000) return 196; else return 197;
									else
										if (_b < 0x80000000000000000000000000000000000000000000000000) return 198; else return 199;
							else
								if (_b < 0x1000000000000000000000000000000000000000000000000000)
									if (_b < 0x0400000000000000000000000000000000000000000000000000)
										if (_b < 0x0200000000000000000000000000000000000000000000000000) return 200; else return 201;
									else
										if (_b < 0x0800000000000000000000000000000000000000000000000000) return 202; else return 203;
								else
									if (_b < 0x4000000000000000000000000000000000000000000000000000)
										if (_b < 0x2000000000000000000000000000000000000000000000000000) return 204; else return 205;
									else
										if (_b < 0x8000000000000000000000000000000000000000000000000000) return 206; else return 207;
						else
							if (_b < 0x01000000000000000000000000000000000000000000000000000000)
								if (_b < 0x100000000000000000000000000000000000000000000000000000)
									if (_b < 0x040000000000000000000000000000000000000000000000000000)
										if (_b < 0x020000000000000000000000000000000000000000000000000000) return 208; else return 209;
									else
										if (_b < 0x080000000000000000000000000000000000000000000000000000) return 210; else return 211;
								else
									if (_b < 0x400000000000000000000000000000000000000000000000000000)
										if (_b < 0x200000000000000000000000000000000000000000000000000000) return 212; else return 213;
									else
										if (_b < 0x800000000000000000000000000000000000000000000000000000) return 214; else return 215;
							else
								if (_b < 0x10000000000000000000000000000000000000000000000000000000)
									if (_b < 0x04000000000000000000000000000000000000000000000000000000)
										if (_b < 0x02000000000000000000000000000000000000000000000000000000) return 216; else return 217;
									else
										if (_b < 0x08000000000000000000000000000000000000000000000000000000) return 218; else return 219;
								else
									if (_b < 0x40000000000000000000000000000000000000000000000000000000)
										if (_b < 0x20000000000000000000000000000000000000000000000000000000) return 220; else return 221;
									else
										if (_b < 0x80000000000000000000000000000000000000000000000000000000) return 222; else return 223;
					else
						if (_b < 0x01000000000000000000000000000000000000000000000000000000000000)
							if (_b < 0x010000000000000000000000000000000000000000000000000000000000)
								if (_b < 0x1000000000000000000000000000000000000000000000000000000000)
									if (_b < 0x0400000000000000000000000000000000000000000000000000000000)
										if (_b < 0x0200000000000000000000000000000000000000000000000000000000) return 224; else return 225;
									else
										if (_b < 0x0800000000000000000000000000000000000000000000000000000000) return 226; else return 227;
								else
									if (_b < 0x4000000000000000000000000000000000000000000000000000000000)
										if (_b < 0x2000000000000000000000000000000000000000000000000000000000) return 228; else return 229;
									else
										if (_b < 0x8000000000000000000000000000000000000000000000000000000000) return 230; else return 231;
							else
								if (_b < 0x100000000000000000000000000000000000000000000000000000000000)
									if (_b < 0x040000000000000000000000000000000000000000000000000000000000)
										if (_b < 0x020000000000000000000000000000000000000000000000000000000000) return 232; else return 233;
									else
										if (_b < 0x080000000000000000000000000000000000000000000000000000000000) return 234; else return 235;
								else
									if (_b < 0x400000000000000000000000000000000000000000000000000000000000)
										if (_b < 0x200000000000000000000000000000000000000000000000000000000000) return 236; else return 237;
									else
										if (_b < 0x800000000000000000000000000000000000000000000000000000000000) return 238; else return 239;
						else
							if (_b < 0x0100000000000000000000000000000000000000000000000000000000000000)
								if (_b < 0x10000000000000000000000000000000000000000000000000000000000000)
									if (_b < 0x04000000000000000000000000000000000000000000000000000000000000)
										if (_b < 0x02000000000000000000000000000000000000000000000000000000000000) return 240; else return 241;
									else
										if (_b < 0x08000000000000000000000000000000000000000000000000000000000000) return 242; else return 243;
								else
									if (_b < 0x40000000000000000000000000000000000000000000000000000000000000)
										if (_b < 0x20000000000000000000000000000000000000000000000000000000000000) return 244; else return 245;
									else
										if (_b < 0x80000000000000000000000000000000000000000000000000000000000000) return 246; else return 247;
							else
								if (_b < 0x1000000000000000000000000000000000000000000000000000000000000000)
									if (_b < 0x0400000000000000000000000000000000000000000000000000000000000000)
										if (_b < 0x0200000000000000000000000000000000000000000000000000000000000000) return 248; else return 249;
									else
										if (_b < 0x0800000000000000000000000000000000000000000000000000000000000000) return 250; else return 251;
								else
									if (_b < 0x4000000000000000000000000000000000000000000000000000000000000000)
										if (_b < 0x2000000000000000000000000000000000000000000000000000000000000000) return 252; else return 253;
									else
										if (_b < 0x8000000000000000000000000000000000000000000000000000000000000000) return 254; else return 255;
		}
	}
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"payable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes32","name":"topic0","type":"bytes32"},{"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":"ERC20Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes32","name":"topic0","type":"bytes32"},{"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":"ERC20Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"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":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"bulkTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_tokens","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collectAllTradingFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_wethAmount0Max","type":"uint128"},{"internalType":"uint128","name":"_wethAmount1Max","type":"uint128"},{"internalType":"uint128","name":"_wcellAmount0Max","type":"uint128"},{"internalType":"uint128","name":"_wcellAmount1Max","type":"uint128"}],"name":"collectTradingFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bool","name":"_getOwner","type":"bool"}],"name":"getToken","outputs":[{"internalType":"address","name":"tokenOwner","type":"address"},{"internalType":"address","name":"approved","type":"address"},{"internalType":"string","name":"uri","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"bool","name":"_getOwner","type":"bool"}],"name":"getTokens","outputs":[{"internalType":"address[]","name":"owners","type":"address[]"},{"internalType":"address[]","name":"approveds","type":"address[]"},{"internalType":"string[]","name":"uris","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasClaimedAirdrop","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holders","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"isOwnerOf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"maskAtIndexOf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"masksOf","outputs":[{"internalType":"bytes32[]","name":"masks","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"metadata","outputs":[{"internalType":"contract Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokens","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"mintCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mintable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pairV2","outputs":[{"internalType":"contract PairV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"salt","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_operator","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Metadata","name":"_metadata","type":"address"}],"name":"setMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"team","outputs":[{"internalType":"contract Team","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"_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":"wcellPoolV3","outputs":[{"internalType":"contract PoolV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wcellPositionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethPoolV3","outputs":[{"internalType":"contract PoolV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethPositionId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

6101606040525f805460ff19169055610200600d5530611000600180546001600160a01b0319166001600160a01b038416178155608082905261010090620000489083620010ea565b6200005491906200111a565b6200006190600162001130565b60a05260066020527f477a984de5936bcb02475f64e0ea676103106ac0785c67bf7e9e846450b51ef68054600160ff1991821681179092557fd544553a2e70858ffdf1e1169f6f124859d29ddf2686bcabf4e6f71bc630442280548216831790557fcc41b8fe3dd37df8e4a56c49f4e83a8fb6899f1fe8f1ddc40678281e8ec62212805482168317905563780e9d6360e01b5f527fa99870648958e45dc5b37a02b811cf5f899ba384167c205b3dcb1f6df5e47372805490911690911790556200012a620006c1565b50505f341162000138575f80fd5b600180546001600160a01b03191673faded72464d6e76e37300b467673b36ecc4d2ccf1790556040516200016c90620010ba565b604051809103905ff08015801562000186573d5f803e3d5ffd5b506001600160a01b031661010052604051620001a290620010c8565b604051809103905ff080158015620001bc573d5f803e3d5ffd5b50600780546001600160a01b0319166001600160a01b039290921691909117905560805161010090620001f190349062001146565b620001fd91906200111a565b60e052604080516312a9293f60e21b8152905130915f917368b3465833fb72a70ecdf485e0e4c7bd8665fc4591634aa4a4fc9160048083019260209291908290030181865afa15801562000253573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000279919062001175565b90505f620002a7836001600160a01b0316836001600160a01b03161061100060e051620006e260201b60201c565b5090507368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002fb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000321919062001175565b60405163a167129560e01b81526001600160a01b03858116600483015284811660248301526127106044830152919091169063a1671295906064016020604051808303815f875af115801562000379573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200039f919062001175565b6001600160a01b0390811661014081905260405163f637731d60e01b815291831660048301529063f637731d906024015f604051808303815f87803b158015620003e7575f80fd5b505af1158015620003fa573d5f803e3d5ffd5b505050505f73685c401540c103631a0ba7f14a3d16ae3cb4e50b6001600160a01b0316633850c7bd6040518163ffffffff1660e01b815260040160e060405180830381865afa15801562000450573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620004769190620011b1565b5050505050506001600160a01b0316905060c0818262000497919062001146565b620004ab90670de0b6b3a764000062001146565b901c60c081905260e05162000506916001600160a01b0387167318e5f92103d1b34623738ee79214b1659f2ee10910916110009190620004f490670de0b6b3a764000062001146565b6200050091906200111a565b620006e2565b50809250507368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200055c573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000582919062001175565b60405163a167129560e01b81526001600160a01b0386811660048301527318e5f92103d1b34623738ee79214b1659f2ee10960248301526127106044830152919091169063a1671295906064016020604051808303815f875af1158015620005ec573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000612919062001175565b6001600160a01b0390811661012081905260405163f637731d60e01b815291841660048301529063f637731d906024015f604051808303815f87803b1580156200065a575f80fd5b505af11580156200066d573d5f803e3d5ffd5b50505050600143620006809190620010ea565b6040516429b0b63a1d60d91b60208201529040602582015260450160405160208183030381529060405280519060200120600b8190555050505050620012a5565b5f805460ff19166001179055620006d76200076a565b5f805460ff19169055565b5f805f6200072a86620006f65784620006f8565b855b871562000706578562000708565b865b6200071890600160c01b6200111a565b62000724919062001146565b62000a07565b9050620007378162000a52565b91506200074660c88362001259565b6200075290836200127d565b91506200075f8262000d77565b925050935093915050565b5f5b60a0518110156200085757600160a0510381148015620007a15750610100608051816200079d576200079d62001106565b0615155b156200080c5761010060805181620007bd57620007bd62001106565b5f19919006610100031c60025f620007dd6001546001600160a01b031690565b6001600160a01b0316815260208082019290925260409081015f9081208582526001019092529020556200084e565b5f1960025f620008246001546001600160a01b031690565b6001600160a01b0316815260208082019290925260409081015f9081208582526001019092529020555b6001016200076c565b5060805160025f620008716001546001600160a01b031690565b6001600160a01b031681526020808201929092526040015f908120805461ffff191661ffff949094169390931790925560a051600290810a5f190190911b91620008c36001546001600160a01b031690565b6001600160a01b031681526020808201929092526040015f20805463ffffffff166401000000009390921c9290920217905560046200090a6001546001600160a01b031690565b8154600180820184555f93845260209093200180546001600160a01b0319166001600160a01b039283161790559054166001600160a01b03165f6001600160a01b031660405180606001604052806021815260200162009d7f60219139805190602001206080516040516200098191815260200190565b60405180910390a35f5460ff1662000a05575f5b60805181101562000a03576080518101600101620009bb6001546001600160a01b031690565b6001600160a01b03165f6001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a460010162000995565b505b565b80600260018201045b8181101562000a4c5780915060028182858162000a315762000a3162001106565b04018162000a435762000a4362001106565b04905062000a10565b50919050565b5f6401000276a36001600160a01b0383161080159062000a8e575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b62000ac45760405162461bcd60e51b81526020600482015260016024820152602960f91b60448201526064015b60405180910390fd5b600160201b600160c01b03602083901b166001600160801b03811160071b81811c6001600160401b03811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c9790881196179094179092171790911717176080811062000b5857607f810383901c915062000b62565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c678000000000000000161760c19b909b1c674000000000000000169a909a1760c29990991c672000000000000000169890981760c39790971c671000000000000000169690961760c49590951c670800000000000000169490941760c59390931c670400000000000000169290921760c69190911c670200000000000000161760c79190911c670100000000000000161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b1462000d68576001600160a01b03891662000d4a8262000d77565b6001600160a01b0316111562000d61578162000d6a565b8062000d6a565b815b9998505050505050505050565b5f805f8360020b1262000d8e578260020b62000d95565b8260020b5f035b9050620d89e881111562000dd05760405162461bcd60e51b81526020600482015260016024820152601560fa1b604482015260640162000abb565b5f816001165f0362000de757600160801b62000df9565b6ffffcb933bd6fad37aa2d162d1a5940015b6001600160881b03169050600282161562000e24576ffff97272373d413259a46990580e213a0260801c5b600482161562000e44576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b600882161562000e64576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b601082161562000e84576fffcb9843d60f6159c9db58835c9266440260801c5b602082161562000ea4576fff973b41fa98c081472e6896dfb254c00260801c5b604082161562000ec4576fff2ea16466c96a3843ec78b326b528610260801c5b608082161562000ee4576ffe5dee046a99a2a811c461f1969c30530260801c5b61010082161562000f05576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b61020082161562000f26576ff987a7253ac413176f2b074cf7815e540260801c5b61040082161562000f47576ff3392b0822b70005940c7a398e4b70f30260801c5b61080082161562000f68576fe7159475a2c29b7443b29c7fa6e889d90260801c5b61100082161562000f89576fd097f3bdfd2022b8845ad8f792aa58250260801c5b61200082161562000faa576fa9f746462d870fdf8a65dc1f90e061e50260801c5b61400082161562000fcb576f70d869a156d2a1b890bb3df62baf32f70260801c5b61800082161562000fec576f31be135f97d08fd981231505542fcfa60260801c5b620100008216156200100e576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156200102f576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156200104f576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156200106d576b048a170391f7dc42444e8fa20260801c5b5f8460020b13156200109057805f19816200108c576200108c62001106565b0490505b640100000000810615620010a6576001620010a8565b5f5b60ff16602082901c0192505050919050565b61093980620066f283390190565b612d54806200702b83390190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115620011005762001100620010d6565b92915050565b634e487b7160e01b5f52601260045260245ffd5b5f826200112b576200112b62001106565b500490565b80820180821115620011005762001100620010d6565b8082028115828204841417620011005762001100620010d6565b6001600160a01b038116811462000a03575f80fd5b5f6020828403121562001186575f80fd5b8151620011938162001160565b9392505050565b805161ffff81168114620011ac575f80fd5b919050565b5f805f805f805f60e0888a031215620011c8575f80fd5b8751620011d58162001160565b8097505060208801518060020b8114620011ed575f80fd5b9550620011fd604089016200119a565b94506200120d606089016200119a565b93506200121d608089016200119a565b925060a088015160ff8116811462001233575f80fd5b60c0890151909250801515811462001249575f80fd5b8091505092959891949750929550565b5f8260020b806200126e576200126e62001106565b808360020b0791505092915050565b600282810b9082900b03627fffff198112627fffff82131715620011005762001100620010d6565b60805160a05160c05160e05161010051610120516101405161533e620013b45f395f6104b101525f61042601525f818161064201528181610cd701528181610d9201528181610e330152611be001525f818161172401526118e501525f81816118c1015261192e01525f818161094701528181611353015281816120f2015281816122120152613b6c01525f81816103b5015281816109a1015281816109cb01528181610a1701528181610a4101528181610ea901528181610ed30152818161108501528181611215015281816112410152818161127b015281816112a501528181611d8b01528181611db50152818161200a01528181612034015281816123260152613abd015261533e5ff3fe60806040526004361061026a575f3560e01c806370a082311161014a578063a9059cbb116100be578063d28a476111610078578063d28a4761146107a7578063db737c78146107c6578063dd62ed3e146107f4578063e985e9c514610839578063f3cb838514610884578063f4cdda36146108a3575f80fd5b8063a9059cbb146106fb578063b88d4fde1461071a578063bdb4b84814610739578063bfa0b13314610754578063c5b8f77214610769578063c87b56dd14610788575f80fd5b8063888ce1f31161010f578063888ce1f3146106645780638da5cb5b146106795780638fffabed1461069657806395d89b41146106b5578063a0712d68146106c9578063a22cb465146106dc575f80fd5b806370a08231146105985780637c187f7b146105d05780638129fc1c146105fc5780638188f71c1461061057806385f2aef214610631575f80fd5b806324cea3a6116101e15780633d13f874116101a65780633d13f874146104f257806342842e0e146105115780634bce92f3146105305780634bf365df146105455780634f6ccce71461055a5780636352211e14610579575f80fd5b806324cea3a6146104485780632f745c591461045c578063313ce5671461047b578063348fb288146104a0578063392f37e9146104d3575f80fd5b80631078d1ed116102325780631078d1ed1461035557806313af40351461038357806318160ddd146103a457806319781e3c146103d757806323b872dd146103f657806324bfe56514610415575f80fd5b806301ffc9a71461026e57806306fdde03146102b1578063076f4662146102d2578063081812fc146102ff578063095ea7b314610336575b5f80fd5b348015610279575f80fd5b5061029c61028836600461492a565b60066020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156102bc575f80fd5b506102c56108d1565b6040516102a89190614999565b3480156102dd575f80fd5b506102f16102ec3660046149bf565b610944565b6040519081526020016102a8565b34801561030a575f80fd5b5061031e6103193660046149ed565b61099e565b6040516001600160a01b0390911681526020016102a8565b348015610341575f80fd5b5061029c610350366004614a04565b610a14565b348015610360575f80fd5b5061037461036f366004614b02565b610a8f565b6040516102a893929190614b8f565b34801561038e575f80fd5b506103a261039d366004614c14565b610c11565b005b3480156103af575f80fd5b506102f17f000000000000000000000000000000000000000000000000000000000000000081565b3480156103e2575f80fd5b506103a26103f1366004614c43565b610c49565b348015610401575f80fd5b5061029c610410366004614c9c565b610ea6565b348015610420575f80fd5b5061031e7f000000000000000000000000000000000000000000000000000000000000000081565b348015610453575f80fd5b506103a2610f8a565b348015610467575f80fd5b506102f1610476366004614a04565b610fa6565b348015610486575f80fd5b5061048e5f81565b60405160ff90911681526020016102a8565b3480156104ab575f80fd5b5061031e7f000000000000000000000000000000000000000000000000000000000000000081565b3480156104de575f80fd5b5060075461031e906001600160a01b031681565b3480156104fd575f80fd5b506103a261050c366004614cda565b6110d4565b34801561051c575f80fd5b506103a261052b366004614c9c565b6111f3565b34801561053b575f80fd5b506102f160085481565b348015610550575f80fd5b506102f1600d5481565b348015610565575f80fd5b506102f16105743660046149ed565b611212565b348015610584575f80fd5b5061031e6105933660046149ed565b611267565b3480156105a3575f80fd5b506102f16105b2366004614c14565b6001600160a01b03165f9081526002602052604090205461ffff1690565b3480156105db575f80fd5b506105ef6105ea366004614c14565b61134f565b6040516102a89190614d5e565b348015610607575f80fd5b506103a26113f5565b34801561061b575f80fd5b50610624611ad8565b6040516102a89190614da1565b34801561063c575f80fd5b5061031e7f000000000000000000000000000000000000000000000000000000000000000081565b34801561066f575f80fd5b506102f160095481565b348015610684575f80fd5b506001546001600160a01b031661031e565b3480156106a1575f80fd5b50600a5461031e906001600160a01b031681565b3480156106c0575f80fd5b506102c5611b3b565b6103a26106d73660046149ed565b611b82565b3480156106e7575f80fd5b506103a26106f6366004614db3565b611c66565b348015610706575f80fd5b5061029c610715366004614a04565b611cd5565b348015610725575f80fd5b506103a2610734366004614e03565b611ce1565b348015610744575f80fd5b506102f167016345785d8a000081565b34801561075f575f80fd5b506102f1600b5481565b348015610774575f80fd5b5061029c610783366004614a04565b611d88565b348015610793575f80fd5b506102c56107a23660046149ed565b611e09565b3480156107b2575f80fd5b506103a26107c1366004614eaa565b611e77565b3480156107d1575f80fd5b506107e56107e0366004614ef6565b611e81565b6040516102a893929190614f17565b3480156107ff575f80fd5b506102f161080e366004614f4b565b6001600160a01b039182165f9081526002602081815260408084209490951683529201909152205490565b348015610844575f80fd5b5061029c610853366004614f4b565b6001600160a01b039182165f9081526002602090815260408083209390941682526003909201909152205460ff1690565b34801561088f575f80fd5b506103a261089e366004614c14565b611eb8565b3480156108ae575f80fd5b5061029c6108bd366004614c14565b600c6020525f908152604090205460ff1681565b600754604080516306fdde0360e01b815290516060926001600160a01b0316916306fdde03916004808301925f9291908290030181865afa158015610918573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261093f9190810190614f77565b905090565b5f7f00000000000000000000000000000000000000000000000000000000000000008310610970575f80fd5b506001600160a01b0381165f9081526002602090815260408083208584526001019091529020545b92915050565b5f7f0000000000000000000000000000000000000000000000000000000000000000821180156109f157507f00000000000000000000000000000000000000000000000000000000000000006002028211155b6109f9575f80fd5b505f908152600360205260409020546001600160a01b031690565b5f7f000000000000000000000000000000000000000000000000000000000000000082118015610a6757507f00000000000000000000000000000000000000000000000000000000000000006002028211155b15610a7b57610a768383611ef0565b610a86565b610a86338484611f9f565b50600192915050565b60608060605f85519050806001600160401b03811115610ab157610ab1614a2e565b604051908082528060200260200182016040528015610ada578160200160208202803683370190505b509350806001600160401b03811115610af557610af5614a2e565b604051908082528060200260200182016040528015610b1e578160200160208202803683370190505b509250806001600160401b03811115610b3957610b39614a2e565b604051908082528060200260200182016040528015610b6c57816020015b6060815260200190600190039081610b575790505b5091505f5b81811015610c0857610b9c878281518110610b8e57610b8e614fdf565b602002602001015187611e81565b878481518110610bae57610bae614fdf565b60200260200101878581518110610bc757610bc7614fdf565b60200260200101878681518110610be057610be0614fdf565b60209081029190910101929092526001600160a01b0392831690915291169052600101610b71565b50509250925092565b6001546001600160a01b03163314610c27575f80fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b5f7368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b031663791b98bc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c9a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cbe9190614ff3565b6040805160808101825260095481526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660208301526001600160801b038981168385015288166060830152915163fc6f786560e01b81529293509083169163fc6f786591610d389160040161500e565b60408051808303815f875af1158015610d53573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d779190615051565b50506040805160808101825260085481526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660208301526001600160801b038681168385015285166060830152915163fc6f786560e01b81529183169163fc6f786591610df09160040161500e565b60408051808303815f875af1158015610e0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e2f9190615051565b50507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663476343ee6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610e89575f80fd5b505af1158015610e9b573d5f803e3d5ffd5b505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000082118015610ef957507f00000000000000000000000000000000000000000000000000000000000000006002028211155b15610f0e57610f09848484612008565b610f80565b6001600160a01b0384165f908152600260208181526040808420338552909201905290205482811015610f3f575f80fd5b5f198114610f73576001600160a01b0385165f90815260026020818152604080842033855290920190529020805484900390555b610f7e8585856121c9565b505b5060019392505050565b610fa46001600160801b03806001600160801b0380610c49565b565b6001600160a01b0382165f9081526002602052604081205461ffff168210610fcc575f80fd5b6001600160a01b0383165f9081526002602052604081205464010000000090046001600160e01b03165b5f811180156110055750838211155b156110cc575f611014826123db565b9050806001901b821891505f61102a8288610944565b90505f61103682613928565b9050868186011161104a57938401936110c4565b815b5f8111801561105b5750878611155b156110c2575f61106a826123db565b60018881019890821b93909318929091508990036110bc57807f000000000000000000000000000000000000000000000000000000000000000086610100020101600101975050505050505050610998565b5061104c565b505b505050610ff6565b505092915050565b6001600160a01b0384165f908152600c602052604090205460ff16156110f8575f80fd5b6111758282808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040516bffffffffffffffffffffffff1960608a901b16602082015260348101889052605401915061115a9050565b604051602081830303815290604052805190602001206139f4565b61117d575f80fd5b6001600160a01b0384165f908152600c60205260409020805460ff191660011790556111aa3085856121c9565b836001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4846040516111e591815260200190565b60405180910390a250505050565b61120d83838360405180602001604052805f815250611ce1565b505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000821061123e575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000000160010190565b5f3363ffffffff811615611279575f80fd5b7f0000000000000000000000000000000000000000000000000000000000000000831180156112cb57507f00000000000000000000000000000000000000000000000000000000000000006002028311155b6112d3575f80fd5b5f806112de85613ab6565b60045491935091505f5b81811015611343575f6001600301828154811061130757611307614fdf565b5f918252602090912001546001600160a01b0316905083806113298784610944565b160361133a57979650505050505050565b506001016112e8565b505f9695505050505050565b60607f00000000000000000000000000000000000000000000000000000000000000006001600160401b0381111561138957611389614a2e565b6040519080825280602002602001820160405280156113b2578160200160208202803683370190505b5090505f5b81518110156113ef576113ca8184610944565b8282815181106113dc576113dc614fdf565b60209081029190910101526001016113b7565b50919050565b5f805460ff19166001179055600a546001600160a01b031615611416575f80fd5b5f3090505f7368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b0316634aa4a4fc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561146b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061148f9190614ff3565b90506114b282737a250d5630b4cf539739df2c5dacb4c659f2488d610100611f9f565b737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611502573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115269190614ff3565b6040516364e329cb60e11b81526001600160a01b0383811660048301528481166024830152919091169063c9c65396906044016020604051808303815f875af1158015611575573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115999190614ff3565b600a80546001600160a01b039283166001600160a01b0319909116179055737a250d5630b4cf539739df2c5dacb4c659f2488d9063f305d71990841631846101005f806115ee6001546001600160a01b031690565b60405160e088901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094526044840192909252606483015290911660848201524260a482015260c40160606040518083038185885af1158015611654573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906116799190615073565b5050505f7368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b031663791b98bc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f19190614ff3565b905061170b83826117066105006101006150b2565b611f9f565b6001600160a01b03808416908316105f611748826110007f0000000000000000000000000000000000000000000000000000000000000000613af3565b9150505f611764836110006a52b7d2dcc80cd2e4000000613af3565b915050836001600160a01b031663883164566040518061016001604052808661178d578961178f565b885b6001600160a01b0316815260200186156117a957896117ab565b885b6001600160a01b031681526127106020820152604001866117cc57856117ce565b845b60020b815260200186156117e257856117e4565b845b60020b8152602001866117f9576105006117fb565b5f5b8152602001861561180e57610500611810565b5f5b81526020015f81526020015f8152602001896001600160a01b03168152602001428152506040518263ffffffff1660e01b815260040161185091906150c5565b6080604051808303815f875af115801561186c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118909190615189565b5050506009556001600160a01b0386167318e5f92103d1b34623738ee79214b1659f2ee109109250611921836110007f00000000000000000000000000000000000000000000000000000000000000006119127f0000000000000000000000000000000000000000000000000000000000000000670de0b6b3a76400006151c4565b61191c91906151ef565b613af3565b925061196a9050836110007f00000000000000000000000000000000000000000000000000000000000000006119126a52b7d2dcc80cd2e4000000670de0b6b3a76400006151c4565b905080915050836001600160a01b031663883164566040518061016001604052808661199657896119ac565b7318e5f92103d1b34623738ee79214b1659f2ee1095b6001600160a01b0316815260200186156119c657896119dc565b7318e5f92103d1b34623738ee79214b1659f2ee1095b6001600160a01b031681526127106020820152604001866119fd57856119ff565b845b60020b81526020018615611a135785611a15565b845b60020b815260200186611a2a57610100611a2c565b5f5b81526020018615611a3f57610100611a41565b5f5b81526020015f81526020015f8152602001896001600160a01b03168152602001428152506040518263ffffffff1660e01b8152600401611a8191906150c5565b6080604051808303815f875af1158015611a9d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ac19190615189565b50505060085550505f805460ff1916905550505050565b60606001600301805480602002602001604051908101604052809291908181526020018280548015611b3157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611b13575b5050505050905090565b600754604080516395d89b4160e01b815290516060926001600160a01b0316916395d89b41916004808301925f9291908290030181865afa158015610918573d5f803e3d5ffd5b600d54811115611b90575f80fd5b5f611ba367016345785d8a0000836151c4565b905080341015611bb1575f80fd5b81600d5f828254611bc29190615202565b90915550611bd390503033846121c9565b6040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169082156108fc029083905f818181858888f19350505050158015611c26573d5f803e3d5ffd5b5080341115611c6257336108fc611c3d8334615202565b6040518115909202915f818181858888f1935050505015801561120d573d5f803e3d5ffd5b5050565b335f8181526002602090815260408083206001600160a01b0387168085526003909101835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b5f610a863384846121c9565b611cec848484612008565b823b63ffffffff811615611d8157604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290611d2e9033908a9089908990600401615215565b6020604051808303815f875af1158015611d4a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d6e9190615251565b6001600160e01b03191614611d81575f80fd5b5050505050565b5f7f000000000000000000000000000000000000000000000000000000000000000082118015611ddb57507f00000000000000000000000000000000000000000000000000000000000000006002028211155b611de3575f80fd5b5f80611dee84613ab6565b915091508081611dfe8488610944565b161495945050505050565b60075460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd906024015f60405180830381865afa158015611e50573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109989190810190614f77565b611c628282613b69565b5f80606083611e90575f611e99565b611e9985611267565b611ea28661099e565b611eab87611e09565b9250925092509250925092565b6001546001600160a01b03163314611ece575f80fd5b600780546001600160a01b0319166001600160a01b0392909216919091179055565b5f80611efb83613ab6565b915091508081611f0b8433610944565b1614611f15575f80fd5b5f83815260036020908152604080832080546001600160a01b0389166001600160a01b03199091168117909155338085526002909352818420805461ffff6201000080830482166001019091160263ffff000019909116179055905186939192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b6001600160a01b038084165f81815260026020818152604080842095881680855295909201815291819020859055805160608101909152602180825290916152c7908301398051906020012083604051611ffb91815260200190565b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000000008111801561205a57507f00000000000000000000000000000000000000000000000000000000000000006002028111155b612062575f80fd5b5f8061206d83613ab6565b91509150808161207d8488610944565b1614612087575f80fd5b336001600160a01b03861614806120b757506120a28361099e565b6001600160a01b0316336001600160a01b0316145b806120e757506001600160a01b0385165f90815260026020908152604080832033845260030190915290205460ff165b6120ef575f80fd5b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160401b0381111561212857612128614a2e565b604051908082528060200260200182016040528015612151578160200160208202803683370190505b5090508181848151811061216757612167614fdf565b60209081029190910101526040805160018082528183019092525f9181602001602082028036833701905050905084815f815181106121a8576121a8614fdf565b6020026020010181815250506121c087878484613cf4565b50505050505050565b5f80826001600160401b038111156121e3576121e3614a2e565b60405190808252806020026020018201604052801561220c578160200160208202803683370190505b5090505f7f00000000000000000000000000000000000000000000000000000000000000006001600160401b0381111561224857612248614a2e565b604051908082528060200260200182016040528015612271578160200160208202803683370190505b506001600160a01b0387165f9081526002602052604090205490915064010000000090046001600160e01b03165b5f811180156122ad57508484105b156123c4575f6122bc826123db565b9050806001901b821891505f6122d2828a610944565b9050805b5f811180156122e457508787105b1561237d575f6122f3826123db565b86519091506001821b90819088908790811061231157612311614fdf565b602002602001018181511791508181525050817f000000000000000000000000000000000000000000000000000000000000000086610100020101600101888a806001019b508151811061236757612367614fdf565b60209081029190910101529190911890506122d6565b84838151811061238f5761238f614fdf565b60200260200101518584815181106123a9576123a9614fdf565b60200260200101518316146123bc575f80fd5b50505061229f565b8484146123cf575f80fd5b6121c087878486613cf4565b5f5f198201198216600160801b811015612eb4576801000000000000000081101561292d5764010000000081101561266a576201000081101561252d5761010081101561249f576010811015612460576004811015612445576002811015610a8657505f92915050565b60088110156124575750600292915050565b50600392915050565b604081101561248457602081101561247b5750600492915050565b50600592915050565b60808110156124965750600692915050565b50600792915050565b6110008110156124eb576104008110156124cf576102008110156124c65750600892915050565b50600992915050565b6108008110156124e25750600a92915050565b50600b92915050565b614000811015612511576120008110156125085750600c92915050565b50600d92915050565b6180008110156125245750600e92915050565b50600f92915050565b63010000008110156125ce5762100000811015612589576204000081101561256c57620200008110156125635750601092915050565b50601192915050565b620800008110156125805750601292915050565b50601392915050565b624000008110156125b157622000008110156125a85750601492915050565b50601592915050565b628000008110156125c55750601692915050565b50601792915050565b63100000008110156126225763040000008110156126045763020000008110156125fb5750601892915050565b50601992915050565b63080000008110156126195750601a92915050565b50601b92915050565b634000000081101561264c5763200000008110156126435750601c92915050565b50601d92915050565b63800000008110156126615750601e92915050565b50601f92915050565b66010000000000008110156127d4576501000000000081101561272a576410000000008110156126df576404000000008110156126c0576402000000008110156126b75750602092915050565b50602192915050565b6408000000008110156126d65750602292915050565b50602392915050565b64400000000081101561270b576420000000008110156127025750602492915050565b50602592915050565b6480000000008110156127215750602692915050565b50602792915050565b651000000000008110156127865765040000000000811015612766576502000000000081101561275d5750602892915050565b50602992915050565b6508000000000081101561277d5750602a92915050565b50602b92915050565b654000000000008110156127b457652000000000008110156127ab5750602c92915050565b50602d92915050565b658000000000008110156127cb5750602e92915050565b50602f92915050565b600160381b81101561289157661000000000000081101561284057660400000000000081101561281f5766020000000000008110156128165750603092915050565b50603192915050565b66080000000000008110156128375750603292915050565b50603392915050565b66400000000000008110156128705766200000000000008110156128675750603492915050565b50603592915050565b66800000000000008110156128885750603692915050565b50603792915050565b6001603c1b8110156128e5576001603a1b8110156128c757600160391b8110156128be5750603892915050565b50603992915050565b6001603b1b8110156128dc5750603a92915050565b50603b92915050565b6001603e1b81101561290f576001603d1b8110156129065750603c92915050565b50603d92915050565b6001603f1b8110156129245750603e92915050565b50603f92915050565b600160601b811015612c2057600160501b811015612adc576901000000000000000000811015612a1657681000000000000000008110156129bf576804000000000000000081101561299c57680200000000000000008110156129935750604092915050565b50604192915050565b680800000000000000008110156129b65750604292915050565b50604392915050565b684000000000000000008110156129f357682000000000000000008110156129ea5750604492915050565b50604592915050565b68800000000000000000811015612a0d5750604692915050565b50604792915050565b6910000000000000000000811015612a82576904000000000000000000811015612a5e576902000000000000000000811015612a555750604892915050565b50604992915050565b6908000000000000000000811015612a795750604a92915050565b50604b92915050565b6940000000000000000000811015612ab8576920000000000000000000811015612aaf5750604c92915050565b50604d92915050565b6980000000000000000000811015612ad35750604e92915050565b50604f92915050565b600160581b811015612b8457600160541b811015612b3c57600160521b811015612b1e57600160511b811015612b155750605092915050565b50605192915050565b600160531b811015612b335750605292915050565b50605392915050565b600160561b811015612b6657600160551b811015612b5d5750605492915050565b50605592915050565b600160571b811015612b7b5750605692915050565b50605792915050565b6001605c1b811015612bd8576001605a1b811015612bba57600160591b811015612bb15750605892915050565b50605992915050565b6001605b1b811015612bcf5750605a92915050565b50605b92915050565b6001605e1b811015612c02576001605d1b811015612bf95750605c92915050565b50605d92915050565b6001605f1b811015612c175750605e92915050565b50605f92915050565b600160701b811015612d7057600160681b811015612cd457600160641b811015612c8c57600160621b811015612c6e57600160611b811015612c655750606092915050565b50606192915050565b600160631b811015612c835750606292915050565b50606392915050565b600160661b811015612cb657600160651b811015612cad5750606492915050565b50606592915050565b600160671b811015612ccb5750606692915050565b50606792915050565b6001606c1b811015612d28576001606a1b811015612d0a57600160691b811015612d015750606892915050565b50606992915050565b6001606b1b811015612d1f5750606a92915050565b50606b92915050565b6001606e1b811015612d52576001606d1b811015612d495750606c92915050565b50606d92915050565b6001606f1b811015612d675750606e92915050565b50606f92915050565b600160781b811015612e1857600160741b811015612dd057600160721b811015612db257600160711b811015612da95750607092915050565b50607192915050565b600160731b811015612dc75750607292915050565b50607392915050565b600160761b811015612dfa57600160751b811015612df15750607492915050565b50607592915050565b600160771b811015612e0f5750607692915050565b50607792915050565b6001607c1b811015612e6c576001607a1b811015612e4e57600160791b811015612e455750607892915050565b50607992915050565b6001607b1b811015612e635750607a92915050565b50607b92915050565b6001607e1b811015612e96576001607d1b811015612e8d5750607c92915050565b50607d92915050565b6001607f1b811015612eab5750607e92915050565b50607f92915050565b600160c01b8110156133f457600160a01b81101561316057600160901b81101561301c57600160881b811015612f8057600160841b811015612f3857600160821b811015612f1a57600160811b811015612f115750608092915050565b50608192915050565b600160831b811015612f2f5750608292915050565b50608392915050565b600160861b811015612f6257600160851b811015612f595750608492915050565b50608592915050565b600160871b811015612f775750608692915050565b50608792915050565b6001608c1b811015612fd4576001608a1b811015612fb657600160891b811015612fad5750608892915050565b50608992915050565b6001608b1b811015612fcb5750608a92915050565b50608b92915050565b6001608e1b811015612ffe576001608d1b811015612ff55750608c92915050565b50608d92915050565b6001608f1b8110156130135750608e92915050565b50608f92915050565b600160981b8110156130c457600160941b81101561307c57600160921b81101561305e57600160911b8110156130555750609092915050565b50609192915050565b600160931b8110156130735750609292915050565b50609392915050565b600160961b8110156130a657600160951b81101561309d5750609492915050565b50609592915050565b600160971b8110156130bb5750609692915050565b50609792915050565b6001609c1b811015613118576001609a1b8110156130fa57600160991b8110156130f15750609892915050565b50609992915050565b6001609b1b81101561310f5750609a92915050565b50609b92915050565b6001609e1b811015613142576001609d1b8110156131395750609c92915050565b50609d92915050565b6001609f1b8110156131575750609e92915050565b50609f92915050565b600160b01b8110156132b057600160a81b81101561321457600160a41b8110156131cc57600160a21b8110156131ae57600160a11b8110156131a5575060a092915050565b5060a192915050565b600160a31b8110156131c3575060a292915050565b5060a392915050565b600160a61b8110156131f657600160a51b8110156131ed575060a492915050565b5060a592915050565b600160a71b81101561320b575060a692915050565b5060a792915050565b600160ac1b81101561326857600160aa1b81101561324a57600160a91b811015613241575060a892915050565b5060a992915050565b600160ab1b81101561325f575060aa92915050565b5060ab92915050565b600160ae1b81101561329257600160ad1b811015613289575060ac92915050565b5060ad92915050565b600160af1b8110156132a7575060ae92915050565b5060af92915050565b600160b81b81101561335857600160b41b81101561331057600160b21b8110156132f257600160b11b8110156132e9575060b092915050565b5060b192915050565b600160b31b811015613307575060b292915050565b5060b392915050565b600160b61b81101561333a57600160b51b811015613331575060b492915050565b5060b592915050565b600160b71b81101561334f575060b692915050565b5060b792915050565b600160bc1b8110156133ac57600160ba1b81101561338e57600160b91b811015613385575060b892915050565b5060b992915050565b600160bb1b8110156133a3575060ba92915050565b5060bb92915050565b600160be1b8110156133d657600160bd1b8110156133cd575060bc92915050565b5060bd92915050565b600160bf1b8110156133eb575060be92915050565b5060bf92915050565b600160e01b81101561369457600160d01b81101561355057600160c81b8110156134b457600160c41b81101561346c57600160c21b81101561344e57600160c11b811015613445575060c092915050565b5060c192915050565b600160c31b811015613463575060c292915050565b5060c392915050565b600160c61b81101561349657600160c51b81101561348d575060c492915050565b5060c592915050565b600160c71b8110156134ab575060c692915050565b5060c792915050565b600160cc1b81101561350857600160ca1b8110156134ea57600160c91b8110156134e1575060c892915050565b5060c992915050565b600160cb1b8110156134ff575060ca92915050565b5060cb92915050565b600160ce1b81101561353257600160cd1b811015613529575060cc92915050565b5060cd92915050565b600160cf1b811015613547575060ce92915050565b5060cf92915050565b600160d81b8110156135f857600160d41b8110156135b057600160d21b81101561359257600160d11b811015613589575060d092915050565b5060d192915050565b600160d31b8110156135a7575060d292915050565b5060d392915050565b600160d61b8110156135da57600160d51b8110156135d1575060d492915050565b5060d592915050565b600160d71b8110156135ef575060d692915050565b5060d792915050565b600160dc1b81101561364c57600160da1b81101561362e57600160d91b811015613625575060d892915050565b5060d992915050565b600160db1b811015613643575060da92915050565b5060db92915050565b600160de1b81101561367657600160dd1b81101561366d575060dc92915050565b5060dd92915050565b600160df1b81101561368b575060de92915050565b5060df92915050565b600160f01b8110156137e457600160e81b81101561374857600160e41b81101561370057600160e21b8110156136e257600160e11b8110156136d9575060e092915050565b5060e192915050565b600160e31b8110156136f7575060e292915050565b5060e392915050565b600160e61b81101561372a57600160e51b811015613721575060e492915050565b5060e592915050565b600160e71b81101561373f575060e692915050565b5060e792915050565b600160ec1b81101561379c57600160ea1b81101561377e57600160e91b811015613775575060e892915050565b5060e992915050565b600160eb1b811015613793575060ea92915050565b5060eb92915050565b600160ee1b8110156137c657600160ed1b8110156137bd575060ec92915050565b5060ed92915050565b600160ef1b8110156137db575060ee92915050565b5060ef92915050565b600160f81b81101561388c57600160f41b81101561384457600160f21b81101561382657600160f11b81101561381d575060f092915050565b5060f192915050565b600160f31b81101561383b575060f292915050565b5060f392915050565b600160f61b81101561386e57600160f51b811015613865575060f492915050565b5060f592915050565b600160f71b811015613883575060f692915050565b5060f792915050565b600160fc1b8110156138e057600160fa1b8110156138c257600160f91b8110156138b9575060f892915050565b5060f992915050565b600160fb1b8110156138d7575060fa92915050565b5060fb92915050565b600160fe1b81101561390a57600160fd1b811015613901575060fc92915050565b5060fd92915050565b600160ff1b81101561391f575060fe92915050565b5060ff92915050565b5f8180820361393957505f92915050565b5f19810361394b575061010092915050565b7f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f5555555555555555555555555555555555555555555555555555555555555555600183901c16909103600281901c7f3333333333333333333333333333333333333333333333333333333333333333908116911601600481901c01167f01010101010101010101010101010101010101010101010101010101010101010260f81c92915050565b5f81815b8451811015613a8c575f858281518110613a1457613a14614fdf565b60200260200101519050808311613a56576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250613a83565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b506001016139f8565b507f3f856c8d1611023aaa9915c692b07293eea0d4dd7c26df3914d5bfbd430ce84c149392505050565b6101005f197f0000000000000000000000000000000000000000000000000000000000000000808403820183900494600193860290940303011b90565b5f805f613b3186613b045784613b06565b855b8715613b125785613b14565b865b613b2290600160c01b6151ef565b613b2c91906151c4565b6140dd565b9050613b3c8161411a565b9150613b4960c88361526c565b613b53908361528d565b9150613b5e82614416565b925050935093915050565b5f7f00000000000000000000000000000000000000000000000000000000000000006001600160401b03811115613ba257613ba2614a2e565b604051908082528060200260200182016040528015613bcb578160200160208202803683370190505b5090505f5b8251811015613c2f575f80613bfd858481518110613bf057613bf0614fdf565b6020026020010151613ab6565b9150915080848381518110613c1457613c14614fdf565b60209081029190910101805190911790525050600101613bd0565b505f805b8251811015613cd557828181518110613c4e57613c4e614fdf565b60200260200101515f801b14613ccd57828181518110613c7057613c70614fdf565b6020026020010151838281518110613c8a57613c8a614fdf565b6020026020010151613c9c8333610944565b1614613ca6575f80fd5b613cc8838281518110613cbb57613cbb614fdf565b6020026020010151613928565b820191505b600101613c33565b5082518114613ce2575f80fd5b613cee33858486613cf4565b50505050565b6001600160a01b038316613d06575f80fd5b5f815111613d12575f80fd5b613d1e84848484614744565b6001600160a01b038085165f908152600260205260408082205492861682528120546001600160e01b036401000000009384900481169390910416905b8451811015613e5e575f801b858281518110613d7957613d79614fdf565b602002602001015114613e56575f613d918289610944565b9050858281518110613da557613da5614fdf565b6020908102919091018101516001600160a01b038a165f908152600283526040808220868352600101909352918220921891829055613de48389610944565b9050868381518110613df857613df8614fdf565b6020908102919091018101516001600160a01b038a165f908152600283526040808220878352600101909352918220921791829055829003613e3e57826001901b851894505b6001831b939093179281811615613e53575f80fd5b50505b600101613d5b565b506001600160a01b038681165f908152600260205260408082208054875161ffff8083169190910380821663ffff0000938416176401000000006001600160e01b038b8116820292909217909555968c16865293852080548a5197891690940292841693821696870190911692909217179055919082900361401f576001600160a01b0388165f9081526005602052604081205490829003613f4e578760016003018281548110613f1157613f11614fdf565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918a168152600590915260409020819055614001565b600480545f91905f198101908110613f6857613f68614fdf565b5f91825260209091200154600480546001600160a01b039092169250829184908110613f9657613f96614fdf565b5f91825260208083209190910180546001600160a01b0319166001600160a01b0394851617905591831681526005909152604090208290556004805480613fdf57613fdf6152b2565b5f8281526020902081015f1990810180546001600160a01b0319169055019055505b506001600160a01b0388165f90815260056020526040812055614086565b805f0361408657600480546001810182557f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038a1690811790915590545f918252600560205260409091205f1990910190555b866001600160a01b0316886001600160a01b03166040518060600160405280602181526020016152e8602191398051906020012087516040516140cb91815260200190565b60405180910390a35050505050505050565b80600260018201045b818110156113ef57809150600281828581614103576141036151db565b040181614112576141126151db565b0490506140e6565b5f6401000276a36001600160a01b03831610801590614155575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61418a5760405162461bcd60e51b81526020600482015260016024820152602960f91b60448201526064015b60405180910390fd5b640100000000600160c01b03602083901b166001600160801b03811160071b81811c6001600160401b03811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c9790881196179094179092171790911717176080811061421d57607f810383901c9150614227565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c6001603f1b161760c19b909b1c6001603e1b169a909a1760c29990991c6001603d1b169890981760c39790971c6001603c1b169690961760c49590951c6001603b1b169490941760c59390931c6001603a1b169290921760c69190911c600160391b161760c79190911c600160381b161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b1461440757886001600160a01b03166143ec82614416565b6001600160a01b031611156144015781614409565b80614409565b815b9998505050505050505050565b5f805f8360020b1261442b578260020b614432565b8260020b5f035b9050620d89e881111561446b5760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401614181565b5f816001165f0361448057600160801b614492565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156144c6576ffff97272373d413259a46990580e213a0260801c5b60048216156144e5576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615614504576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615614523576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615614542576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615614561576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615614580576ffe5dee046a99a2a811c461f1969c30530260801c5b6101008216156145a0576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156145c0576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156145e0576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615614600576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615614620576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615614640576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615614660576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615614680576f31be135f97d08fd981231505542fcfa60260801c5b620100008216156146a1576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156146c1576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156146e0576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156146fd576b048a170391f7dc42444e8fa20260801c5b5f8460020b131561471c57805f1981614718576147186151db565b0490505b640100000000810615614730576001614732565b5f5b60ff16602082901c0192505050919050565b5f80546001600160a01b0386168252600260205260409091205460ff9091169062010000900461ffff16158080156147795750815b61490a575f5b83518110156121c057811580156147c957505f6001600160a01b03166147bd8583815181106147b0576147b0614fdf565b602002602001015161099e565b6001600160a01b031614155b156148a2576001600160a01b0387165f90815260026020526040812080545f1961ffff62010000808404821692909201160263ffff0000199091161790558451600390829087908590811061482057614820614fdf565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555083818151811061486a5761486a614fdf565b60209081029190910101516040515f9081907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908290a45b82614902578381815181106148b9576148b9614fdf565b6020026020010151866001600160a01b0316886001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b60010161477f565b505050505050565b6001600160e01b031981168114614927575f80fd5b50565b5f6020828403121561493a575f80fd5b813561494581614912565b9392505050565b5f5b8381101561496657818101518382015260200161494e565b50505f910152565b5f815180845261498581602086016020860161494c565b601f01601f19169290920160200192915050565b602081525f614945602083018461496e565b6001600160a01b0381168114614927575f80fd5b5f80604083850312156149d0575f80fd5b8235915060208301356149e2816149ab565b809150509250929050565b5f602082840312156149fd575f80fd5b5035919050565b5f8060408385031215614a15575f80fd5b8235614a20816149ab565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715614a6a57614a6a614a2e565b604052919050565b5f82601f830112614a81575f80fd5b813560206001600160401b03821115614a9c57614a9c614a2e565b8160051b614aab828201614a42565b9283528481018201928281019087851115614ac4575f80fd5b83870192505b84831015614ae357823582529183019190830190614aca565b979650505050505050565b80358015158114614afd575f80fd5b919050565b5f8060408385031215614b13575f80fd5b82356001600160401b03811115614b28575f80fd5b614b3485828601614a72565b925050614b4360208401614aee565b90509250929050565b5f815180845260208085019450602084015f5b83811015614b845781516001600160a01b031687529582019590820190600101614b5f565b509495945050505050565b606081525f614ba16060830186614b4c565b602083820381850152614bb48287614b4c565b915083820360408501528185518084528284019150828160051b8501018388015f5b83811015614c0457601f19878403018552614bf283835161496e565b94860194925090850190600101614bd6565b50909a9950505050505050505050565b5f60208284031215614c24575f80fd5b8135614945816149ab565b6001600160801b0381168114614927575f80fd5b5f805f8060808587031215614c56575f80fd5b8435614c6181614c2f565b93506020850135614c7181614c2f565b92506040850135614c8181614c2f565b91506060850135614c9181614c2f565b939692955090935050565b5f805f60608486031215614cae575f80fd5b8335614cb9816149ab565b92506020840135614cc9816149ab565b929592945050506040919091013590565b5f805f8060608587031215614ced575f80fd5b8435614cf8816149ab565b93506020850135925060408501356001600160401b0380821115614d1a575f80fd5b818701915087601f830112614d2d575f80fd5b813581811115614d3b575f80fd5b8860208260051b8501011115614d4f575f80fd5b95989497505060200194505050565b602080825282518282018190525f9190848201906040850190845b81811015614d9557835183529284019291840191600101614d79565b50909695505050505050565b602081525f6149456020830184614b4c565b5f8060408385031215614dc4575f80fd5b8235614dcf816149ab565b9150614b4360208401614aee565b5f6001600160401b03821115614df557614df5614a2e565b50601f01601f191660200190565b5f805f8060808587031215614e16575f80fd5b8435614e21816149ab565b93506020850135614e31816149ab565b92506040850135915060608501356001600160401b03811115614e52575f80fd5b8501601f81018713614e62575f80fd5b8035614e75614e7082614ddd565b614a42565b818152886020838501011115614e89575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f8060408385031215614ebb575f80fd5b8235614ec6816149ab565b915060208301356001600160401b03811115614ee0575f80fd5b614eec85828601614a72565b9150509250929050565b5f8060408385031215614f07575f80fd5b82359150614b4360208401614aee565b6001600160a01b038481168252831660208201526060604082018190525f90614f429083018461496e565b95945050505050565b5f8060408385031215614f5c575f80fd5b8235614f67816149ab565b915060208301356149e2816149ab565b5f60208284031215614f87575f80fd5b81516001600160401b03811115614f9c575f80fd5b8201601f81018413614fac575f80fd5b8051614fba614e7082614ddd565b818152856020838501011115614fce575f80fd5b614f4282602083016020860161494c565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215615003575f80fd5b8151614945816149ab565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b5f8060408385031215615062575f80fd5b505080516020909101519092909150565b5f805f60608486031215615085575f80fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b5f52601160045260245ffd5b808201808211156109985761099861509e565b81516001600160a01b03168152610160810160208301516150f160208401826001600160a01b03169052565b506040830151615108604084018262ffffff169052565b50606083015161511d606084018260020b9052565b506080830151615132608084018260020b9052565b5060a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151615178828501826001600160a01b03169052565b505061014092830151919092015290565b5f805f806080858703121561519c575f80fd5b8451935060208501516151ae81614c2f565b6040860151606090960151949790965092505050565b80820281158282048414176109985761099861509e565b634e487b7160e01b5f52601260045260245ffd5b5f826151fd576151fd6151db565b500490565b818103818111156109985761099861509e565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f906152479083018461496e565b9695505050505050565b5f60208284031215615261575f80fd5b815161494581614912565b5f8260020b8061527e5761527e6151db565b808360020b0791505092915050565b600282810b9082900b03627fffff198112627fffff821317156109985761099861509e565b634e487b7160e01b5f52603160045260245ffdfe417070726f76616c28616464726573732c616464726573732c75696e74323536295472616e7366657228616464726573732c616464726573732c75696e7432353629a264697066735822122069d46335cf5f96540b8e9eb83f90e3f81428e4e7c384d4ff3c208ef923e6acea64736f6c6343000818003360a060405234801561000f575f80fd5b503360805261003373faded72464d6e76e37300b467673b36ecc4d2ccf6004610057565b61005273ec513e5959dbb02f314fc2f30041fca2685119f36001610057565b61012a565b604080518082019091526001600160a01b038381168252602082018381525f80546001808201835582805294517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563600290920291820180546001600160a01b031916919095161790935590517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e564909201919091558154839291906100fc908490610105565b90915550505050565b8082018082111561012457634e487b7160e01b5f52601160045260245ffd5b92915050565b6080516107e96101505f395f8181610150015281816101b4015261044d01526107e95ff3fe608060405260043610610071575f3560e01c806357a858fc1161004c57806357a858fc146100ce578063894760691461010c578063e086e5ec1461012b578063fc0c546a1461013f575f80fd5b80633a98ef391461007c578063476343ee146100a45780634c02f62e146100ba575f80fd5b3661007857005b5f80fd5b348015610087575f80fd5b5061009160015481565b6040519081526020015b60405180910390f35b3480156100af575f80fd5b506100b861018a565b005b3480156100c5575f80fd5b506100b86101da565b3480156100d9575f80fd5b506100ed6100e83660046106b9565b610251565b604080516001600160a01b03909316835260208301919091520161009b565b348015610117575f80fd5b506100b86101263660046106e4565b610286565b348015610136575f80fd5b506100b861061b565b34801561014a575f80fd5b506101727f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161009b565b6101926101da565b6101af7318e5f92103d1b34623738ee79214b1659f2ee109610286565b6101d87f0000000000000000000000000000000000000000000000000000000000000000610286565b565b6101d87368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b0316634aa4a4fc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561022d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101269190610706565b5f818154811061025f575f80fd5b5f918252602090912060029091020180546001909101546001600160a01b03909116915082565b5f7368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b0316634aa4a4fc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102d7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102fb9190610706565b9050806001600160a01b0316826001600160a01b0316036103db576040516370a0823160e01b81523060048201526001600160a01b03821690632e1a7d4d9082906370a0823190602401602060405180830381865afa158015610360573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103849190610721565b6040518263ffffffff1660e01b81526004016103a291815260200190565b5f604051808303815f87803b1580156103b9575f80fd5b505af11580156103cb573d5f803e3d5ffd5b505050506103d761061b565b5050565b6040516370a0823160e01b81523060048201525f906001600160a01b038416906370a0823190602401602060405180830381865afa15801561041f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104439190610721565b90508015610616577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b03160361052957826001600160a01b031663a9059cbb5f80815481106104a5576104a5610738565b5f91825260209091206002909102015460405160e083901b6001600160e01b03191681526001600160a01b039091166004820152602481018490526044016020604051808303815f875af11580156104ff573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610523919061074c565b50505050565b5f5b5f54811015610523575f80828154811061054757610547610738565b5f9182526020918290206040805180820190915260029092020180546001600160a01b03908116808452600192830154948401859052915492945088169263a9059cbb9290610596908861076b565b6105a09190610794565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af11580156105e8573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061060c919061074c565b505060010161052b565b505050565b4780156106b6575f5b5f548110156103d7575f80828154811061064057610640610738565b5f9182526020918290206040805180820190915260029092020180546001600160a01b03168083526001918201549383018490529054919350916108fc9190610689908761076b565b6106939190610794565b6040518115909202915f818181858888f150506001909401935061062492505050565b50565b5f602082840312156106c9575f80fd5b5035919050565b6001600160a01b03811681146106b6575f80fd5b5f602082840312156106f4575f80fd5b81356106ff816106d0565b9392505050565b5f60208284031215610716575f80fd5b81516106ff816106d0565b5f60208284031215610731575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b5f6020828403121561075c575f80fd5b815180151581146106ff575f80fd5b808202811582820484141761078e57634e487b7160e01b5f52601160045260245ffd5b92915050565b5f826107ae57634e487b7160e01b5f52601260045260245ffd5b50049056fea26469706673582212207b700e3a7e46284f5e69ec5d328c765a875a3a15be5550aa30646655cfe2fec664736f6c6343000818003360e0604052600f60a09081526e105d5d1bdb585d1bdb9cc81e139195608a1b60c0525f906200002f908262000d58565b506040805180820190915260048152634155544f60e01b60208201526001906200005a908262000d58565b5034801562000067575f80fd5b50336080908152604080518082018252601081526014602080830191825260028054600181810183555f8381529551945160ff908116600160f81b9081026001600160f81b03978816177f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace948501558851808a018a5286815260c881880190815286548086018855878b52915190518416830290891617908501558851808a018a5260308152607881880190815286548086018855878b52915190518416830290891617908501558851808a018a52898152603281880190815286548086018855878b52915190518416830290891617908501558851808a018a526060808252600a82890190815287548087018955888c529251905185168402908a1617918601919091558951808b018b528b815280880185815287548087018955888c52915190519094169092029290971691909117920191909155855196870186526001600160e81b03198752868301858152610c808888019081528751808901909852600b88526a436c65616e20576869746560a81b94880194909452938701958652600380549182018155909452855193025f8051602062002cf4833981519152810180549351925161ffff1666010000000000000261ffff60301b1960e894851c63010000000265ffffffffffff199096169690941c95909517939093179190911692909217815591515f8051602062002cd4833981519152909101906200028f908262000d58565b5050604080516080810182525f8082526001600160e81b031960208084019182526103208486019081528551808701909652600a8652694465657020426c61636b60b01b9186019190915260608401948552600380546001810182559352835160029093025f8051602062002cf4833981519152810180549351925161ffff1666010000000000000261ffff60301b1960e894851c63010000000265ffffffffffff199096169690941c95909517939093179190911692909217815592519193505f8051602062002cd483398151915201906200036d908262000d58565b5050604080516080810182526217962960e81b81526215491f60e81b602080830191825260648385019081528451808601909552600b85526a29b634b6bc9023b932b2b760a91b9185019190915260608301938452600380546001810182555f91909152835160029091025f8051602062002cf4833981519152810180549451935161ffff1666010000000000000261ffff60301b1960e895861c63010000000265ffffffffffff199097169490951c9390931794909417929092161782559251919350915f8051602062002cd483398151915201906200044f908262000d58565b50506040805160808101825262326a4760ea1b81526202fa8960ed1b6020808301918252604b8385019081528451808601909552600c85526b5061636966696320426c756560a01b9185019190915260608301938452600380546001810182555f91909152835160029091025f8051602062002cf4833981519152810180549451935161ffff1666010000000000000261ffff60301b1960e895861c63010000000265ffffffffffff199097169490951c9390931794909417929092161782559251919350915f8051602062002cd4833981519152019062000532908262000d58565b505060408051608081018252619fff60e81b815262144d7960e81b602080830191825260378385019081528451808601909552600b85526a13dc985b99d9481419595b60aa1b9185019190915260608301938452600380546001810182555f91909152835160029091025f8051602062002cf4833981519152810180549451935161ffff1666010000000000000261ffff60301b1960e895861c63010000000265ffffffffffff199097169490951c9390931794909417929092161782559251919350915f8051602062002cd4833981519152019062000613908262000d58565b505060408051608081018252623bb5cf60e81b81526223576360e81b602080830191825260238385019081528451808601909552600885526713db190811dbdb1960c21b9185019190915260608301938452600380546001810182555f91909152835160029091025f8051602062002cf4833981519152810180549451935161ffff1666010000000000000261ffff60301b1960e895861c63010000000265ffffffffffff199097169490951c9390931794909417929092161782559251919350915f8051602062002cd48339815191520190620006f2908262000d58565b5050604080516080810182526209080760ec1b81526208c7e760eb1b602080830191825260198385019081528451808601909552600a855269536c617465204772617960b01b9185019190915260608301938452600380546001810182555f91909152835160029091025f8051602062002cf4833981519152810180549451935161ffff1666010000000000000261ffff60301b1960e895861c63010000000265ffffffffffff199097169490951c9390931794909417929092161782559251919350915f8051602062002cd48339815191520190620007d3908262000d58565b505060408051608081018252625647f360e91b81526253466d60e81b6020808301918252600f8385019081528451808601909552600a855269436861726d2050696e6b60b01b9185019190915260608301938452600380546001810182555f91909152835160029091025f8051602062002cf4833981519152810180549451935161ffff1666010000000000000261ffff60301b1960e895861c63010000000265ffffffffffff199097169490951c9390931794909417929092161782559251919350915f8051602062002cd48339815191520190620008b4908262000d58565b5050604080516080810182526215965360e91b8152620c8ea960e91b6020808301918252600a8385019081528451808601909552600c85526b13595d185b1b1a58c814995960a21b9185019190915260608301938452600380546001810182555f91909152835160029091025f8051602062002cf4833981519152810180549451935161ffff1666010000000000000261ffff60301b1960e895861c63010000000265ffffffffffff199097169490951c9390931794909417929092161782559251919350915f8051602062002cd4833981519152019062000997908262000d58565b50506040805160808101825262152a2f60eb1b815262522b3d60e81b602080830191825260058385019081528451808601909552600c85526b526f79616c20507572706c6560a01b9185019190915260608301938452600380546001810182555f91909152835160029091025f8051602062002cf4833981519152810180549451935161ffff1666010000000000000261ffff60301b1960e895861c63010000000265ffffffffffff199097169490951c9390931794909417929092161782559251919350915f8051602062002cd4833981519152019062000a7a908262000d58565b50506040805180820182526028815281518083019092526004808352634e6f6e6560e01b602080850191909152820192835280546001810182555f9190915281515f8051602062002d348339815191526002909202918201805460ff191660ff90921691909117815592519193505f8051602062002d14833981519152019062000b05908262000d58565b505060408051808201825260148152815180830190925260088252672937ba30ba34b7b760c11b6020808401919091528101918252600480546001810182555f9190915281515f8051602062002d348339815191526002909202918201805460ff191660ff90921691909117815592519193505f8051602062002d14833981519152019062000b95908262000d58565b5050604080518082018252600a81528151808301909252600682526553696e676c6560d01b6020808401919091528101918252600480546001810182555f9190915281515f8051602062002d348339815191526002909202918201805460ff191660ff90921691909117815592519193505f8051602062002d14833981519152019062000c23908262000d58565b50506040805180820182526005815281518083019092526006825265446f75626c6560d01b6020808401919091528101918252600480546001810182555f9190915281515f8051602062002d348339815191526002909202918201805460ff191660ff90921691909117815592519193505f8051602062002d14833981519152019062000cb1908262000d58565b50505062000e24565b634e487b7160e01b5f52604160045260245ffd5b600181811c9082168062000ce357607f821691505b60208210810362000d0257634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111562000d5357805f5260205f20601f840160051c8101602085101562000d2f5750805b601f840160051c820191505b8181101562000d50575f815560010162000d3b565b50505b505050565b81516001600160401b0381111562000d745762000d7462000cba565b62000d8c8162000d85845462000cce565b8462000d08565b602080601f83116001811462000dc2575f841562000daa5750858301515b5f19600386901b1c1916600185901b17855562000e1c565b5f85815260208120601f198616915b8281101562000df25788860151825594840194600190910190840162000dd1565b508582101562000e1057878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b608051611e9162000e435f395f818160c101526103220152611e915ff3fe608060405234801561000f575f80fd5b506004361061008f575f3560e01c80638c7a63ae116100635780638c7a63ae1461011657806395d89b4114610156578063be985ac91461015e578063c87b56dd14610171578063ca54cc3f14610184575f80fd5b8062b958f31461009357806305c5652b146100bc57806306fdde03146100fb57806348b62fe414610103575b5f80fd5b6100a66100a136600461159d565b610197565b6040516100b39190611601565b60405180910390f35b6100e37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016100b3565b6100a66101d0565b6100a661011136600461159d565b61025b565b61012961012436600461159d565b61031a565b6040805195865263ffffffff9094166020860152928401919091526060830152608082015260a0016100b3565b6100a6610544565b6100a661016c36600461159d565b610551565b6100a661017f36600461159d565b6105c2565b6100a661019236600461159d565b61073a565b60606101aa6101a58361025b565b610758565b6040516020016101ba9190611635565b6040516020818303038152906040529050919050565b5f80546101dc90611672565b80601f016020809104026020016040519081016040528092919081815260200182805461020890611672565b80156102535780601f1061022a57610100808354040283529160200191610253565b820191905f5260205f20905b81548152906001019060200180831161023657829003601f168201915b505050505081565b60605f805f805f61026b8761031a565b9450945094509450945061030f6102d86003848154811061028e5761028e6116a4565b5f9182526020909120600290910201546003805460e89290921b91869081106102b9576102b96116a4565b5f9182526020909120600290910201546301000000900460e81b6108a2565b6102ec6102e7888888876108e5565b610c3b565b6102f586610d72565b6103009060026116cc565b61030a90876116e3565b610d7e565b979650505050505050565b5f805f805f857f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663bfa0b1336040518163ffffffff1660e01b8152600401602060405180830381865afa15801561037c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103a091906116f6565b6040516429b2b2b21d60d91b6020820152602581019290925260458201526065016040516020818303038152906040528051906020012094506103e161157e565b5f5b602081101561040c57808282602081106103ff576103ff6116a4565b60200201526001016103e3565b505f5b600d8110156104e4575f81602003828960405160200161044c9291906729b43ab33336329d60c11b81526008810192909252602882015260480190565b604051602081830303815290604052805190602001205f1c816104715761047161170d565b06820190505f838260208110610489576104896116a4565b602002015190508383602081106104a2576104a26116a4565b60200201518483602081106104b9576104b96116a4565b602002018181525050808484602081106104d5576104d56116a4565b6020020152505060010161040f565b505f5b600d81101561051857818160208110610502576105026116a4565b602002015160019081901b9690961795016104e7565b50610522866110ef565b935061052d866111fe565b9250610538866112f0565b91505091939590929450565b600180546101dc90611672565b60605f61055d8361031a565b50935050505061059160038281548110610579576105796116a4565b5f91825260209091206002909102015460e81b6113d1565b61059a84610197565b6040516020016105ab929190611721565b604051602081830303815290604052915050919050565b60605f805f6105d08561031a565b94509450945050505f6105e2866114a0565b6040516020016105f291906119f2565b60405160208183030381529060405290508061060d8761073a565b60405160200161061e929190611aac565b604051602081830303815290604052905080610639856114a0565b60405160200161064a929190611b0c565b6040516020818303038152906040529050806003848154811061066f5761066f6116a4565b905f5260205f20906002020160010160405160200161068f929190611c0b565b604051602081830303815290604052905080600483815481106106b4576106b46116a4565b905f5260205f2090600202016001016040516020016106d4929190611c65565b6040516020818303038152906040529050806040516020016106f69190611ccb565b604051602081830303815290604052905061071081610758565b6040516020016107209190611cf0565b604051602081830303815290604052945050505050919050565b60606107486101a583610551565b6040516020016101ba9190611d34565b606081515f0361077557505060408051602081019091525f815290565b5f604051806060016040528060408152602001611e1c6040913990505f60038451600201816107a6576107a661170d565b0460040290508060200167ffffffffffffffff8111156107c8576107c8611d78565b6040519080825280601f01601f1916602001820160405280156107f2576020820181803683370190505b509250808352600182018485518101602086015b818310156108605760039283018051603f601282901c811687015160f890811b8552600c83901c8216880151811b6001860152600683901c8216880151811b60028601529116860151901b93820193909352600401610806565b60038851066001811461087a576002811461088b57610896565b613d3d60f01b600119830152610896565b603d60f81b5f198301525b50505050505050919050565b604080516001600160e81b031984811660208301525f60238301819052908416602483015260278201528151600881830301815260289091019091525b92915050565b6040516529ba30ba329d60d11b6020820152602681018590526060905f9060460160408051601f19818403018152919052805160209091012090505f83156109305760028504610932565b845b90505f846003146109435785610948565b600286045b90505f8167ffffffffffffffff81111561096457610964611d78565b60405190808252806020026020018201604052801561098d578160200160208202803683370190505b5090505f5b82811015610a5457805f036109ce576001846001901b0385168282815181106109bd576109bd6116a4565b602002602001018181525050610a4c565b5f808360018403815181106109e5576109e56116a4565b602090810291909101015180871b1760021b80871c6003161790505f5b86811015610a2957600163ffffffff8d16601f84841c161c8116821b939093179201610a02565b5081848481518110610a3d57610a3d6116a4565b60200260200101818152505050505b600101610992565b505f610a5f88610d72565b905080600202880167ffffffffffffffff811115610a7f57610a7f611d78565b604051908082528060200260200182016040528015610ab257816020015b6060815260200190600190039081610a9d5790505b5095505f5b8651811015610c2d5781600202890167ffffffffffffffff811115610ade57610ade611d78565b604051908082528060200260200182016040528015610b07578160200160208202803683370190505b50878281518110610b1a57610b1a6116a4565b6020026020010181905250818110158015610b36575081890181105b15610c2557815b82888381518110610b5057610b506116a4565b60200260200101515103811015610c23578281038383038a15801590610b7857508488018310155b15610b9a57600183868e01030391508a600103610b9a57600184868e01030390505b8a6003148015610bac57508487018410155b15610bbc57600184868e01030390505b81868281518110610bcf57610bcf6116a4565b6020026020010151901c6001168a8581518110610bee57610bee6116a4565b60200260200101518481518110610c0757610c076116a4565b60ff909216602092830291909101909101525050600101610b3d565b505b600101610ab7565b505050505050949350505050565b60605f825f81518110610c5057610c506116a4565b602002602001015151905060048181610c6b57610c6b61170d565b0615610c7a5760048106600403015b8083510267ffffffffffffffff811115610c9657610c96611d78565b6040519080825280601f01601f191660200182016040528015610cc0576020820181803683370190505b5091505f5b8351811015610d6b575f5b848281518110610ce257610ce26116a4565b602002602001015151811015610d6257848281518110610d0457610d046116a4565b60200260200101518181518110610d1d57610d1d6116a4565b602002602001015160f81b8482856001868a510303020181518110610d4457610d446116a4565b60200101906001600160f81b03191690815f1a905350600101610cd0565b50600101610cc5565b5050919050565b5f6108df600883611d8c565b825160609060368101905f9063ffffffff83160367ffffffffffffffff811115610daa57610daa611d78565b6040519080825280601f01601f191660200182016040528015610dd4576020820181803683370190505b509050604260f81b815f81518110610dee57610dee6116a4565b60200101906001600160f81b03191690815f1a905350604d60f81b81600181518110610e1c57610e1c6116a4565b60200101906001600160f81b03191690815f1a905350845182015f60025b6006811015610e835760ff831691508260081c92508160f81b848281518110610e6557610e656116a4565b60200101906001600160f81b03191690815f1a905350600101610e3a565b50839150600a5b600e811015610ed35760ff831691508260081c92508160f81b848281518110610eb557610eb56116a4565b60200101906001600160f81b03191690815f1a905350600101610e8a565b50602860f81b83600e81518110610eec57610eec6116a4565b60200101906001600160f81b03191690815f1a90535085915060125b6016811015610f805760ff831691508260081c92508160f81b848281518110610f3357610f336116a4565b60200101906001600160f81b03191690815f1a9053508160f81b848260040181518110610f6257610f626116a4565b60200101906001600160f81b03191690815f1a905350600101610f08565b50600160f81b83601a81518110610f9957610f996116a4565b60200101906001600160f81b03191690815f1a905350600860f81b83601c81518110610fc757610fc76116a4565b60200101906001600160f81b03191690815f1a9053508651915060225b602681101561102d5760ff831691508260081c92508160f81b84828151811061100f5761100f6116a4565b60200101906001600160f81b03191690815f1a905350600101610fe4565b50600488518161103f5761103f61170d565b049150602e5b60328110156110bd5760ff831691508260081c92508160f81b848281518110611070576110706116a4565b60200101906001600160f81b03191690815f1a9053508160f81b84826004018151811061109f5761109f6116a4565b60200101906001600160f81b03191690815f1a905350600101611045565b508288886040516020016110d393929190611dab565b6040516020818303038152906040529450505050509392505050565b5f80805b6002548110156111325760028181548110611110576111106116a4565b5f91825260209091200154600160f81b900460ff1691909101906001016110f3565b506040516429b4bd329d60d91b6020820152602581018490525f908290604501604051602081830303815290604052805190602001205f1c816111775761117761170d565b0690505f91505f5b6002548110156111f6576002818154811061119c5761119c6116a4565b5f91825260209091200154600160f81b900460ff169290920191828210156111ee57600281815481106111d1576111d16116a4565b5f918252602090912001546001600160f81b031695945050505050565b60010161117f565b505050919050565b5f80805b60035481101561124a576003818154811061121f5761121f6116a4565b5f9182526020909120600290910201546601000000000000900461ffff169190910190600101611202565b506040516521b7b637b91d60d11b6020820152602681018490525f908290604601604051602081830303815290604052805190602001205f1c816112905761129061170d565b0690505f91505f5b6003548110156111f657600381815481106112b5576112b56116a4565b5f9182526020909120600290910201546601000000000000900461ffff169290920191828210156112e857949350505050565b600101611298565b5f80805b6004548110156113315760048181548110611311576113116116a4565b5f91825260209091206002909102015460ff1691909101906001016112f4565b506040516a2932b33632b1ba34b7b71d60a91b6020820152602b81018490525f908290604b01604051602081830303815290604052805190602001205f1c8161137c5761137c61170d565b0690505f91505f5b6004548110156111f657600481815481106113a1576113a16116a4565b5f91825260209091206002909102015460ff169290920191828210156113c957949350505050565b600101611384565b6040805180820190915260018152602360f81b60208201525f5b600681101561149a57604080516001808252818301909252600f60e886901c600285851602850384016004021c16915f91906020820181803683370190505090506009821161143b57603061143e565b60575b820160f81b815f81518110611455576114556116a4565b60200101906001600160f81b03191690815f1a905350838160405160200161147e929190611ded565b60408051808303601f19018152919052935050506001016113eb565b50919050565b60606001825b60098111156114bf5760019190910190600a90046114a6565b5f8267ffffffffffffffff8111156114d9576114d9611d78565b6040519080825280601f01601f191660200182016040528015611503576020820181803683370190505b5090505f5b8151811015611575575f600a60018385510303600a0a888161152c5761152c61170d565b048161153a5761153a61170d565b0690508060300160f81b838381518110611556576115566116a4565b60200101906001600160f81b03191690815f1a90535050600101611508565b50949350505050565b6040518061040001604052806020906020820280368337509192915050565b5f602082840312156115ad575f80fd5b5035919050565b5f5b838110156115ce5781810151838201526020016115b6565b50505f910152565b5f81518084526115ed8160208601602086016115b4565b601f01601f19169290920160200192915050565b602081525f61161360208301846115d6565b9392505050565b5f815161162b8185602086016115b4565b9290920192915050565b7519185d184e9a5b5859d94bd89b5c0ed8985cd94d8d0b60521b81525f82516116658160168501602087016115b4565b9190910160160192915050565b600181811c9082168061168657607f821691505b60208210810361149a57634e487b7160e01b5f52602260045260245ffd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176108df576108df6116b8565b808201808211156108df576108df6116b8565b5f60208284031215611706575f80fd5b5051919050565b634e487b7160e01b5f52601260045260245ffd5b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081527f30302f737667222076657273696f6e3d22312e3122207072657365727665417360208201527f70656374526174696f3d22784d6964594d6964206d656574222076696577426f60408201527f783d223020302035313220353132222077696474683d2231303025222068656960608201527f6768743d2231303025223e3c646566733e3c7374796c6520747970653d22746560808201527f78742f637373223e7376677b696d6167652d72656e646572696e673a6f70746960a08201527f6d697a6553706565643b696d6167652d72656e646572696e673a2d6d6f7a2d6360c08201527f726973702d65646765733b696d6167652d72656e646572696e673a2d6f2d637260e08201527f6973702d65646765733b696d6167652d72656e646572696e673a2d7765626b696101008201527f742d6f7074696d697a652d636f6e74726173743b696d6167652d72656e6465726101208201527f696e673a706978656c617465643b696d6167652d72656e646572696e673a6f706101408201527f74696d697a652d636f6e74726173743b2d6d732d696e746572706f6c6174696f6101608201527f6e2d6d6f64653a6e6561726573742d6e65696768626f723b6261636b67726f7561018082015268373216b1b7b637b91d60b91b6101a08201525f6119ea61196461195e61193c6101a986018861161a565b75076c4c2c6d6cee4deeadcc85ad2dac2ceca74eae4d8560531b815260160190565b8561161a565b7f293b6261636b67726f756e642d7265706561743a6e6f2d7265706561743b626181527f636b67726f756e642d73697a653a636f6e7461696e3b6261636b67726f756e6460208201527f2d706f736974696f6e3a353025203530253b7d3c2f7374796c653e3c2f646566604082015267399f1e17b9bb339f60c11b606082015260680190565b949350505050565b6e7b226e616d65223a224155544f202360881b815281515f90611a1c81600f8501602087016115b4565b7f222c226465736372697074696f6e223a2254686520666972737420636f6c6c65600f9390910192830152507f6374696f6e20746f207573652074686520784e46542068796272696420737461602f8201527f6e646172642e2043726561746564206279207468652043656c6c4d6174657320604f820152661d19585b4b888b60ca1b606f820152607601919050565b5f8351611abd8184602088016115b4565b681134b6b0b3b2911d1160b91b9083019081528351611ae38160098401602088016115b4565b6f222c2261747472696275746573223a5b60801b60099290910191820152601901949350505050565b5f8351611b1d8184602088016115b4565b7f7b2274726169745f74797065223a2253697a65222c2276616c7565223a2200009083019081528351611b5781601e8401602088016115b4565b62089f4b60ea1b601e9290910191820152602101949350505050565b80545f90600181811c9080831680611b8c57607f831692505b60208084108203611bab57634e487b7160e01b5f52602260045260245ffd5b818015611bbf5760018114611bd457611bff565b60ff1986168952841515850289019650611bff565b5f888152602090205f5b86811015611bf75781548b820152908501908301611bde565b505084890196505b50505050505092915050565b5f8351611c1c8184602088016115b4565b7f7b2274726169745f74797065223a22436f6c6f72222c2276616c7565223a2200908301908152611c50601f820185611b73565b62089f4b60ea1b815260030195945050505050565b5f8351611c768184602088016115b4565b7f7b2274726169745f74797065223a225265666c656374696f6e222c2276616c759083019081526332911d1160e11b6020820152611cb76024820185611b73565b61227d60f01b815260020195945050505050565b5f8251611cdc8184602087016115b4565b615d7d60f01b920191825250600201919050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c00000081525f8251611d2781601d8501602087016115b4565b91909101601d0192915050565b7f646174613a696d6167652f7376672b786d6c3b6261736536342c00000000000081525f8251611d6b81601a8501602087016115b4565b91909101601a0192915050565b634e487b7160e01b5f52604160045260245ffd5b5f82611da657634e487b7160e01b5f52601260045260245ffd5b500490565b5f8451611dbc8184602089016115b4565b845190830190611dd08183602089016115b4565b8451910190611de38183602088016115b4565b0195945050505050565b5f8351611dfe8184602088016115b4565b835190830190611e128183602088016115b4565b0194935050505056fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212209b902f1bbbe22c2f94ffb97e27c2b2f56513b713e4875b1f60343db9810741ec64736f6c63430008180033c2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85cc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19c8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b5472616e7366657228616464726573732c616464726573732c75696e7432353629

Deployed Bytecode

0x60806040526004361061026a575f3560e01c806370a082311161014a578063a9059cbb116100be578063d28a476111610078578063d28a4761146107a7578063db737c78146107c6578063dd62ed3e146107f4578063e985e9c514610839578063f3cb838514610884578063f4cdda36146108a3575f80fd5b8063a9059cbb146106fb578063b88d4fde1461071a578063bdb4b84814610739578063bfa0b13314610754578063c5b8f77214610769578063c87b56dd14610788575f80fd5b8063888ce1f31161010f578063888ce1f3146106645780638da5cb5b146106795780638fffabed1461069657806395d89b41146106b5578063a0712d68146106c9578063a22cb465146106dc575f80fd5b806370a08231146105985780637c187f7b146105d05780638129fc1c146105fc5780638188f71c1461061057806385f2aef214610631575f80fd5b806324cea3a6116101e15780633d13f874116101a65780633d13f874146104f257806342842e0e146105115780634bce92f3146105305780634bf365df146105455780634f6ccce71461055a5780636352211e14610579575f80fd5b806324cea3a6146104485780632f745c591461045c578063313ce5671461047b578063348fb288146104a0578063392f37e9146104d3575f80fd5b80631078d1ed116102325780631078d1ed1461035557806313af40351461038357806318160ddd146103a457806319781e3c146103d757806323b872dd146103f657806324bfe56514610415575f80fd5b806301ffc9a71461026e57806306fdde03146102b1578063076f4662146102d2578063081812fc146102ff578063095ea7b314610336575b5f80fd5b348015610279575f80fd5b5061029c61028836600461492a565b60066020525f908152604090205460ff1681565b60405190151581526020015b60405180910390f35b3480156102bc575f80fd5b506102c56108d1565b6040516102a89190614999565b3480156102dd575f80fd5b506102f16102ec3660046149bf565b610944565b6040519081526020016102a8565b34801561030a575f80fd5b5061031e6103193660046149ed565b61099e565b6040516001600160a01b0390911681526020016102a8565b348015610341575f80fd5b5061029c610350366004614a04565b610a14565b348015610360575f80fd5b5061037461036f366004614b02565b610a8f565b6040516102a893929190614b8f565b34801561038e575f80fd5b506103a261039d366004614c14565b610c11565b005b3480156103af575f80fd5b506102f17f000000000000000000000000000000000000000000000000000000000000100081565b3480156103e2575f80fd5b506103a26103f1366004614c43565b610c49565b348015610401575f80fd5b5061029c610410366004614c9c565b610ea6565b348015610420575f80fd5b5061031e7f00000000000000000000000097cc21a332c96ee626548051b62d28828a7a295e81565b348015610453575f80fd5b506103a2610f8a565b348015610467575f80fd5b506102f1610476366004614a04565b610fa6565b348015610486575f80fd5b5061048e5f81565b60405160ff90911681526020016102a8565b3480156104ab575f80fd5b5061031e7f0000000000000000000000007c72445127e3b1dfd7ecfbf7988c8e9e82718b6581565b3480156104de575f80fd5b5060075461031e906001600160a01b031681565b3480156104fd575f80fd5b506103a261050c366004614cda565b6110d4565b34801561051c575f80fd5b506103a261052b366004614c9c565b6111f3565b34801561053b575f80fd5b506102f160085481565b348015610550575f80fd5b506102f1600d5481565b348015610565575f80fd5b506102f16105743660046149ed565b611212565b348015610584575f80fd5b5061031e6105933660046149ed565b611267565b3480156105a3575f80fd5b506102f16105b2366004614c14565b6001600160a01b03165f9081526002602052604090205461ffff1690565b3480156105db575f80fd5b506105ef6105ea366004614c14565b61134f565b6040516102a89190614d5e565b348015610607575f80fd5b506103a26113f5565b34801561061b575f80fd5b50610624611ad8565b6040516102a89190614da1565b34801561063c575f80fd5b5061031e7f000000000000000000000000eefe1c0bc74f0114722641656e6072002eaac8cd81565b34801561066f575f80fd5b506102f160095481565b348015610684575f80fd5b506001546001600160a01b031661031e565b3480156106a1575f80fd5b50600a5461031e906001600160a01b031681565b3480156106c0575f80fd5b506102c5611b3b565b6103a26106d73660046149ed565b611b82565b3480156106e7575f80fd5b506103a26106f6366004614db3565b611c66565b348015610706575f80fd5b5061029c610715366004614a04565b611cd5565b348015610725575f80fd5b506103a2610734366004614e03565b611ce1565b348015610744575f80fd5b506102f167016345785d8a000081565b34801561075f575f80fd5b506102f1600b5481565b348015610774575f80fd5b5061029c610783366004614a04565b611d88565b348015610793575f80fd5b506102c56107a23660046149ed565b611e09565b3480156107b2575f80fd5b506103a26107c1366004614eaa565b611e77565b3480156107d1575f80fd5b506107e56107e0366004614ef6565b611e81565b6040516102a893929190614f17565b3480156107ff575f80fd5b506102f161080e366004614f4b565b6001600160a01b039182165f9081526002602081815260408084209490951683529201909152205490565b348015610844575f80fd5b5061029c610853366004614f4b565b6001600160a01b039182165f9081526002602090815260408083209390941682526003909201909152205460ff1690565b34801561088f575f80fd5b506103a261089e366004614c14565b611eb8565b3480156108ae575f80fd5b5061029c6108bd366004614c14565b600c6020525f908152604090205460ff1681565b600754604080516306fdde0360e01b815290516060926001600160a01b0316916306fdde03916004808301925f9291908290030181865afa158015610918573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261093f9190810190614f77565b905090565b5f7f00000000000000000000000000000000000000000000000000000000000000108310610970575f80fd5b506001600160a01b0381165f9081526002602090815260408083208584526001019091529020545b92915050565b5f7f0000000000000000000000000000000000000000000000000000000000001000821180156109f157507f00000000000000000000000000000000000000000000000000000000000010006002028211155b6109f9575f80fd5b505f908152600360205260409020546001600160a01b031690565b5f7f000000000000000000000000000000000000000000000000000000000000100082118015610a6757507f00000000000000000000000000000000000000000000000000000000000010006002028211155b15610a7b57610a768383611ef0565b610a86565b610a86338484611f9f565b50600192915050565b60608060605f85519050806001600160401b03811115610ab157610ab1614a2e565b604051908082528060200260200182016040528015610ada578160200160208202803683370190505b509350806001600160401b03811115610af557610af5614a2e565b604051908082528060200260200182016040528015610b1e578160200160208202803683370190505b509250806001600160401b03811115610b3957610b39614a2e565b604051908082528060200260200182016040528015610b6c57816020015b6060815260200190600190039081610b575790505b5091505f5b81811015610c0857610b9c878281518110610b8e57610b8e614fdf565b602002602001015187611e81565b878481518110610bae57610bae614fdf565b60200260200101878581518110610bc757610bc7614fdf565b60200260200101878681518110610be057610be0614fdf565b60209081029190910101929092526001600160a01b0392831690915291169052600101610b71565b50509250925092565b6001546001600160a01b03163314610c27575f80fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b5f7368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b031663791b98bc6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c9a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cbe9190614ff3565b6040805160808101825260095481526001600160a01b037f000000000000000000000000eefe1c0bc74f0114722641656e6072002eaac8cd811660208301526001600160801b038981168385015288166060830152915163fc6f786560e01b81529293509083169163fc6f786591610d389160040161500e565b60408051808303815f875af1158015610d53573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d779190615051565b50506040805160808101825260085481526001600160a01b037f000000000000000000000000eefe1c0bc74f0114722641656e6072002eaac8cd811660208301526001600160801b038681168385015285166060830152915163fc6f786560e01b81529183169163fc6f786591610df09160040161500e565b60408051808303815f875af1158015610e0b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e2f9190615051565b50507f000000000000000000000000eefe1c0bc74f0114722641656e6072002eaac8cd6001600160a01b031663476343ee6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610e89575f80fd5b505af1158015610e9b573d5f803e3d5ffd5b505050505050505050565b5f7f000000000000000000000000000000000000000000000000000000000000100082118015610ef957507f00000000000000000000000000000000000000000000000000000000000010006002028211155b15610f0e57610f09848484612008565b610f80565b6001600160a01b0384165f908152600260208181526040808420338552909201905290205482811015610f3f575f80fd5b5f198114610f73576001600160a01b0385165f90815260026020818152604080842033855290920190529020805484900390555b610f7e8585856121c9565b505b5060019392505050565b610fa46001600160801b03806001600160801b0380610c49565b565b6001600160a01b0382165f9081526002602052604081205461ffff168210610fcc575f80fd5b6001600160a01b0383165f9081526002602052604081205464010000000090046001600160e01b03165b5f811180156110055750838211155b156110cc575f611014826123db565b9050806001901b821891505f61102a8288610944565b90505f61103682613928565b9050868186011161104a57938401936110c4565b815b5f8111801561105b5750878611155b156110c2575f61106a826123db565b60018881019890821b93909318929091508990036110bc57807f000000000000000000000000000000000000000000000000000000000000100086610100020101600101975050505050505050610998565b5061104c565b505b505050610ff6565b505092915050565b6001600160a01b0384165f908152600c602052604090205460ff16156110f8575f80fd5b6111758282808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040516bffffffffffffffffffffffff1960608a901b16602082015260348101889052605401915061115a9050565b604051602081830303815290604052805190602001206139f4565b61117d575f80fd5b6001600160a01b0384165f908152600c60205260409020805460ff191660011790556111aa3085856121c9565b836001600160a01b03167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4846040516111e591815260200190565b60405180910390a250505050565b61120d83838360405180602001604052805f815250611ce1565b505050565b5f7f0000000000000000000000000000000000000000000000000000000000001000821061123e575f80fd5b507f00000000000000000000000000000000000000000000000000000000000010000160010190565b5f3363ffffffff811615611279575f80fd5b7f0000000000000000000000000000000000000000000000000000000000001000831180156112cb57507f00000000000000000000000000000000000000000000000000000000000010006002028311155b6112d3575f80fd5b5f806112de85613ab6565b60045491935091505f5b81811015611343575f6001600301828154811061130757611307614fdf565b5f918252602090912001546001600160a01b0316905083806113298784610944565b160361133a57979650505050505050565b506001016112e8565b505f9695505050505050565b60607f00000000000000000000000000000000000000000000000000000000000000106001600160401b0381111561138957611389614a2e565b6040519080825280602002602001820160405280156113b2578160200160208202803683370190505b5090505f5b81518110156113ef576113ca8184610944565b8282815181106113dc576113dc614fdf565b60209081029190910101526001016113b7565b50919050565b5f805460ff19166001179055600a546001600160a01b031615611416575f80fd5b5f3090505f7368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b0316634aa4a4fc6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561146b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061148f9190614ff3565b90506114b282737a250d5630b4cf539739df2c5dacb4c659f2488d610100611f9f565b737a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611502573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115269190614ff3565b6040516364e329cb60e11b81526001600160a01b0383811660048301528481166024830152919091169063c9c65396906044016020604051808303815f875af1158015611575573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115999190614ff3565b600a80546001600160a01b039283166001600160a01b0319909116179055737a250d5630b4cf539739df2c5dacb4c659f2488d9063f305d71990841631846101005f806115ee6001546001600160a01b031690565b60405160e088901b6001600160e01b03191681526001600160a01b03958616600482015260248101949094526044840192909252606483015290911660848201524260a482015260c40160606040518083038185885af1158015611654573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906116799190615073565b5050505f7368b3465833fb72a70ecdf485e0e4c7bd8665fc456001600160a01b031663791b98bc6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116cd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116f19190614ff3565b905061170b83826117066105006101006150b2565b611f9f565b6001600160a01b03808416908316105f611748826110007f000000000000000000000000000000000000000000000003782dace9d9000000613af3565b9150505f611764836110006a52b7d2dcc80cd2e4000000613af3565b915050836001600160a01b031663883164566040518061016001604052808661178d578961178f565b885b6001600160a01b0316815260200186156117a957896117ab565b885b6001600160a01b031681526127106020820152604001866117cc57856117ce565b845b60020b815260200186156117e257856117e4565b845b60020b8152602001866117f9576105006117fb565b5f5b8152602001861561180e57610500611810565b5f5b81526020015f81526020015f8152602001896001600160a01b03168152602001428152506040518263ffffffff1660e01b815260040161185091906150c5565b6080604051808303815f875af115801561186c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118909190615189565b5050506009556001600160a01b0386167318e5f92103d1b34623738ee79214b1659f2ee109109250611921836110007f00000000000000000000000000000000000000000000000055dd981adc3dbdbf6119127f000000000000000000000000000000000000000000000003782dace9d9000000670de0b6b3a76400006151c4565b61191c91906151ef565b613af3565b925061196a9050836110007f00000000000000000000000000000000000000000000000055dd981adc3dbdbf6119126a52b7d2dcc80cd2e4000000670de0b6b3a76400006151c4565b905080915050836001600160a01b031663883164566040518061016001604052808661199657896119ac565b7318e5f92103d1b34623738ee79214b1659f2ee1095b6001600160a01b0316815260200186156119c657896119dc565b7318e5f92103d1b34623738ee79214b1659f2ee1095b6001600160a01b031681526127106020820152604001866119fd57856119ff565b845b60020b81526020018615611a135785611a15565b845b60020b815260200186611a2a57610100611a2c565b5f5b81526020018615611a3f57610100611a41565b5f5b81526020015f81526020015f8152602001896001600160a01b03168152602001428152506040518263ffffffff1660e01b8152600401611a8191906150c5565b6080604051808303815f875af1158015611a9d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ac19190615189565b50505060085550505f805460ff1916905550505050565b60606001600301805480602002602001604051908101604052809291908181526020018280548015611b3157602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611b13575b5050505050905090565b600754604080516395d89b4160e01b815290516060926001600160a01b0316916395d89b41916004808301925f9291908290030181865afa158015610918573d5f803e3d5ffd5b600d54811115611b90575f80fd5b5f611ba367016345785d8a0000836151c4565b905080341015611bb1575f80fd5b81600d5f828254611bc29190615202565b90915550611bd390503033846121c9565b6040516001600160a01b037f000000000000000000000000eefe1c0bc74f0114722641656e6072002eaac8cd169082156108fc029083905f818181858888f19350505050158015611c26573d5f803e3d5ffd5b5080341115611c6257336108fc611c3d8334615202565b6040518115909202915f818181858888f1935050505015801561120d573d5f803e3d5ffd5b5050565b335f8181526002602090815260408083206001600160a01b0387168085526003909101835292819020805460ff191686151590811790915590519081529192917f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a35050565b5f610a863384846121c9565b611cec848484612008565b823b63ffffffff811615611d8157604051630a85bd0160e11b808252906001600160a01b0386169063150b7a0290611d2e9033908a9089908990600401615215565b6020604051808303815f875af1158015611d4a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d6e9190615251565b6001600160e01b03191614611d81575f80fd5b5050505050565b5f7f000000000000000000000000000000000000000000000000000000000000100082118015611ddb57507f00000000000000000000000000000000000000000000000000000000000010006002028211155b611de3575f80fd5b5f80611dee84613ab6565b915091508081611dfe8488610944565b161495945050505050565b60075460405163c87b56dd60e01b8152600481018390526060916001600160a01b03169063c87b56dd906024015f60405180830381865afa158015611e50573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109989190810190614f77565b611c628282613b69565b5f80606083611e90575f611e99565b611e9985611267565b611ea28661099e565b611eab87611e09565b9250925092509250925092565b6001546001600160a01b03163314611ece575f80fd5b600780546001600160a01b0319166001600160a01b0392909216919091179055565b5f80611efb83613ab6565b915091508081611f0b8433610944565b1614611f15575f80fd5b5f83815260036020908152604080832080546001600160a01b0389166001600160a01b03199091168117909155338085526002909352818420805461ffff6201000080830482166001019091160263ffff000019909116179055905186939192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a450505050565b6001600160a01b038084165f81815260026020818152604080842095881680855295909201815291819020859055805160608101909152602180825290916152c7908301398051906020012083604051611ffb91815260200190565b60405180910390a3505050565b7f00000000000000000000000000000000000000000000000000000000000010008111801561205a57507f00000000000000000000000000000000000000000000000000000000000010006002028111155b612062575f80fd5b5f8061206d83613ab6565b91509150808161207d8488610944565b1614612087575f80fd5b336001600160a01b03861614806120b757506120a28361099e565b6001600160a01b0316336001600160a01b0316145b806120e757506001600160a01b0385165f90815260026020908152604080832033845260030190915290205460ff165b6120ef575f80fd5b5f7f00000000000000000000000000000000000000000000000000000000000000106001600160401b0381111561212857612128614a2e565b604051908082528060200260200182016040528015612151578160200160208202803683370190505b5090508181848151811061216757612167614fdf565b60209081029190910101526040805160018082528183019092525f9181602001602082028036833701905050905084815f815181106121a8576121a8614fdf565b6020026020010181815250506121c087878484613cf4565b50505050505050565b5f80826001600160401b038111156121e3576121e3614a2e565b60405190808252806020026020018201604052801561220c578160200160208202803683370190505b5090505f7f00000000000000000000000000000000000000000000000000000000000000106001600160401b0381111561224857612248614a2e565b604051908082528060200260200182016040528015612271578160200160208202803683370190505b506001600160a01b0387165f9081526002602052604090205490915064010000000090046001600160e01b03165b5f811180156122ad57508484105b156123c4575f6122bc826123db565b9050806001901b821891505f6122d2828a610944565b9050805b5f811180156122e457508787105b1561237d575f6122f3826123db565b86519091506001821b90819088908790811061231157612311614fdf565b602002602001018181511791508181525050817f000000000000000000000000000000000000000000000000000000000000100086610100020101600101888a806001019b508151811061236757612367614fdf565b60209081029190910101529190911890506122d6565b84838151811061238f5761238f614fdf565b60200260200101518584815181106123a9576123a9614fdf565b60200260200101518316146123bc575f80fd5b50505061229f565b8484146123cf575f80fd5b6121c087878486613cf4565b5f5f198201198216600160801b811015612eb4576801000000000000000081101561292d5764010000000081101561266a576201000081101561252d5761010081101561249f576010811015612460576004811015612445576002811015610a8657505f92915050565b60088110156124575750600292915050565b50600392915050565b604081101561248457602081101561247b5750600492915050565b50600592915050565b60808110156124965750600692915050565b50600792915050565b6110008110156124eb576104008110156124cf576102008110156124c65750600892915050565b50600992915050565b6108008110156124e25750600a92915050565b50600b92915050565b614000811015612511576120008110156125085750600c92915050565b50600d92915050565b6180008110156125245750600e92915050565b50600f92915050565b63010000008110156125ce5762100000811015612589576204000081101561256c57620200008110156125635750601092915050565b50601192915050565b620800008110156125805750601292915050565b50601392915050565b624000008110156125b157622000008110156125a85750601492915050565b50601592915050565b628000008110156125c55750601692915050565b50601792915050565b63100000008110156126225763040000008110156126045763020000008110156125fb5750601892915050565b50601992915050565b63080000008110156126195750601a92915050565b50601b92915050565b634000000081101561264c5763200000008110156126435750601c92915050565b50601d92915050565b63800000008110156126615750601e92915050565b50601f92915050565b66010000000000008110156127d4576501000000000081101561272a576410000000008110156126df576404000000008110156126c0576402000000008110156126b75750602092915050565b50602192915050565b6408000000008110156126d65750602292915050565b50602392915050565b64400000000081101561270b576420000000008110156127025750602492915050565b50602592915050565b6480000000008110156127215750602692915050565b50602792915050565b651000000000008110156127865765040000000000811015612766576502000000000081101561275d5750602892915050565b50602992915050565b6508000000000081101561277d5750602a92915050565b50602b92915050565b654000000000008110156127b457652000000000008110156127ab5750602c92915050565b50602d92915050565b658000000000008110156127cb5750602e92915050565b50602f92915050565b600160381b81101561289157661000000000000081101561284057660400000000000081101561281f5766020000000000008110156128165750603092915050565b50603192915050565b66080000000000008110156128375750603292915050565b50603392915050565b66400000000000008110156128705766200000000000008110156128675750603492915050565b50603592915050565b66800000000000008110156128885750603692915050565b50603792915050565b6001603c1b8110156128e5576001603a1b8110156128c757600160391b8110156128be5750603892915050565b50603992915050565b6001603b1b8110156128dc5750603a92915050565b50603b92915050565b6001603e1b81101561290f576001603d1b8110156129065750603c92915050565b50603d92915050565b6001603f1b8110156129245750603e92915050565b50603f92915050565b600160601b811015612c2057600160501b811015612adc576901000000000000000000811015612a1657681000000000000000008110156129bf576804000000000000000081101561299c57680200000000000000008110156129935750604092915050565b50604192915050565b680800000000000000008110156129b65750604292915050565b50604392915050565b684000000000000000008110156129f357682000000000000000008110156129ea5750604492915050565b50604592915050565b68800000000000000000811015612a0d5750604692915050565b50604792915050565b6910000000000000000000811015612a82576904000000000000000000811015612a5e576902000000000000000000811015612a555750604892915050565b50604992915050565b6908000000000000000000811015612a795750604a92915050565b50604b92915050565b6940000000000000000000811015612ab8576920000000000000000000811015612aaf5750604c92915050565b50604d92915050565b6980000000000000000000811015612ad35750604e92915050565b50604f92915050565b600160581b811015612b8457600160541b811015612b3c57600160521b811015612b1e57600160511b811015612b155750605092915050565b50605192915050565b600160531b811015612b335750605292915050565b50605392915050565b600160561b811015612b6657600160551b811015612b5d5750605492915050565b50605592915050565b600160571b811015612b7b5750605692915050565b50605792915050565b6001605c1b811015612bd8576001605a1b811015612bba57600160591b811015612bb15750605892915050565b50605992915050565b6001605b1b811015612bcf5750605a92915050565b50605b92915050565b6001605e1b811015612c02576001605d1b811015612bf95750605c92915050565b50605d92915050565b6001605f1b811015612c175750605e92915050565b50605f92915050565b600160701b811015612d7057600160681b811015612cd457600160641b811015612c8c57600160621b811015612c6e57600160611b811015612c655750606092915050565b50606192915050565b600160631b811015612c835750606292915050565b50606392915050565b600160661b811015612cb657600160651b811015612cad5750606492915050565b50606592915050565b600160671b811015612ccb5750606692915050565b50606792915050565b6001606c1b811015612d28576001606a1b811015612d0a57600160691b811015612d015750606892915050565b50606992915050565b6001606b1b811015612d1f5750606a92915050565b50606b92915050565b6001606e1b811015612d52576001606d1b811015612d495750606c92915050565b50606d92915050565b6001606f1b811015612d675750606e92915050565b50606f92915050565b600160781b811015612e1857600160741b811015612dd057600160721b811015612db257600160711b811015612da95750607092915050565b50607192915050565b600160731b811015612dc75750607292915050565b50607392915050565b600160761b811015612dfa57600160751b811015612df15750607492915050565b50607592915050565b600160771b811015612e0f5750607692915050565b50607792915050565b6001607c1b811015612e6c576001607a1b811015612e4e57600160791b811015612e455750607892915050565b50607992915050565b6001607b1b811015612e635750607a92915050565b50607b92915050565b6001607e1b811015612e96576001607d1b811015612e8d5750607c92915050565b50607d92915050565b6001607f1b811015612eab5750607e92915050565b50607f92915050565b600160c01b8110156133f457600160a01b81101561316057600160901b81101561301c57600160881b811015612f8057600160841b811015612f3857600160821b811015612f1a57600160811b811015612f115750608092915050565b50608192915050565b600160831b811015612f2f5750608292915050565b50608392915050565b600160861b811015612f6257600160851b811015612f595750608492915050565b50608592915050565b600160871b811015612f775750608692915050565b50608792915050565b6001608c1b811015612fd4576001608a1b811015612fb657600160891b811015612fad5750608892915050565b50608992915050565b6001608b1b811015612fcb5750608a92915050565b50608b92915050565b6001608e1b811015612ffe576001608d1b811015612ff55750608c92915050565b50608d92915050565b6001608f1b8110156130135750608e92915050565b50608f92915050565b600160981b8110156130c457600160941b81101561307c57600160921b81101561305e57600160911b8110156130555750609092915050565b50609192915050565b600160931b8110156130735750609292915050565b50609392915050565b600160961b8110156130a657600160951b81101561309d5750609492915050565b50609592915050565b600160971b8110156130bb5750609692915050565b50609792915050565b6001609c1b811015613118576001609a1b8110156130fa57600160991b8110156130f15750609892915050565b50609992915050565b6001609b1b81101561310f5750609a92915050565b50609b92915050565b6001609e1b811015613142576001609d1b8110156131395750609c92915050565b50609d92915050565b6001609f1b8110156131575750609e92915050565b50609f92915050565b600160b01b8110156132b057600160a81b81101561321457600160a41b8110156131cc57600160a21b8110156131ae57600160a11b8110156131a5575060a092915050565b5060a192915050565b600160a31b8110156131c3575060a292915050565b5060a392915050565b600160a61b8110156131f657600160a51b8110156131ed575060a492915050565b5060a592915050565b600160a71b81101561320b575060a692915050565b5060a792915050565b600160ac1b81101561326857600160aa1b81101561324a57600160a91b811015613241575060a892915050565b5060a992915050565b600160ab1b81101561325f575060aa92915050565b5060ab92915050565b600160ae1b81101561329257600160ad1b811015613289575060ac92915050565b5060ad92915050565b600160af1b8110156132a7575060ae92915050565b5060af92915050565b600160b81b81101561335857600160b41b81101561331057600160b21b8110156132f257600160b11b8110156132e9575060b092915050565b5060b192915050565b600160b31b811015613307575060b292915050565b5060b392915050565b600160b61b81101561333a57600160b51b811015613331575060b492915050565b5060b592915050565b600160b71b81101561334f575060b692915050565b5060b792915050565b600160bc1b8110156133ac57600160ba1b81101561338e57600160b91b811015613385575060b892915050565b5060b992915050565b600160bb1b8110156133a3575060ba92915050565b5060bb92915050565b600160be1b8110156133d657600160bd1b8110156133cd575060bc92915050565b5060bd92915050565b600160bf1b8110156133eb575060be92915050565b5060bf92915050565b600160e01b81101561369457600160d01b81101561355057600160c81b8110156134b457600160c41b81101561346c57600160c21b81101561344e57600160c11b811015613445575060c092915050565b5060c192915050565b600160c31b811015613463575060c292915050565b5060c392915050565b600160c61b81101561349657600160c51b81101561348d575060c492915050565b5060c592915050565b600160c71b8110156134ab575060c692915050565b5060c792915050565b600160cc1b81101561350857600160ca1b8110156134ea57600160c91b8110156134e1575060c892915050565b5060c992915050565b600160cb1b8110156134ff575060ca92915050565b5060cb92915050565b600160ce1b81101561353257600160cd1b811015613529575060cc92915050565b5060cd92915050565b600160cf1b811015613547575060ce92915050565b5060cf92915050565b600160d81b8110156135f857600160d41b8110156135b057600160d21b81101561359257600160d11b811015613589575060d092915050565b5060d192915050565b600160d31b8110156135a7575060d292915050565b5060d392915050565b600160d61b8110156135da57600160d51b8110156135d1575060d492915050565b5060d592915050565b600160d71b8110156135ef575060d692915050565b5060d792915050565b600160dc1b81101561364c57600160da1b81101561362e57600160d91b811015613625575060d892915050565b5060d992915050565b600160db1b811015613643575060da92915050565b5060db92915050565b600160de1b81101561367657600160dd1b81101561366d575060dc92915050565b5060dd92915050565b600160df1b81101561368b575060de92915050565b5060df92915050565b600160f01b8110156137e457600160e81b81101561374857600160e41b81101561370057600160e21b8110156136e257600160e11b8110156136d9575060e092915050565b5060e192915050565b600160e31b8110156136f7575060e292915050565b5060e392915050565b600160e61b81101561372a57600160e51b811015613721575060e492915050565b5060e592915050565b600160e71b81101561373f575060e692915050565b5060e792915050565b600160ec1b81101561379c57600160ea1b81101561377e57600160e91b811015613775575060e892915050565b5060e992915050565b600160eb1b811015613793575060ea92915050565b5060eb92915050565b600160ee1b8110156137c657600160ed1b8110156137bd575060ec92915050565b5060ed92915050565b600160ef1b8110156137db575060ee92915050565b5060ef92915050565b600160f81b81101561388c57600160f41b81101561384457600160f21b81101561382657600160f11b81101561381d575060f092915050565b5060f192915050565b600160f31b81101561383b575060f292915050565b5060f392915050565b600160f61b81101561386e57600160f51b811015613865575060f492915050565b5060f592915050565b600160f71b811015613883575060f692915050565b5060f792915050565b600160fc1b8110156138e057600160fa1b8110156138c257600160f91b8110156138b9575060f892915050565b5060f992915050565b600160fb1b8110156138d7575060fa92915050565b5060fb92915050565b600160fe1b81101561390a57600160fd1b811015613901575060fc92915050565b5060fd92915050565b600160ff1b81101561391f575060fe92915050565b5060ff92915050565b5f8180820361393957505f92915050565b5f19810361394b575061010092915050565b7f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f7f5555555555555555555555555555555555555555555555555555555555555555600183901c16909103600281901c7f3333333333333333333333333333333333333333333333333333333333333333908116911601600481901c01167f01010101010101010101010101010101010101010101010101010101010101010260f81c92915050565b5f81815b8451811015613a8c575f858281518110613a1457613a14614fdf565b60200260200101519050808311613a56576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250613a83565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b506001016139f8565b507f3f856c8d1611023aaa9915c692b07293eea0d4dd7c26df3914d5bfbd430ce84c149392505050565b6101005f197f0000000000000000000000000000000000000000000000000000000000001000808403820183900494600193860290940303011b90565b5f805f613b3186613b045784613b06565b855b8715613b125785613b14565b865b613b2290600160c01b6151ef565b613b2c91906151c4565b6140dd565b9050613b3c8161411a565b9150613b4960c88361526c565b613b53908361528d565b9150613b5e82614416565b925050935093915050565b5f7f00000000000000000000000000000000000000000000000000000000000000106001600160401b03811115613ba257613ba2614a2e565b604051908082528060200260200182016040528015613bcb578160200160208202803683370190505b5090505f5b8251811015613c2f575f80613bfd858481518110613bf057613bf0614fdf565b6020026020010151613ab6565b9150915080848381518110613c1457613c14614fdf565b60209081029190910101805190911790525050600101613bd0565b505f805b8251811015613cd557828181518110613c4e57613c4e614fdf565b60200260200101515f801b14613ccd57828181518110613c7057613c70614fdf565b6020026020010151838281518110613c8a57613c8a614fdf565b6020026020010151613c9c8333610944565b1614613ca6575f80fd5b613cc8838281518110613cbb57613cbb614fdf565b6020026020010151613928565b820191505b600101613c33565b5082518114613ce2575f80fd5b613cee33858486613cf4565b50505050565b6001600160a01b038316613d06575f80fd5b5f815111613d12575f80fd5b613d1e84848484614744565b6001600160a01b038085165f908152600260205260408082205492861682528120546001600160e01b036401000000009384900481169390910416905b8451811015613e5e575f801b858281518110613d7957613d79614fdf565b602002602001015114613e56575f613d918289610944565b9050858281518110613da557613da5614fdf565b6020908102919091018101516001600160a01b038a165f908152600283526040808220868352600101909352918220921891829055613de48389610944565b9050868381518110613df857613df8614fdf565b6020908102919091018101516001600160a01b038a165f908152600283526040808220878352600101909352918220921791829055829003613e3e57826001901b851894505b6001831b939093179281811615613e53575f80fd5b50505b600101613d5b565b506001600160a01b038681165f908152600260205260408082208054875161ffff8083169190910380821663ffff0000938416176401000000006001600160e01b038b8116820292909217909555968c16865293852080548a5197891690940292841693821696870190911692909217179055919082900361401f576001600160a01b0388165f9081526005602052604081205490829003613f4e578760016003018281548110613f1157613f11614fdf565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055918a168152600590915260409020819055614001565b600480545f91905f198101908110613f6857613f68614fdf565b5f91825260209091200154600480546001600160a01b039092169250829184908110613f9657613f96614fdf565b5f91825260208083209190910180546001600160a01b0319166001600160a01b0394851617905591831681526005909152604090208290556004805480613fdf57613fdf6152b2565b5f8281526020902081015f1990810180546001600160a01b0319169055019055505b506001600160a01b0388165f90815260056020526040812055614086565b805f0361408657600480546001810182557f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b038a1690811790915590545f918252600560205260409091205f1990910190555b866001600160a01b0316886001600160a01b03166040518060600160405280602181526020016152e8602191398051906020012087516040516140cb91815260200190565b60405180910390a35050505050505050565b80600260018201045b818110156113ef57809150600281828581614103576141036151db565b040181614112576141126151db565b0490506140e6565b5f6401000276a36001600160a01b03831610801590614155575073fffd8963efd1fc6a506488495d951d5263988d266001600160a01b038316105b61418a5760405162461bcd60e51b81526020600482015260016024820152602960f91b60448201526064015b60405180910390fd5b640100000000600160c01b03602083901b166001600160801b03811160071b81811c6001600160401b03811160061b90811c63ffffffff811160051b90811c61ffff811160041b90811c60ff8111600390811b91821c600f811160021b90811c918211600190811b92831c9790881196179094179092171790911717176080811061421d57607f810383901c9150614227565b80607f0383901b91505b908002607f81811c60ff83811c9190911c800280831c81831c1c800280841c81841c1c800280851c81851c1c800280861c81861c1c800280871c81871c1c800280881c81881c1c800280891c81891c1c8002808a1c818a1c1c8002808b1c818b1c1c8002808c1c818c1c1c8002808d1c818d1c1c8002808e1c9c81901c9c909c1c80029c8d901c9e9d607f198f0160401b60c09190911c6001603f1b161760c19b909b1c6001603e1b169a909a1760c29990991c6001603d1b169890981760c39790971c6001603c1b169690961760c49590951c6001603b1b169490941760c59390931c6001603a1b169290921760c69190911c600160391b161760c79190911c600160381b161760c89190911c6680000000000000161760c99190911c6640000000000000161760ca9190911c6620000000000000161760cb9190911c6610000000000000161760cc9190911c6608000000000000161760cd9190911c66040000000000001617693627a301d71055774c8581026f028f6481ab7f045a5af012a19d003aa9198101608090811d906fdb2df09e81959a81455e260799a0632f8301901d600281810b9083900b1461440757886001600160a01b03166143ec82614416565b6001600160a01b031611156144015781614409565b80614409565b815b9998505050505050505050565b5f805f8360020b1261442b578260020b614432565b8260020b5f035b9050620d89e881111561446b5760405162461bcd60e51b81526020600482015260016024820152601560fa1b6044820152606401614181565b5f816001165f0361448057600160801b614492565b6ffffcb933bd6fad37aa2d162d1a5940015b70ffffffffffffffffffffffffffffffffff16905060028216156144c6576ffff97272373d413259a46990580e213a0260801c5b60048216156144e5576ffff2e50f5f656932ef12357cf3c7fdcc0260801c5b6008821615614504576fffe5caca7e10e4e61c3624eaa0941cd00260801c5b6010821615614523576fffcb9843d60f6159c9db58835c9266440260801c5b6020821615614542576fff973b41fa98c081472e6896dfb254c00260801c5b6040821615614561576fff2ea16466c96a3843ec78b326b528610260801c5b6080821615614580576ffe5dee046a99a2a811c461f1969c30530260801c5b6101008216156145a0576ffcbe86c7900a88aedcffc83b479aa3a40260801c5b6102008216156145c0576ff987a7253ac413176f2b074cf7815e540260801c5b6104008216156145e0576ff3392b0822b70005940c7a398e4b70f30260801c5b610800821615614600576fe7159475a2c29b7443b29c7fa6e889d90260801c5b611000821615614620576fd097f3bdfd2022b8845ad8f792aa58250260801c5b612000821615614640576fa9f746462d870fdf8a65dc1f90e061e50260801c5b614000821615614660576f70d869a156d2a1b890bb3df62baf32f70260801c5b618000821615614680576f31be135f97d08fd981231505542fcfa60260801c5b620100008216156146a1576f09aa508b5b7a84e1c677de54f3e99bc90260801c5b620200008216156146c1576e5d6af8dedb81196699c329225ee6040260801c5b620400008216156146e0576d2216e584f5fa1ea926041bedfe980260801c5b620800008216156146fd576b048a170391f7dc42444e8fa20260801c5b5f8460020b131561471c57805f1981614718576147186151db565b0490505b640100000000810615614730576001614732565b5f5b60ff16602082901c0192505050919050565b5f80546001600160a01b0386168252600260205260409091205460ff9091169062010000900461ffff16158080156147795750815b61490a575f5b83518110156121c057811580156147c957505f6001600160a01b03166147bd8583815181106147b0576147b0614fdf565b602002602001015161099e565b6001600160a01b031614155b156148a2576001600160a01b0387165f90815260026020526040812080545f1961ffff62010000808404821692909201160263ffff0000199091161790558451600390829087908590811061482057614820614fdf565b602002602001015181526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555083818151811061486a5761486a614fdf565b60209081029190910101516040515f9081907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925908290a45b82614902578381815181106148b9576148b9614fdf565b6020026020010151866001600160a01b0316886001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b60010161477f565b505050505050565b6001600160e01b031981168114614927575f80fd5b50565b5f6020828403121561493a575f80fd5b813561494581614912565b9392505050565b5f5b8381101561496657818101518382015260200161494e565b50505f910152565b5f815180845261498581602086016020860161494c565b601f01601f19169290920160200192915050565b602081525f614945602083018461496e565b6001600160a01b0381168114614927575f80fd5b5f80604083850312156149d0575f80fd5b8235915060208301356149e2816149ab565b809150509250929050565b5f602082840312156149fd575f80fd5b5035919050565b5f8060408385031215614a15575f80fd5b8235614a20816149ab565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715614a6a57614a6a614a2e565b604052919050565b5f82601f830112614a81575f80fd5b813560206001600160401b03821115614a9c57614a9c614a2e565b8160051b614aab828201614a42565b9283528481018201928281019087851115614ac4575f80fd5b83870192505b84831015614ae357823582529183019190830190614aca565b979650505050505050565b80358015158114614afd575f80fd5b919050565b5f8060408385031215614b13575f80fd5b82356001600160401b03811115614b28575f80fd5b614b3485828601614a72565b925050614b4360208401614aee565b90509250929050565b5f815180845260208085019450602084015f5b83811015614b845781516001600160a01b031687529582019590820190600101614b5f565b509495945050505050565b606081525f614ba16060830186614b4c565b602083820381850152614bb48287614b4c565b915083820360408501528185518084528284019150828160051b8501018388015f5b83811015614c0457601f19878403018552614bf283835161496e565b94860194925090850190600101614bd6565b50909a9950505050505050505050565b5f60208284031215614c24575f80fd5b8135614945816149ab565b6001600160801b0381168114614927575f80fd5b5f805f8060808587031215614c56575f80fd5b8435614c6181614c2f565b93506020850135614c7181614c2f565b92506040850135614c8181614c2f565b91506060850135614c9181614c2f565b939692955090935050565b5f805f60608486031215614cae575f80fd5b8335614cb9816149ab565b92506020840135614cc9816149ab565b929592945050506040919091013590565b5f805f8060608587031215614ced575f80fd5b8435614cf8816149ab565b93506020850135925060408501356001600160401b0380821115614d1a575f80fd5b818701915087601f830112614d2d575f80fd5b813581811115614d3b575f80fd5b8860208260051b8501011115614d4f575f80fd5b95989497505060200194505050565b602080825282518282018190525f9190848201906040850190845b81811015614d9557835183529284019291840191600101614d79565b50909695505050505050565b602081525f6149456020830184614b4c565b5f8060408385031215614dc4575f80fd5b8235614dcf816149ab565b9150614b4360208401614aee565b5f6001600160401b03821115614df557614df5614a2e565b50601f01601f191660200190565b5f805f8060808587031215614e16575f80fd5b8435614e21816149ab565b93506020850135614e31816149ab565b92506040850135915060608501356001600160401b03811115614e52575f80fd5b8501601f81018713614e62575f80fd5b8035614e75614e7082614ddd565b614a42565b818152886020838501011115614e89575f80fd5b816020840160208301375f6020838301015280935050505092959194509250565b5f8060408385031215614ebb575f80fd5b8235614ec6816149ab565b915060208301356001600160401b03811115614ee0575f80fd5b614eec85828601614a72565b9150509250929050565b5f8060408385031215614f07575f80fd5b82359150614b4360208401614aee565b6001600160a01b038481168252831660208201526060604082018190525f90614f429083018461496e565b95945050505050565b5f8060408385031215614f5c575f80fd5b8235614f67816149ab565b915060208301356149e2816149ab565b5f60208284031215614f87575f80fd5b81516001600160401b03811115614f9c575f80fd5b8201601f81018413614fac575f80fd5b8051614fba614e7082614ddd565b818152856020838501011115614fce575f80fd5b614f4282602083016020860161494c565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215615003575f80fd5b8151614945816149ab565b815181526020808301516001600160a01b0316908201526040808301516001600160801b0390811691830191909152606092830151169181019190915260800190565b5f8060408385031215615062575f80fd5b505080516020909101519092909150565b5f805f60608486031215615085575f80fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b5f52601160045260245ffd5b808201808211156109985761099861509e565b81516001600160a01b03168152610160810160208301516150f160208401826001600160a01b03169052565b506040830151615108604084018262ffffff169052565b50606083015161511d606084018260020b9052565b506080830151615132608084018260020b9052565b5060a083015160a083015260c083015160c083015260e083015160e083015261010080840151818401525061012080840151615178828501826001600160a01b03169052565b505061014092830151919092015290565b5f805f806080858703121561519c575f80fd5b8451935060208501516151ae81614c2f565b6040860151606090960151949790965092505050565b80820281158282048414176109985761099861509e565b634e487b7160e01b5f52601260045260245ffd5b5f826151fd576151fd6151db565b500490565b818103818111156109985761099861509e565b6001600160a01b03858116825284166020820152604081018390526080606082018190525f906152479083018461496e565b9695505050505050565b5f60208284031215615261575f80fd5b815161494581614912565b5f8260020b8061527e5761527e6151db565b808360020b0791505092915050565b600282810b9082900b03627fffff198112627fffff821317156109985761099861509e565b634e487b7160e01b5f52603160045260245ffdfe417070726f76616c28616464726573732c616464726573732c75696e74323536295472616e7366657228616464726573732c616464726573732c75696e7432353629a264697066735822122069d46335cf5f96540b8e9eb83f90e3f81428e4e7c384d4ff3c208ef923e6acea64736f6c63430008180033

Loading...
Loading
Loading...
Loading
[ 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.