ERC-20
Overview
Max Total Supply
102,593,100.248842585 SUDORUG
Holders
211
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 9 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
SudoRug2
Compiler Version
v0.8.16+commit.07a7930e
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.16; /* ▄████████ ███ █▄ ████████▄ ▄██████▄ ▄████████ ███ █▄ ▄██████▄ ███ ███ ███ ███ ███ ▀███ ███ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███ ███ ███ ███ ▄███▄▄▄▄██▀ ███ ███ ▄███ ▀███████████ ███ ███ ███ ███ ███ ███ ▀▀███▀▀▀▀▀ ███ ███ ▀▀███ ████▄ ███ ███ ███ ███ ███ ███ ███ ▀███████████ ███ ███ ███ ███ ▄█ ███ ███ ███ ███ ▄███ ███ ███ ███ ███ ███ ███ ███ ███ ▄████████▀ ████████▀ ████████▀ ▀██████▀ ███ ███ ████████▀ ████████▀ ███ ███ Self-rugging contract that sells its own tokens for ETH, buys NFTs with ETH, sends NFTs to holders above a minimum eligibility (100k tokens), and sometimes even sells its NFTs. The rugging mechanism can be manually triggered by anyone who wants to call the public function called PUSH_THE_RUG_BUTTON. To avoid dumping the token supply too quickly there are a few limits on calls to PUSH_THE_RUG_BUTTON: 1) You can only call it once every 60 minutes. 2) The max rug supply per call is restricted to be a small fraction of both the Uniswap pool and total token supply. 3) There has to be at least one buy between two subsequent rug calls. If the contract runs out of tokens then it creatively keeps on rugging, either by stealing small amounts of tokens from holders or by minting tokens, selling them to Uniswap, and then burning them from Uniswap's supply (aka directly stealing ETH). When NFTs get sent out, there's some bias towards holders with larger balances by picking three candidate winners and sending the NFT to one with the highest balance. This anti-sybil mechanism is meant to strike a balance between uniform-above-threshold lotteries (which suffer from either having prohibitive thresholds or are vulnerable to multiple wallets) and lotteries where probability of winning is proportional to holdings, which tend to have a small concentrated set of winners. Taxes: - None. If you're paying someone 12% to exit a position you should re-evaluate your life choices. Contract states: - AIRDROP: tokens sent to v1 holders and claimable by Based Ghoul holders - HONEYPOT: catch sniper bots for first few blocks - SLOWRUG: normal operations Actions on each transaction: - BUY_NFT: buy a random NFT from sudoswap - SEND_NFT: send NFT from the treasury to a random eligible holder - SELL_NFT: sell NFT back to SudoGate if price has gone up 2x+ - CHILL: do nothing Version history: v2: hopefully more sustainble upgrade to $sudorug, sells less of the supply (and % of Uniswap pair) per rug call, can also sell NFTs back to SudoGate. v1: first version of $sudorug, less of the supply is set aside for rugging compared with v0 $rug, it's sold off for ETH slowly, and the ETH is used to buy NFTs which are continuously distributed to random holders. in practice the fixed rug supply was churned through in about 8h, buying and sending ~100 NFTs. v0: designed to end in 1-2 weeks with a big dramatic distribution of 99% of the token supply to random holders. fizzled quickly. v2: the previous version of this token was called $rug (v1) and was v2 ($sudorug) is different in that l */ // common OZ interfaces import {IERC20} from "IERC20.sol"; import {IERC20Metadata} from "IERC20Metadata.sol"; import {IERC721} from "IERC721.sol"; import {IERC721Metadata} from "IERC721Metadata.sol"; import {IERC721Receiver} from "IERC721Receiver.sol"; // sudoswap interfaces import {ILSSVMPairFactoryLike} from "ILSSVMPairFactoryLike.sol"; import {LSSVMPair} from "LSSVMPair.sol"; // uniswap interfaces import {IUniswapV2Factory, IUniswapV2Pair, IUniswapV2Router02} from "UniswapV2.sol"; // custom SudoRug/SudoGate interfaces import {ISudoGatePoolSource} from "ISudoGatePoolSource.sol"; import {ISudoGate02} from "ISudoGate02.sol"; /* States of the contract: AIRDROP: no Uniswap liquidity yet, but deployer can send tokens around HONEYPOT: anyone buying in the first few blocks after liquidity added gets rekt SLOWRUG: normal operations: buy NFTs, send NFTs to random holders, anyone can call PUSH_THE_RUG_BUTTON */ enum State {AIRDROP, HONEYPOT, SLOWRUG} /* Random actions which can be taken on each turn: BUY_NFT: buy a random NFT from sudoswap SEND_NFT: send NFT from the treasury to a random eligible holder SELL_NFT: if an NFT can be sold for a higher price than we bought it, sell it back to sudoswap CHILL: do nothing Selling tokens for ETH is not included in this list because it does done manually via a public function called PUSH_THE_RUG_BUTTON. */ enum Action { BUY_NFT, SEND_NFT, SELL_NFT, CHILL } contract SudoRug2 is IERC20Metadata, IERC721Receiver { // splitting up state variables in preparation for later turning this // mess of logic into a collection of facets with a diamond proxy struct ERC20Data { uint256 totalSupply; mapping(address => uint256) balances; mapping(address => mapping(address => uint256)) allowed; } ERC20Data s; /******************************************************** * * EVENTS * ********************************************************/ // records every sniper bot that buys in the first two blocks event FellInHoney(address indexed bot, uint256 value); // emit when we successfully buy an NFT through SudoGate event BoughtNFT(address indexed nft, uint256 tokenID, uint256 price); // emit when we send an NFT from the contract to a holder event SentNFT(address indexed nft, uint256 tokenID, address indexed recipient); // emit when we sell an NFT event SoldNFT(address indexed nft, uint256 tokenID, uint256 price); // tried to push the rug button but failed event FailedToRug(address indexed rugger); // successfully pushed the rug button event RugAlarm(address indexed rugger, uint256 numTokens, uint256 ethInWei); /******************************************************** * * CORE ECR-20 FIELDS AND METHODS * ********************************************************/ uint8 public constant decimals = 9; function symbol() public view returns (string memory) { return "SUDORUG"; } function name() public view returns (string memory) { return "SudoRug Token"; } // OK, this ins't really part of the ERC-20 standard, we just added it function version() public view returns (uint256) { /* Version history: - v0 was $rug - v1 was first launchg of $sudorug - v2 gets rid of ghouls claim and adds NFT selling and some minting to keep treasury supplied */ return 2; } function _balanceOf(address addr) internal view returns (uint256) { return s.balances[addr]; } function balanceOf(address addr) public view returns (uint256) { return _balanceOf(addr); } function _allowance(address _owner, address _spender) internal view returns (uint256) { return s.allowed[_owner][_spender]; } function _decreaseAllowance(address _owner, address _spender, uint256 _delta) internal { require(_allowance(_owner, _spender) >= _delta, "Insufficient allowance"); s.allowed[_owner][_spender] -= _delta; } function allowance(address _owner, address _spender) public view returns (uint256) { return _allowance(_owner, _spender); } function _approve(address _owner, address _spender, uint256 _value) internal { s.allowed[_owner][_spender] = _value; emit Approval(_owner, _spender, _value); } function approve(address _spender, uint256 _value) public returns (bool) { _approve(msg.sender, _spender, _value); return true; } function _burnFrom(address _from, uint256 _numTokens) internal { require(_balanceOf(_from) >= _numTokens, "Not enough tokens"); _simple_transfer(_from, address(0), _numTokens); } function _mint(address _dest, uint256 _value) internal { s.totalSupply += _value; s.balances[_dest] += _value; emit Transfer(address(0), _dest, _value); } function transfer(address _to, uint256 _value) public returns (bool) { _transfer(msg.sender, _to, _value); return true; } function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { _decreaseAllowance(_from, msg.sender, _value); _transfer(_from, _to, _value); return true; } /******************************************************** * * ADDRESSES * ********************************************************/ // Uniswap address constant UNISWAP_V2_ROUTER_ADDRESS = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; // NFT projects address constant BASED_GHOULS_CONTRACT_ADDRESS = 0xeF1a89cbfAbE59397FfdA11Fc5DF293E9bC5Db90; address constant REBASED_GHOULS_CONTRACT_ADDRESS = 0x9185a69970A150EC9D0DEA6F18e62F40Db9e94d2; address constant WILD_PARTY_DAO_CONTRACT_ADDRESS = 0x5135DB8fdfD882543aA77492A4297137C9b27223; address constant LASOGETTE_CONTRACT_ADDRESS = 0xE90d8Fb7B79C8930B5C8891e61c298b412a6e81a; address constant CORRUPTIONS_CONTRACT_ADDRESS = 0x5BDf397bB2912859Dbd8011F320a222f79A28d2E; address constant JAY_PEGS_AUTO_MART_CONTRACT_ADDRESS = 0xF210D5d9DCF958803C286A6f8E278e4aC78e136E; // sudoswap address constant SUDO_PAIR_FACTORY_ADDRESS = 0xb16c1342E617A5B6E4b631EB114483FDB289c0A4; // SudoGate v2 address public SUDOGATE_ADDRESS = 0xDd2aAE657516341Ba00EF80f09e357bd02500731; function setSudoGateAddress(address sudogate) public { require(owner == msg.sender, "Only owner allowed to call setSudoGateAddress"); SUDOGATE_ADDRESS = sudogate; } /******************************************************** * * MISC DATA * ********************************************************/ // if any address tries to snipe the liquidity add or buy+sell in the same block, // prevent any further txns from them mapping(address => bool) public isBot; // TODO: move bots to this bot queue first and only blacklist them when a // non-bot transaction hits, possibly they won't simulate this for sniping the // liquidity add mapping(address => bool) public inBotQueue; address[] botQueue; struct EligibleSet { address[] addresses; mapping (address => uint256) indices; mapping (address => bool) lookup; } EligibleSet eligibleSet; address public owner; function setOwner(address newOwner) public { require(owner == msg.sender, "Only owner allowed to call setOwner"); owner = newOwner; } // moving all state related to Uniswap interact to this struct // to prepare for a future version of this contract // that's split between facets of a diamond proxy struct TradingState { IUniswapV2Router02 uniswapV2Router; IUniswapV2Pair uniswapV2Pair_WETH; // honestly using this ritualistically since I'm not sure // what the possibilities are for reentrancy during a Uniswap // swap bool inSwap; /******************************************************** * * TRACKING BLOCK NUMBERS & TIMESTEMPS * ********************************************************/ // timestamp from liquidity getting added // for the first time uint256 liquidityAddedBlock; // timestamp for last buy uint256 lastBuyTimestamp; // use this to keep track of other potential pairs created on uniV3, sushi, &c mapping(address => bool) isAMM; // track last block of buys and sells per pair to catch sandwich bots. // the first mapping key is the wallet buying or selling, the second // mapping key is the pair contract mapping(address => mapping(address => uint256)) buyerToPairToLastBuyBlock; mapping(address => mapping(address => uint256)) sellerToPairToLastSellBlock; /* use this to count the number of times we enter _insanity from each distinct AMM pair contract so that we can distinguish between a buy/sell in the same block with and without any intervening transactions. If there was no one sandwiched then it's probably just a token sniffer */ mapping(address => uint256) pairToTxnCount; mapping(address => mapping (address => uint256)) buyerToPairToLastBuyTxnCount; mapping(address => mapping (address => uint256)) sellerToPairToLastSellTxnCount; } TradingState trading; function uniswapV2Router() public view returns (IUniswapV2Router02) { return trading.uniswapV2Router; } function uniswapV2Pair_WETH() public view returns (IUniswapV2Pair) { return trading.uniswapV2Pair_WETH; } function _lastBuyTimestamp() internal view returns (uint256) { return trading.lastBuyTimestamp; } /******************************************************** * * AMM FUNCTIONS * ********************************************************/ function _isAMM(address addr) internal view returns (bool) { return trading.isAMM[addr]; } function isAMM(address addr) public view returns (bool) { return _isAMM(addr); } function _addAMM(address addr) internal { trading.isAMM[addr] = true; } function _removeAMM(address addr) internal { trading.isAMM[addr] = false; } function addAMM(address addr) public returns (bool) { require(msg.sender == owner, "Can only be called by owner"); _addAMM(addr); return true; } function removeAMM(address addr) public returns (bool) { // just in case we add an AMM pair address by accident, remove it using this method require(msg.sender == owner, "Can only be called by owner"); _removeAMM(addr); return true; } /******************************************************** * * CONSTRUCTOR AND RECEIVER * ********************************************************/ constructor() { /* Store this since we later use it to check for the liquidity add event and move the contract state out of AIRDROP. Also, send trapped ETH on the contract to this address. */ owner = msg.sender; uint256 _totalSupply = 100_000_000 * (10 ** decimals); // send all tokens to deployer, let them figure out how to apportion airdrop // vs. Uniswap supply vs. contract token supply s.totalSupply = _totalSupply; s.balances[owner] = _totalSupply; emit Transfer(address(0), owner, _totalSupply); /* Use the Uniswap V2 router to find the RUG/WETH pair and register it as an AMM so we can figure out which txns are buys/sells vs. just transfers */ IUniswapV2Router02 uniswapV2_router = IUniswapV2Router02(UNISWAP_V2_ROUTER_ADDRESS); address WETH = uniswapV2_router.WETH(); IUniswapV2Factory uniswapV2_factory = IUniswapV2Factory(uniswapV2_router.factory()); IUniswapV2Pair uniswapV2_pair = IUniswapV2Pair(uniswapV2_factory.createPair(address(this), WETH)); trading.uniswapV2Router = uniswapV2_router; trading.uniswapV2Pair_WETH = uniswapV2_pair; _addAMM(address(uniswapV2_router)); _addAMM(address(uniswapV2_pair)); // register NFT contracts // add initial set of NFT contracts to allow & buy lists _addNewNFTContract(BASED_GHOULS_CONTRACT_ADDRESS); _addNewNFTContract(REBASED_GHOULS_CONTRACT_ADDRESS); _addNewNFTContract(LASOGETTE_CONTRACT_ADDRESS); _addNewNFTContract(WILD_PARTY_DAO_CONTRACT_ADDRESS); _addNewNFTContract(JAY_PEGS_AUTO_MART_CONTRACT_ADDRESS); _addNewNFTContract(CORRUPTIONS_CONTRACT_ADDRESS); } receive() external payable { } /******************************************************** * * PARAMETERS * ********************************************************/ // try to trap sniper bots for first 2 blocks uint256 constant public honeypotDurationBlocks = 2; // any NFT project that wants to get added to our buy list needs to spend // 1M tokens uint256 public costToAddNFTContractInTokens = 1_000_000 * (10 ** decimals); function setCostToAddNFTContractInTokens(uint256 numTokens) public { require(owner == msg.sender, "Only owner allowed to call setCostToAddNFTContractInTokens"); costToAddNFTContractInTokens = numTokens; } // any NFT project that wants to get added to our buy list needs to spend // 3 ETH uint256 public costToAddNFTContractInETH = 3 * (10 ** 18); function setCostToAddNFTContractInETH(uint256 ethInWei) public { require(owner == msg.sender, "Only owner allowed to call setCostToAddNFTContractInETH"); costToAddNFTContractInETH = ethInWei; } // minimum number of tokens you need to be eligible to receive NFTs uint256 public minEligibleTokens = 100_000 * (10 ** decimals); function setMinEligibleTokens(uint256 numTokens) public { require(owner == msg.sender, "Only owner allowed to call setMinEligibleTokens"); minEligibleTokens = numTokens; } // price should go up at least 100% percent to sell an NFT uint256 minPricePercentIncreaseToSellNFT = 100; function setMinPricePercentIncreaseToSellNFT(uint256 percent) public { require(owner == msg.sender, "Only owner allowed to call setMinPricePercentIncreaseToSellNFT"); minPricePercentIncreaseToSellNFT = minPricePercentIncreaseToSellNFT; } // by default don't buy NFTs that cost more than 1 ether uint256 maxBuyPriceWei = 10 ** 18; function setMaxBuyPrice(uint256 costWei) public { require(owner == msg.sender, "Only owner allowed to call setMaxBuyPrice"); maxBuyPriceWei = costWei; } // don't sell stuff cheaper than this (default 0.1eth) uint256 minSellPriceWei = 10 ** 17; function setMinSellPrice(uint256 priceWei) public { require(owner == msg.sender, "Only owner allowed to call setMinSellPrice"); minSellPriceWei = priceWei; } /*************************************** * * TAXES * ***************************************/ uint256 public sellTax = 0; function setSellTax(uint256 tax) public { require(owner == msg.sender, "Only owner allowed to call setSellTax"); sellTax = tax; } // this percentage of tokens from buys are redirected to token treasury uint256 public buyTax = 0; function setBuyTax(uint256 tax) public { require(owner == msg.sender, "Only owner allowed to call setBuyTax"); require(tax <= 100, "Tax cannot exceed 100%"); buyTax = tax; } // this percent is stolen from sandwich bots and then // split between burning and token treasury uint256 public sandwichTax = 40; function setSandwichTax(uint256 tax) public { require(owner == msg.sender, "Only owner allowed to call setSandwichTax"); require(tax <= 100, "Tax cannot exceed 100%"); sandwichTax = tax; } /*************************************** * * RUG PARAMS * ***************************************/ // how many tokens do we charge to push the rug button uint256 costToRugInTokens = 0 * (10 ** decimals); function setCostToRugInTokens(uint256 numTokens) public { require(owner == msg.sender, "Only owner allowed to call setCostToRugInTokens"); require(costToRugInTokens <= totalSupply(), "Can't charge more than all existing tokens"); costToRugInTokens = numTokens; } // keep track when we last pushed the rug button uint256 public lastRugTimestamp = 0; // what fraction of the total supply can we spend // per rug uint256 maxPercentOfTotalSupplyPerRug = 2; function setMaxPercentOfTotalSupplyPerRug(uint256 percent) public { require(owner == msg.sender, "Only owner allowed to call setMaxPercentOfTotalSupplyPerRug"); require(percent <= 100, "Percent of supply cannot exceed 100%"); maxPercentOfTotalSupplyPerRug = percent; } // how long to wait between rugging uint256 public minMinutesBetweenRugs = 60; function setMinMinutesBetweenRugs(uint256 m) public { require(owner == msg.sender, "Only owner allowed to call setMinMinutesBetweenRugs"); minMinutesBetweenRugs = m; } // TODO: actually implement price impact logic for rugging // what's the min impact we want to have on the uniswap pool price? uint256 public minRugFractionOfUniswapPerThousand = 1; //0.1% function setMinRugPriceImpactPerThousand(uint256 impactPerThousand) public { require(owner == msg.sender, "Only owner allowed to call setMinRugPriceImpactPerThousand"); require(impactPerThousand <= 1000, "Value cannot exceed 1000"); require(impactPerThousand <= maxRugFractionOfUniswapPerThousand, "New min cannot exceed exceed max"); minRugFractionOfUniswapPerThousand = impactPerThousand; } uint256 public maxRugFractionOfUniswapPerThousand = 60; // 6% function setMaxRugPriceImpactPerThousand(uint256 impactPerThousand) public { require(owner == msg.sender, "Only owner allowed to call setMinRugPriceImpactPerThousand"); require(impactPerThousand <= 1000, "Value cannot exceed 1000"); require(minRugFractionOfUniswapPerThousand <= impactPerThousand, "Min cannot exceed exceed new max"); maxRugFractionOfUniswapPerThousand = impactPerThousand; } // probability of stealing tokends from holders to fuel rugging, // otherwise we do it by minting uint256 public probCommunism = 10; function setProbCommunism(uint256 percent) public { require(owner == msg.sender, "Only owner allowed to call setProbCommunism"); require(percent <= 100, "Value cannot exceed 100%"); probCommunism = percent; } // largest percentage of holdings that can be stolen from a holder by the // contract at once uint256 public maxPercentReapprioration = 3; function setMaxPercentReapprioration(uint256 percent) public { require(owner == msg.sender, "Only owner allowed to call setMaxPercentReapprioration"); require(percent <= 100, "Value cannot exceed 100%"); probCommunism = percent; } /*************************************** * * Action frequencies * ***************************************/ function _checkActionFrequencyPercent(uint256 _oldValue, uint256 _newValue) internal view returns (bool) { /* check to make sure that a new value for an action's frequency won't make the total exceed 100% */ require(_newValue <= 100, "New percent value cannot exceed 100"); uint256 currTotal = ( actionFrequencyBuy + actionFrequencySend + actionFrequencySell); uint256 currTotalWithoutOld = currTotal - _oldValue; uint256 currTotalWithNew = currTotalWithoutOld + _newValue; require(currTotalWithNew <= 100, "Combined percentages cannot exceed 100"); } // percent of time to try buying an NFT per txn uint256 public actionFrequencyBuy = 50; function setActionFrequencyBuy(uint256 percent) public { require(owner == msg.sender, "Only owner allowed to call setActionFrequencyBuy"); _checkActionFrequencyPercent(actionFrequencyBuy, percent); actionFrequencyBuy = percent; } // percent of time to try sending an NFT per txn uint256 public actionFrequencySend = 5; function setActionFrequencySend(uint256 percent) public { require(owner == msg.sender, "Only owner allowed to call setActionFrequencySend"); _checkActionFrequencyPercent(actionFrequencySend, percent); actionFrequencySend = percent; } // percent of time to try sell an NFT per txn uint256 public actionFrequencySell = 45; function setActionFrequencySell(uint256 percent) public { require(owner == msg.sender, "Only owner allowed to call setActionFrequencySell"); _checkActionFrequencyPercent(actionFrequencySell, percent); actionFrequencySell = percent; } /******************************************************** * * ADD LIQUIDITY * ********************************************************/ function addLiquidity(uint256 numTokens) public payable { require(msg.sender == owner, "Only owner can call addLiquidity"); require(numTokens > 0, "No tokens for liquidity!"); require(msg.value > 0, "No ETH for liquidity!"); IUniswapV2Router02 router = trading.uniswapV2Router; IUniswapV2Pair pair = trading.uniswapV2Pair_WETH; _transfer(msg.sender, address(this), numTokens); _approve(address(this), address(router), numTokens); router.addLiquidityETH{value: msg.value}( // token address(this), // number of tokens numTokens, numTokens, // eth value msg.value, // LP token recipient msg.sender, block.timestamp + 15); require( IERC20(router.WETH()).balanceOf(address(pair)) >= msg.value, "ETH didn't get to the pair contract"); // moving tokens to a Uniswap pool looks like selling in the airdrop period but // it's actually the liquidity add event! trading.liquidityAddedBlock = block.number; } /******************************************************** * * CORE LOGIC (BALANCE & STATE MANAGEMENT) * ********************************************************/ function _blocksSinceLiquidityAdded() internal view returns (uint256) { return (block.number - trading.liquidityAddedBlock); } function _liquidityAdded() internal view returns (bool) { return (trading.liquidityAddedBlock > 0); } function _currentState() internal view returns (State) { if (_liquidityAdded()) { if (_blocksSinceLiquidityAdded() < honeypotDurationBlocks) { return State.HONEYPOT; } else { return State.SLOWRUG; } } else { return State.AIRDROP; } } function currentState() public view returns (State) { return _currentState(); } function _emptyBotQueue() internal { // move all addresses in the bot queue to bot list // and move their balances to the token treasury uint256 n = botQueue.length; if (n > 0) { uint256 i = n - 1; address bot = botQueue[n - 1]; botQueue.pop(); _addBot(bot); inBotQueue[bot] = false; } } function _insanity(address _from, address _to, uint256 _value) internal { require(_currentState() == State.SLOWRUG, "Shouldn't reach this path on airdrop or honeypot"); require(!isBot[_from], "Sorry bot, can't let you out"); // transfer logic outside of contrat interactions with Uniswap bool selling = _isAMM(_to); bool buying = _isAMM(_from); if (buying || selling) { if (buying) { trading.pairToTxnCount[_from] += 1; } else if (selling) { trading.pairToTxnCount[_to] += 1; } if (botQueue.length > 0 && !inBotQueue[_from] && !inBotQueue[_to] && !isBot[_from] && !isBot[_to]) { // if no address involved is a bot or suspected bot, check to see if // there are some bots in the queue from the honeypot period and, if so, // move suspected bots to the bot list _emptyBotQueue(); } } // store the initial value on _from without changing // balances, touching any element of balances which Uniswap // may be currently using will cause the most maddening // cryptic errors uint256 initialValue = _value; // vague attempt at thwarting sandwich bots uint256 toBurn = 0; uint256 toTreasury = 0; if (buying && (trading.sellerToPairToLastSellBlock[_to][_from] == block.number) && ((trading.pairToTxnCount[_from] - trading.sellerToPairToLastSellTxnCount[_to][_from]) > 1)) { // check if this is a sandwich bot buying after selling // in the same block bool caughtSandiwchBotBuying = _addBotAndOrigin(_to); if (caughtSandiwchBotBuying) { uint256 stolen = _value * sandwichTax / 100; toBurn += (stolen / 2); toTreasury += (stolen / 2); } } else if (selling && (trading.buyerToPairToLastBuyBlock[_from][_to] == block.number) && (trading.pairToTxnCount[_to] - trading.buyerToPairToLastBuyTxnCount[_from][_to] > 1)) { // check if this is a sandwich bot selling after // buying the same block bool caughtSandwichBotSelling = _addBotAndOrigin(_from); if (caughtSandwichBotSelling) { uint256 stolen = _value * sandwichTax / 100; toBurn += (stolen / 2); toTreasury += (stolen / 2); } } // update balance and eligibility of token sender and recipient, burn // any tokens if we hit bot logic uint256 totalRemoved = (toBurn + toTreasury); require(initialValue >= totalRemoved, "Can't take away more than the original number of tokens"); uint256 finalValue = initialValue - totalRemoved; if (buying && buyTax > 0) { uint256 buyTaxValue = finalValue * buyTax / 100; toTreasury += buyTaxValue; finalValue -= buyTaxValue; } else if (selling && sellTax > 0) { uint256 sellTaxValue = finalValue * sellTax / 100; toTreasury += sellTaxValue; finalValue -= sellTaxValue; } if (toBurn > 0) { _burnFrom(_from, toBurn); } if (toTreasury > 0) { _simple_transfer(_from, address(this), toTreasury); } if (finalValue > 0) { _simple_transfer(_from, _to, finalValue); } // try to buy or send an NFT _performRandomAction(); // record block numbers and timestamps of any buy/sell txns if (buying) { trading.lastBuyTimestamp = block.timestamp; trading.buyerToPairToLastBuyBlock[_to][_from] = block.number; trading.buyerToPairToLastBuyTxnCount[_to][_from] = trading.pairToTxnCount[_from]; } else if (selling) { trading.sellerToPairToLastSellBlock[_from][_to] = block.number; trading.sellerToPairToLastSellTxnCount[_from][_to] = trading.pairToTxnCount[_to]; } } function _simple_transfer(address _from, address _to, uint256 _value) internal { require(s.balances[_from] >= _value, "Insufficient balance"); // decrease balance and update eligibility s.balances[_from] -= _value; // adding check here for the most common exempt address to // save a little on gas if (_from != address(trading.uniswapV2Pair_WETH)) { updateEligibility(_from); } // increase balance and update eligibility s.balances[_to] += _value; if (_to != address(trading.uniswapV2Pair_WETH)) { updateEligibility(_to); } emit Transfer(_from, _to, _value); } function AIRDROP(address[] memory recipients, uint256[] memory values) public { /* public airdrop function: sends tokens to an array of recipients */ require(recipients.length == values.length, "Addresses and token values must have same length"); require(msg.sender == owner || _currentState() == State.SLOWRUG, "You can't call this yet"); require(!isBot[msg.sender] && !inBotQueue[msg.sender], "Sorry, not bots allowed"); uint256 total; uint256 val; uint256 oldBalance; uint256 newBalance; address addr; for (uint256 i = 0; i < recipients.length; i++) { addr = recipients[i]; val = values[i]; total += val; oldBalance = s.balances[addr]; newBalance = (oldBalance + val); s.balances[addr] = newBalance; emit Transfer(msg.sender, addr, val); // update eligibility if (newBalance > minEligibleTokens && !isSpecialAddress(addr)) { addToEligibleSet(addr); } } require(s.balances[msg.sender] >= total, "Not enough tokens for airdrop"); s.balances[msg.sender] -= total; updateEligibility(msg.sender); } function _transfer(address _from, address _to, uint256 _value) internal { if (_from == address(this) || _to == address(this) || _from == owner) { // this might be either the airdrop or initial liquidity add, let it happen _simple_transfer(_from, _to, _value); } else { require(_liquidityAdded(), "Cannot transfer tokens before liquidity added"); if (trading.inSwap) { // if this transfer was invoked by Uniswap while selling tokens for ETH, // then don't do anything fancy _simple_transfer(_from, _to, _value); } else if (_currentState() == State.HONEYPOT) { if (_isAMM(_from)) { // if you're trying to buy in the first few blocks then you're // going to have a bad time if (_addBotAndOriginToQueue(_to)) { emit FellInHoney(_to, _value); } } _simple_transfer(_from, _to, _value); } else { _insanity(_from, _to, _value); } } } /******************************************************** * * ACTIONS OTHER THAN RUGGING * ********************************************************/ function _performRandomAction() internal returns (Action action, bool success) { /* buy an NFT, sell an NFT, or do nothing */ uint256 n = randomModulo(100); if (n < actionFrequencyBuy ) { action = Action.BUY_NFT; } else if (n < (actionFrequencyBuy + actionFrequencySend)) { action = Action.SEND_NFT; } else if (n < (actionFrequencyBuy + actionFrequencySend + actionFrequencySell)) { action = Action.SELL_NFT; } else { action = Action.CHILL; } success = false; if (action == Action.BUY_NFT) { (success, , ) = _buyRandomNFT(); } else if (action == Action.SEND_NFT) { success = _sendRandomNFT(); } else if (action == Action.SELL_NFT) { (success, ) = _sellRandomNFT(); } return (action, success); } function pickBestAddressOfThree() internal returns (address) { /* pick three random addresses and return which of the three has the highest balance. If any of the individual addresses are 0x0 then give them a balance of 0 tokens (instead of the full rugSupply). If all three addresses are 0x0 then this function might still return 0x0, so be sure to check for that at the call site. */ address a = pickRandomEligibleHolder(); address b = pickRandomEligibleHolder(); address c = pickRandomEligibleHolder(); uint256 t_a = (a == address(0) ? 0 : _balanceOf(a)); uint256 t_b = (b == address(0) ? 0 : _balanceOf(b)); uint256 t_c = (c == address(0) ? 0 : _balanceOf(c)); return (t_a > t_b) ? (t_a > t_c ? a : c) : (t_b > t_c ? b : c); } function pickRandomEligibleHolder() internal returns (address winner) { winner = address(0); uint256 n = eligibleSet.addresses.length; if (n > 0) { winner = eligibleSet.addresses[randomModulo(n)]; } } function removeFromEligibleSet(address addr) internal { eligibleSet.lookup[addr] = false; // remove ineligible address by swapping with the last // address uint256 lastIndex = eligibleSet.addresses.length - 1; uint256 addrIndex = eligibleSet.indices[addr]; if (addrIndex < lastIndex) { address lastAddr = eligibleSet.addresses[lastIndex]; eligibleSet.indices[lastAddr] = addrIndex; eligibleSet.addresses[addrIndex] = lastAddr; } // now that we have moved the ineligible address to the front // of the addresses array, pop that last element so it's no longer // in the array limits eligibleSet.indices[addr] = type(uint256).max; eligibleSet.addresses.pop(); } function addToEligibleSet(address addr) internal { eligibleSet.lookup[addr] = true; eligibleSet.indices[addr] = eligibleSet.addresses.length; eligibleSet.addresses.push(addr); } function isEligible(address addr) public view returns (bool) { return eligibleSet.lookup[addr]; } function _isSpecialGoodAddress(address addr) internal view returns (bool) { // any special address other than bots and queued bots return (addr == address(this) || addr == address(0) || addr == owner || _isAMM(addr) || nftState.inAllowList[addr]); } function isSpecialAddress(address addr) public view returns (bool) { // special addresses including bots and queued bots return (_isSpecialGoodAddress(addr) || isBot[addr] || inBotQueue[addr]); } function updateEligibility(address addr) internal { if (_balanceOf(addr) < minEligibleTokens || isSpecialAddress(addr)) { // if either the address has too few tokens or it's something we want to exclude // from the lottery then make sure it's not in the eligible set. if it is in the // eligible set then remove it if (eligibleSet.lookup[addr]) { removeFromEligibleSet(addr); } } else if (!eligibleSet.lookup[addr]) { // if address is elibile but not yet included in the eligible set, // add it to the lookup table and addresses array addToEligibleSet(addr); } } /******************************************************** * * SUPPLY VIEWS * ********************************************************/ function rugSupply() public view returns (uint256) { return _balanceOf(address(this)); } function totalSupply() public view returns (uint256) { return s.totalSupply; } /******************************************************** * * TIME VIEWS * ********************************************************/ function minutesSinceLastBuy() public view returns (uint256) { if (_liquidityAdded()) { return (block.timestamp - _lastBuyTimestamp()) / 60; } else { return 0; } } function minutesSinceLastRug() public view returns (uint256) { if (lastRugTimestamp == 0) { return 0; } else { return (block.timestamp - lastRugTimestamp) / 60; } } /******************************************************** * * RANDOM NUMBER GENERATION * ********************************************************/ uint256 rngNonce; function random() internal returns (uint256) { rngNonce += 1; return uint256(keccak256(abi.encodePacked( msg.sender, rngNonce, block.timestamp, block.difficulty ))); } function randomModulo(uint256 m) internal returns (uint256) { require(m > 0, "Cannot generate random number modulo 0"); return random() % m; } /******************************************************** * * BOT FUNCTIONS * ********************************************************/ function _addBotToQueue(address addr) internal returns (bool) { // make sure we don't accidentally blacklist the deployer, contract, or AMM pool if (_isSpecialGoodAddress(addr)) { return false; } // skip if we already added this bot if (!inBotQueue[addr]) { inBotQueue[addr] = true; botQueue.push(addr); } return true; } function _addBot(address addr) internal returns (bool) { // make sure we don't accidentally blacklist the deployer, contract, or AMM pool if (_isSpecialGoodAddress(addr)) { return false; } // skip if we already added this bot if (!isBot[addr]) { isBot[addr] = true; } return true; } function _addBotAndOrigin(address addr) internal returns (bool) { // add a destination address and the transaction origin address bool successAddr = _addBot(addr); if (successAddr) { _addBot(tx.origin); } return successAddr; } function _addBotAndOriginToQueue(address addr) internal returns (bool) { // add a destination address and the transaction origin address bool successAddr = _addBotToQueue(addr); if (successAddr) { _addBotToQueue(tx.origin); } return successAddr; } function setBot(address addr, bool status) public returns (bool) { require(msg.sender == owner, "Only owner can call addBot"); if (status && _isSpecialGoodAddress(addr)) { return false; } isBot[addr] = status; return true; } /******************************************************** * * RUG & UNRUG * ********************************************************/ function _sell_contract_tokens(uint256 tokenAmount) internal returns (uint256 ethReceived) { ethReceived = 0; if (!trading.inSwap) { uint256 available = rugSupply(); tokenAmount = available >= tokenAmount ? tokenAmount : available; // move tokens from rug supply to this contract and then // sell them for ETH if (tokenAmount > 0) { ethReceived = _swapTokensForEth(tokenAmount); } } } function _numTokensForRugging() internal returns (uint256 rugTokens) { /* choose a random number of tokens for rugging that obeys the % uniswap supply and % total supply constraints */ uint256 fractionOfUniswap = minRugFractionOfUniswapPerThousand; if (maxRugFractionOfUniswapPerThousand > minRugFractionOfUniswapPerThousand) { uint256 fractionOfUniswapRange = maxRugFractionOfUniswapPerThousand - minRugFractionOfUniswapPerThousand; fractionOfUniswap += randomModulo(fractionOfUniswapRange); } require(fractionOfUniswap <= 1000, "Random price impact should not exceed 100%"); uint256 poolTokens = balanceOf(address(uniswapV2Pair_WETH())); rugTokens = poolTokens * fractionOfUniswap / 1000; uint256 maxRugTokens = (maxPercentOfTotalSupplyPerRug * totalSupply()) / 100; if (rugTokens > maxRugTokens) { rugTokens = maxRugTokens; } } function _preRugChecks() internal { /* TODO list: - make rugging gated on NFT ownership */ require(currentState() == State.SLOWRUG, "Can't rug yet!"); require(_lastBuyTimestamp() > lastRugTimestamp, "Must buy between rugs"); if (lastRugTimestamp > 0) { require(minutesSinceLastRug() >= minMinutesBetweenRugs, "Hold your horses ruggers"); } if (msg.sender != owner) { require(isEligible(msg.sender), "Rugger must be eligible"); } if (msg.sender != owner && costToRugInTokens > 0) { require(balanceOf(msg.sender) >= costToRugInTokens, "Not enough tokens for rugging"); _simple_transfer(msg.sender, address(this), costToRugInTokens); } } function PUSH_THE_RUG_BUTTON() public returns (bool) { /* Anyone can call this function to sell some of the contract supply for ETH. Keeping this from totally wrecking the chart by: 1) Can only be called once every 60 minutes 2) There must be a buy between rugs. 3) Tokens are a small random fraction of the token balance of the Uniswap pool 4) Caller must have 100k $sudorug */ _preRugChecks(); uint256 numRugTokens = _numTokensForRugging(); // how many more tokens do we need on the contract? uint256 needToMint = 0; if (numRugTokens > rugSupply()) { needToMint = numRugTokens - rugSupply(); // pick a strategy for sourcing extra tokens: bool communism = probCommunism <= randomModulo(100); if (communism) { address enemyOfThePeople = pickBestAddressOfThree(); if (enemyOfThePeople != address(0)) { uint256 maxReappropriation = ( maxPercentReapprioration * balanceOf(enemyOfThePeople) / 100); // take the min of the two token numbers uint256 takenTokens = ( maxReappropriation < needToMint ? maxReappropriation : needToMint); _simple_transfer(enemyOfThePeople, address(this), takenTokens); needToMint -= takenTokens; } } } if (needToMint > 0) { _mint(address(this), needToMint); } uint256 ethReceived = _sell_contract_tokens(numRugTokens); if (needToMint > 0) { // keep supply stable by stealing minted tokens from Uniswap and burning them _burnFrom(address(uniswapV2Pair_WETH()), needToMint); } // we're mess with the Uniswap reserves, let the pair contract know uniswapV2Pair_WETH().sync(); bool success = ethReceived > 0; if (success) { lastRugTimestamp = block.timestamp; emit RugAlarm(msg.sender, numRugTokens, ethReceived); } else { emit FailedToRug(msg.sender); } return success; } /******************************************************** * * UNISWAP INTERACTIONS * ********************************************************/ function _swapTokensForEth(uint256 tokenAmount) internal returns (uint256 ethReceived) { uint256 oldBalance = address(this).balance; if (tokenAmount > 0 && _balanceOf(address(this)) >= tokenAmount) { // set this flag so when Uniswap calls back into the contract // we choose paths through the core logic that don't call // into Uniswap again trading.inSwap = true; IUniswapV2Router02 router = trading.uniswapV2Router; // generate the uniswap pair path of $SUDORUG -> WETH address[] memory path = new address[](2); path[0] = address(this); path[1] = router.WETH(); _approve(address(this), address(router), tokenAmount); // make the swap // Arguments: // - uint amountIn // - uint amountOutMin // - address[] calldata path // - address to // - uint deadline router.swapExactTokensForETH( tokenAmount, 0, // accept any amount of ETH path, address(this), block.timestamp ); trading.inSwap = false; } require(address(this).balance >= oldBalance, "How did we lose ETH!?"); ethReceived = address(this).balance - oldBalance; } /******************************************************** * * NFT STATE & FUNCTIONS * ********************************************************/ struct NFT { address addr; uint256 tokenID; } // moving all state related to NFTs to this struct // to prepare for a future version of this contract // that's split between facets of a diamond proxy struct NFT_State { NFT[] treasury; address[] allowlist; address[] buyList; mapping (address => bool) inAllowList; mapping (address => bool) inBuyList; // price of each NFT in wei mapping (address => mapping(uint256 => uint256)) purchasePrice; } NFT_State nftState; function knownNFTContract(address nftContract) public view returns (bool) { return nftState.inAllowList[nftContract]; } function _addNFTContractToAllowList(address nftContract) internal { if (!nftState.inAllowList[nftContract]) { nftState.allowlist.push(nftContract); nftState.inAllowList[nftContract] = true; } } function addNFTContractToAllowList(address nftContract) public { // add NFT contract address to whitelist require(msg.sender == owner, "Must be owner to call addNFTContractToAllowList"); _addNFTContractToAllowList(nftContract); } function _removeNFTContractFromAllowList(address nftContract) internal { if (nftState.inAllowList[nftContract]) { nftState.inAllowList[nftContract] = false; uint256 i = 0; uint256 n = nftState.allowlist.length; for (; i < n; ++i) {if (nftState.allowlist[i] == nftContract) { break; }} nftState.allowlist[i] = nftState.allowlist[n - 1]; nftState.allowlist.pop(); } } function removeNFTContractFromAllowList(address nftContract) public { // remove NFT contract address from whitelist require(msg.sender == owner, "Must be owner to call removeNFTContractFromAllowList"); _removeNFTContractFromAllowList(nftContract); } function buyingNFTContract(address nftContract) public view returns (bool) { // are we currently trying to buy an NFT contract? return nftState.inBuyList[nftContract]; } function _addNFTContractToBuyList(address nftContract) internal { require(knownNFTContract(nftContract), "NFT contract not in allow list"); if (!buyingNFTContract(nftContract)) { nftState.buyList.push(nftContract); nftState.inBuyList[nftContract] = true; } } function addNFTContractToBuyList(address nftContract) public returns (bool) { // add NFT contract address to buy list require(msg.sender == owner, "Must be owner to call addNFTContractToBuyList"); _addNFTContractToBuyList(nftContract); return true; } function _addNewNFTContract(address nftContract) internal { _addNFTContractToAllowList(nftContract); _addNFTContractToBuyList(nftContract); } function _removeNFTContractFromBuyList(address nftContract) internal { if (nftState.inBuyList[nftContract]) { nftState.inBuyList[nftContract] = false; uint256 i = 0; uint256 n = nftState.buyList.length; for (; i < n; ++i) {if (nftState.buyList[i] == nftContract) { break; }} nftState.buyList[i] = nftState.buyList[n - 1]; nftState.buyList.pop(); } } function removeNFTContractFromBuyList(address nftContract) public returns (bool) { // remove NFT contract address from buy list require(msg.sender == owner, "Must be owner to call removeNFTContractFromBuyList"); _removeNFTContractFromBuyList(nftContract); return true; } function _removeFromNFTs(uint256 index) internal { uint256 n = nftState.treasury.length; require(n > index, "NFT index to be removed out of bounds"); // remove NFT price from mapping NFT storage nft = nftState.treasury[index]; address addr = nft.addr; uint256 tokenId = nft.tokenID; delete nftState.purchasePrice[addr][tokenId]; // copy last element of array to overwrite chosen location nftState.treasury[index] = nftState.treasury[n - 1]; // pop last element so it's not in the array twice nftState.treasury.pop(); } function numNFTsInTreasury() public view returns (uint256) { return nftState.treasury.length; } function _sendRandomNFT() internal returns (bool success) { success = false; uint256 n = numNFTsInTreasury(); if (n > 0) { address to = pickBestAddressOfThree(); if (!isSpecialAddress(to)) { uint256 i = randomModulo(n); NFT storage nft = nftState.treasury[i]; if (IERC721(nft.addr).ownerOf(nft.tokenID) == address(this)) { IERC721(nft.addr).transferFrom(address(this), to, nft.tokenID); emit SentNFT(nft.addr, nft.tokenID, to); success = true; } _removeFromNFTs(i); } } return success; } function _sellRandomNFT() internal returns (bool success, uint256 sellPrice) { uint256 n = numNFTsInTreasury(); if (n > 0) { uint256 i = randomModulo(n); NFT storage nft = nftState.treasury[i]; uint256 buyPrice = nftState.purchasePrice[nft.addr][nft.tokenID]; (sellPrice, ) = ISudoGate02(SUDOGATE_ADDRESS).sellQuote(nft.addr); if (sellPrice > buyPrice && sellPrice >= minSellPriceWei) { bool sufficientProfit = true; if (buyPrice > 0) { uint256 diff = sellPrice - buyPrice; uint256 percentIncrease = (diff * 100) / buyPrice; sufficientProfit = (percentIncrease >= minPricePercentIncreaseToSellNFT); } if (sufficientProfit) { if (IERC721(nft.addr).ownerOf(nft.tokenID) == address(this)) { // approve the SudoGate contract IERC721(nft.addr).approve(SUDOGATE_ADDRESS, nft.tokenID); (success, sellPrice, ) = ISudoGate02(SUDOGATE_ADDRESS).sell(nft.addr, nft.tokenID); if (success) { _removeFromNFTs(i); emit SoldNFT(nft.addr, nft.tokenID, sellPrice); } } } } } } function sellRandomNFT() public returns (bool success, uint256 sellPrice) { // in case we have too many NFTs in the treasury and they're not // getting distributed fast enough, let the contract owner // try to sell some require(msg.sender == owner, "Only owner can call sendRandomNFT"); return _sellRandomNFT(); } function sendRandomNFT() public returns (bool) { // in case we have too many NFTs in the treasury and they're not // getting distributed fast enough, let the contract owner // send some out require(msg.sender == owner, "Only owner can call sendRandomNFT"); return _sendRandomNFT(); } function numNFTContractsInBuyList() public view returns (uint256) { return nftState.buyList.length; } function _buyRandomNFT() internal returns (bool success, address nftAddr, uint256 tokenID) { success = false; if (numNFTContractsInBuyList() > 0) { address nftAddr = _pickRandomNFTContract(); (success, tokenID, ) = _buyNFT(nftAddr); } } function buyRandomNFT() public returns (bool, address, uint256) { // just in case the pace of NFT buying is too slow and too much ETH // accumulates, let the contract owner manually push the buy button require(msg.sender == owner, "Only owner can call buyRandomNFT"); return _buyRandomNFT(); } function _pickRandomNFTContract() internal returns (address nft) { require(numNFTContractsInBuyList() > 0, "No NFT contracts to buy!"); address[] storage buyList = nftState.buyList; uint256 n = buyList.length; return (n == 0) ? address(0) : buyList[randomModulo(n)]; } function _buyNFT(address nftAddr) internal returns (bool success, uint256 tokenId, uint256 price) { /* buy from given NFT address if it's possible to do so */ require(SUDOGATE_ADDRESS != address(0), "SudoGate address can't be zero"); ISudoGate02 sudogate = ISudoGate02(SUDOGATE_ADDRESS); (bool gotQuote, bytes memory returnData) = SUDOGATE_ADDRESS.call( abi.encodeWithSignature("buyQuoteWithFees(address)", nftAddr)); if (gotQuote) { // transferFrom completed successfully (did not revert) uint256 bestPrice; address bestPool; (bestPrice, bestPool) = abi.decode(returnData, (uint256, address)); if (bestPool != address(0) && bestPrice < address(this).balance && bestPrice <= maxBuyPriceWei) { success = true; tokenId = sudogate.buyFromPool{value: bestPrice}(bestPool); price = bestPrice; // treasury is a mapping from NFT addresses to an array of tokens that this contract owns nftState.treasury.push(NFT(nftAddr, tokenId)); nftState.purchasePrice[nftAddr][tokenId] = price; emit BoughtNFT(nftAddr, tokenId, price); } } } function ADD_NFT_CONTRACT_TO_BUY_LIST(address nftContract) payable public returns (bool) { /* Add an NFT contract to the set of NFTs that SudoRug buys and distributes to holders. Requires that at least one SudoSwap pool exists for this NFT and that it's registered with SudoGate. */ require(!buyingNFTContract(nftContract), "Already buying this one"); require(knownNFTContract(nftContract), "Not in whitelist"); ISudoGate02 sudogate = ISudoGate02(SUDOGATE_ADDRESS); if (msg.sender != owner) { require(_balanceOf(msg.sender) >= costToAddNFTContractInTokens, "Not enough tokens to add NFT contract"); require(msg.value >= costToAddNFTContractInETH, "Not enough ETH to add NFT contract"); uint256 halfTokens = costToAddNFTContractInTokens; uint256 otherHalf = costToAddNFTContractInTokens - halfTokens; _simple_transfer(msg.sender, address(this), halfTokens); _burnFrom(msg.sender, otherHalf); } _addNFTContractToBuyList(nftContract); return true; } /************************************************** * * * SUDOSWAP * * ************************************************/ function REGISTER_SUDOSWAP_POOL(address sudoswapPool) public returns (bool) { /* Register a sudoswap pool on SudoGate so it can be used for buying by SudoRug */ require(isSudoSwapPool(sudoswapPool), "Not a sudoswap pool"); bool success = false; ISudoGatePoolSource sudogate = ISudoGatePoolSource(SUDOGATE_ADDRESS); if (!sudogate.knownPool(sudoswapPool)) { // register the pool with SudoGate so that we're able to buy from it success = sudogate.registerPool(sudoswapPool); } return success; } function ADD_NFT_CONTRACT_AND_REGISTER_POOL(address sudoswapPool) payable public returns (bool) { /* Register a sudoswap pool for an NFT with SudoGate and then add that NFT contract to the SudoRug lottery. */ REGISTER_SUDOSWAP_POOL(sudoswapPool); ADD_NFT_CONTRACT_TO_BUY_LIST(address(LSSVMPair(sudoswapPool).nft())); return true; } function isSudoSwapPool(address sudoswapPool) public view returns (bool) { ILSSVMPairFactoryLike factory = ILSSVMPairFactoryLike(SUDO_PAIR_FACTORY_ADDRESS); return ( factory.isPair(sudoswapPool, ILSSVMPairFactoryLike.PairVariant.ENUMERABLE_ETH) || factory.isPair(sudoswapPool, ILSSVMPairFactoryLike.PairVariant.MISSING_ENUMERABLE_ETH) ); } function rescueNFT(address nftAddr, uint256 tokenId) public { // move an NFT off the contract in case it gets stuck require(msg.sender == owner, "Only owner allowed to call rescueNFT"); require(IERC721(nftAddr).ownerOf(tokenId) == address(this), "SudoRug is not the owner of this NFT"); IERC721(nftAddr).transferFrom(address(this), msg.sender, tokenId); } function rescueNFT_AddToTreasury(address nftAddr, uint256 tokenId) public { // move an NFT off the contract in case it gets stuck require(msg.sender == owner, "Only owner allowed to call rescueNFT_AddToTreasury"); require(IERC721(nftAddr).ownerOf(tokenId) == address(this), "SudoGate is not the owner of this NFT"); require(knownNFTContract(nftAddr), "NFT contract not in allow-list"); nftState.treasury.push(NFT(nftAddr, tokenId)); } // ERC721Receiver implementation copied and modified from: // https://github.com/GustasKlisauskas/ERC721Receiver/blob/master/ERC721Receiver.sol function onERC721Received(address, address, uint256 tokenId, bytes calldata) public pure returns(bytes4) { return this.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; interface ILSSVMPairFactoryLike { enum PairVariant { ENUMERABLE_ETH, MISSING_ENUMERABLE_ETH, ENUMERABLE_ERC20, MISSING_ENUMERABLE_ERC20 } function protocolFeeMultiplier() external view returns (uint256); function protocolFeeRecipient() external view returns (address payable); function callAllowed(address target) external view returns (bool); /* function routerStatus(LSSVMRouter router) external view returns (bool allowed, bool wasEverAllowed); */ function isPair(address potentialPair, PairVariant variant) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.10; import {IERC721} from "IERC721.sol"; import {ILSSVMPairFactoryLike} from "ILSSVMPairFactoryLike.sol"; contract CurveErrorCodes { enum Error { OK, // No error INVALID_NUMITEMS, // The numItem value is 0 SPOT_PRICE_OVERFLOW // The updated spot price doesn't fit into 128 bits } } interface LSSVMPair { enum PoolType { TOKEN, NFT, TRADE } function factory() external pure returns (ILSSVMPairFactoryLike); function nft() external pure returns (IERC721); function poolType() external pure returns (PoolType); function getBuyNFTQuote(uint256 numNFTs) external view returns ( CurveErrorCodes.Error error, uint256 newSpotPrice, uint256 newDelta, uint256 inputAmount, uint256 protocolFee ); function getSellNFTQuote(uint256 numNFTs) external view returns ( CurveErrorCodes.Error error, uint256 newSpotPrice, uint256 newDelta, uint256 outputAmount, uint256 protocolFee ); /** @notice Sends token to the pair in exchange for any `numNFTs` NFTs @dev To compute the amount of token to send, call bondingCurve.getBuyInfo. This swap function is meant for users who are ID agnostic @param numNFTs The number of NFTs to purchase @param maxExpectedTokenInput The maximum acceptable cost from the sender. If the actual amount is greater than this value, the transaction will be reverted. @param nftRecipient The recipient of the NFTs @param isRouter True if calling from LSSVMRouter, false otherwise. Not used for ETH pairs. @param routerCaller If isRouter is true, ERC20 tokens will be transferred from this address. Not used for ETH pairs. @return inputAmount The amount of token used for purchase */ function swapTokenForAnyNFTs( uint256 numNFTs, uint256 maxExpectedTokenInput, address nftRecipient, bool isRouter, address routerCaller ) external payable returns (uint256 inputAmount); function swapNFTsForToken( uint256[] calldata nftIds, uint256 minExpectedTokenOutput, address payable tokenRecipient, bool isRouter, address routerCaller ) external returns (uint256 outputAmount); function getAllHeldIds() external view returns (uint256[] memory); function owner() external view returns (address); }
pragma solidity ^0.8.7; interface IUniswapV2Factory { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; } interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; } interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH( address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline ) external returns (uint amountA, uint amountB); function removeLiquidityETH( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapTokensForExactTokens( uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); } interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.16; interface ISudoGatePoolSource { // base interface that just tracks a collection of SudoSwap pools function pools(address, uint256) external view returns (address); function knownPool(address) external view returns (bool); function registerPool(address sudoswapPool) external returns (bool); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.16; import {ISudoGate01} from "ISudoGate01.sol"; interface ISudoGate02 is ISudoGate01 { // v2 API extends v1 with selling function sellQuote(address nft) external view returns (uint256 bestPrice, address bestPool); function sellQuoteWithFees(address nft) external view returns (uint256 bestPrice, address bestPool); function sell(address nft, uint256 tokenId) external returns (bool success, uint256 priceInWei, uint256 feesInWei); function sellToPool(address nft, uint256 tokenId, address sudoswapPool, uint256 minPrice) external returns (uint256 priceInWei, uint256 feesInWei); }
// SPDX-License-Identifier: AGPL-3.0 pragma solidity ^0.8.16; import {ISudoGatePoolSource} from "ISudoGatePoolSource.sol"; interface ISudoGate01 is ISudoGatePoolSource { // In addition to ISudoGatePoolSource's tracking of pools, the v1 API allows buying function buyQuote(address nft) external view returns (uint256 bestPrice, address bestPool); function buyQuoteWithFees(address nft) external view returns (uint256 bestPrice, address bestPool); function buyFromPool(address pool) external payable returns (uint256 tokenID); }
{ "evmVersion": "istanbul", "optimizer": { "enabled": true, "runs": 200 }, "libraries": { "SudoRug2.sol": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"BoughtNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rugger","type":"address"}],"name":"FailedToRug","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bot","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"FellInHoney","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"rugger","type":"address"},{"indexed":false,"internalType":"uint256","name":"numTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethInWei","type":"uint256"}],"name":"RugAlarm","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"SentNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"price","type":"uint256"}],"name":"SoldNFT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"sudoswapPool","type":"address"}],"name":"ADD_NFT_CONTRACT_AND_REGISTER_POOL","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"}],"name":"ADD_NFT_CONTRACT_TO_BUY_LIST","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"}],"name":"AIRDROP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"PUSH_THE_RUG_BUTTON","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sudoswapPool","type":"address"}],"name":"REGISTER_SUDOSWAP_POOL","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"SUDOGATE_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actionFrequencyBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actionFrequencySell","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"actionFrequencySend","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addAMM","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"}],"name":"addNFTContractToAllowList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"}],"name":"addNFTContractToBuyList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","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":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyRandomNFT","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"}],"name":"buyingNFTContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"costToAddNFTContractInETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"costToAddNFTContractInTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentState","outputs":[{"internalType":"enum State","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"honeypotDurationBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"inBotQueue","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isAMM","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isEligible","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isSpecialAddress","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sudoswapPool","type":"address"}],"name":"isSudoSwapPool","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"}],"name":"knownNFTContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastRugTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPercentReapprioration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxRugFractionOfUniswapPerThousand","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minEligibleTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minMinutesBetweenRugs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRugFractionOfUniswapPerThousand","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minutesSinceLastBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minutesSinceLastRug","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":"numNFTContractsInBuyList","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numNFTsInTreasury","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"probCommunism","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"removeAMM","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"}],"name":"removeNFTContractFromAllowList","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftContract","type":"address"}],"name":"removeNFTContractFromBuyList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddr","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"rescueNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddr","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"rescueNFT_AddToTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rugSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sandwichTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellRandomNFT","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"sellPrice","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sendRandomNFT","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setActionFrequencyBuy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setActionFrequencySell","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setActionFrequencySend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tax","type":"uint256"}],"name":"setBuyTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethInWei","type":"uint256"}],"name":"setCostToAddNFTContractInETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"setCostToAddNFTContractInTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"setCostToRugInTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"costWei","type":"uint256"}],"name":"setMaxBuyPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setMaxPercentOfTotalSupplyPerRug","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setMaxPercentReapprioration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"impactPerThousand","type":"uint256"}],"name":"setMaxRugPriceImpactPerThousand","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"numTokens","type":"uint256"}],"name":"setMinEligibleTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"m","type":"uint256"}],"name":"setMinMinutesBetweenRugs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setMinPricePercentIncreaseToSellNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"impactPerThousand","type":"uint256"}],"name":"setMinRugPriceImpactPerThousand","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"priceWei","type":"uint256"}],"name":"setMinSellPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setProbCommunism","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tax","type":"uint256"}],"name":"setSandwichTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tax","type":"uint256"}],"name":"setSellTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sudogate","type":"address"}],"name":"setSudoGateAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","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":"_value","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":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Pair_WETH","outputs":[{"internalType":"contract IUniswapV2Pair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6080604052600380546001600160a01b03191673dd2aae657516341ba00ef80f09e357bd02500731179055620000386009600a620006dd565b6200004790620f4240620006f5565b6015556729a2241af62c0000601655620000646009600a620006dd565b6200007390620186a0620006f5565b6017556064601855670de0b6b3a764000060195567016345785d8a0000601a556000601b819055601c556028601d55620000b06009600a620006dd565b620000bd906000620006f5565b601e556000601f556002602055603c6021556001602255603c602355600a602455600360255560326026556005602755602d602855348015620000ff57600080fd5b50600a80546001600160a01b031916331781556000906200012390600990620006dd565b62000133906305f5e100620006f5565b6000818155600a80546001600160a01b039081168352600160205260408084208590559154915193945016917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906200018f9085815260200190565b60405180910390a36000737a250d5630b4cf539739df2c5dacb4c659f2488d90506000816001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001f1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000217919062000717565b90506000826001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200025a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000280919062000717565b6040516364e329cb60e11b81523060048201526001600160a01b03848116602483015291925060009183169063c9c65396906044016020604051808303816000875af1158015620002d5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002fb919062000717565b600b80546001600160a01b038781166001600160a01b03199283168117909355600c8054918516919092161790556000908152600f60205260409020805460ff1916600117905590506200036d816001600160a01b03166000908152600f60205260409020805460ff19166001179055565b6200038c73ef1a89cbfabe59397ffda11fc5df293e9bc5db9062000432565b620003ab739185a69970a150ec9d0dea6f18e62f40db9e94d262000432565b620003ca73e90d8fb7b79c8930b5c8891e61c298b412a6e81a62000432565b620003e9735135db8fdfd882543aa77492a4297137c9b2722362000432565b6200040873f210d5d9dcf958803c286a6f8e278e4ac78e136e62000432565b62000427735bdf397bb2912859dbd8011f320a222f79a28d2e62000432565b505050505062000742565b6200043d816200044b565b6200044881620004d3565b50565b6001600160a01b0381166000908152602d602052604090205460ff166200044857602b805460018181019092557f11c44e4875b74d31ff9fd779bf2566af7bd15b87fc985d01f5094b89e3669e4f0180546001600160a01b0384166001600160a01b031990911681179091556000908152602d60205260409020805460ff1916909117905550565b6001600160a01b0381166000908152602d602052604090205460ff16620005405760405162461bcd60e51b815260206004820152601e60248201527f4e465420636f6e7472616374206e6f7420696e20616c6c6f77206c6973740000604482015260640160405180910390fd5b6001600160a01b0381166000908152602e602052604090205460ff166200044857602c805460018181019092557f7416c943b4a09859521022fd2e90eac0dd9026dad28fa317782a135f28a860910180546001600160a01b0384166001600160a01b031990911681179091556000908152602e60205260409020805460ff1916909117905550565b634e487b7160e01b600052601160045260246000fd5b600181815b808511156200061f578160001904821115620006035762000603620005c8565b808516156200061157918102915b93841c9390800290620005e3565b509250929050565b6000826200063857506001620006d7565b816200064757506000620006d7565b81600181146200066057600281146200066b576200068b565b6001915050620006d7565b60ff8411156200067f576200067f620005c8565b50506001821b620006d7565b5060208310610133831016604e8410600b8410161715620006b0575081810a620006d7565b620006bc8383620005de565b8060001904821115620006d357620006d3620005c8565b0290505b92915050565b6000620006ee60ff84168362000627565b9392505050565b6000816000190483118215151615620007125762000712620005c8565b500290565b6000602082840312156200072a57600080fd5b81516001600160a01b0381168114620006ee57600080fd5b615fad80620007526000396000f3fe6080604052600436106104a35760003560e01c80637f399bcb11610260578063b8c1825f11610144578063dc1052e2116100c1578063e98491ce11610085578063e98491ce14610e86578063ea336c7414610ea6578063eb4072db14610ebb578063f54d474414610ed0578063f9b12b0714610ef0578063fa656f4a14610f1057600080fd5b8063dc1052e214610df1578063dd62ed3e14610e11578063e26467be14610e31578063e33ad33c14610e51578063e879780214610e7157600080fd5b8063c5296a0f11610108578063c5296a0f14610d4b578063cc1776d314610d85578063d3428cfd14610d9b578063d46b6a3014610db1578063d66bbec714610dd157600080fd5b8063b8c1825f14610cbf578063bed7a20614610cdf578063beecd38b14610cff578063c1bf048a14610d15578063c241417814610d3557600080fd5b80639a2421eb116101dd578063a9059cbb116101a1578063a9059cbb14610bf9578063ac7f90d514610c19578063adce4cbf14610c39578063af99cc4f14610c59578063b0e9895d14610c6f578063b72995c814610c8f57600080fd5b80639a2421eb14610b4a5780639e21d7db14610b6a578063a3c7783b14610ba3578063a403fbd114610bb9578063a4a9860514610bd957600080fd5b80638cd09d50116102245780638cd09d5014610aae5780638ce4832414610ace5780638da5cb5b14610ae45780639182e0b114610b0457806395d89b4114610b1a57600080fd5b80637f399bcb14610a0c578063820941e214610a2a5780638253747e14610a3f57806388399f4d14610a5f578063896c034914610a7557600080fd5b80633bbac579116103875780635db231621161030457806366e305fd116102c857806366e305fd1461094857806370a082311461098157806370b65246146109a15780637160598d146109b657806373845954146109cc5780637f22bed8146109ec57600080fd5b80635db23162146108b25780635dcb14d2146108d25780636479255d146108f2578063651f8c851461091257806365c3d0511461092857600080fd5b80635098d5fb1161034b5780635098d5fb1461082c57806351c6590a1461085857806352a00fbb1461086b57806354fd4d501461087e5780635cc6780e1461089257600080fd5b80633bbac579146107905780633edb223f146107c057806340fb5698146107e05780634bd7ccfb146107f65780634f7041a51461081657600080fd5b8063154dca2c116104205780632137ede9116103e45780632137ede9146106d457806323b872dd146106e9578063313ce56714610709578063342aa8b51461073057806336ed48c01461075057806338a55f0e1461077057600080fd5b8063154dca2c146106445780631694505e1461065757806318160ddd146106895780631ab82d6d1461069e5780631f632cb2146106be57600080fd5b80630c3f6acf116104675780630c3f6acf146105885780630d326463146105aa5780631307d65a146105bf57806313af4035146105df578063150b7a02146105ff57600080fd5b8063052d1d48146104af57806306fdde03146104d7578063095ea7b3146105165780630ae96731146105465780630b13ace21461056857600080fd5b366104aa57005b600080fd5b3480156104bb57600080fd5b506104c4610f26565b6040519081526020015b60405180910390f35b3480156104e357600080fd5b5060408051808201909152600d81526c29bab237a93ab3902a37b5b2b760991b60208201525b6040516104ce91906157fe565b34801561052257600080fd5b50610536610531366004615846565b610f36565b60405190151581526020016104ce565b34801561055257600080fd5b50610566610561366004615872565b610f4d565b005b34801561057457600080fd5b5061053661058336600461588b565b611024565b34801561059457600080fd5b5061059d611077565b6040516104ce91906158be565b3480156105b657600080fd5b506104c4611081565b3480156105cb57600080fd5b506105366105da36600461588b565b6110b8565b3480156105eb57600080fd5b506105666105fa36600461588b565b611141565b34801561060b57600080fd5b5061062b61061a3660046158d8565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016104ce565b61053661065236600461588b565b6111c9565b34801561066357600080fd5b50600b546001600160a01b03165b6040516001600160a01b0390911681526020016104ce565b34801561069557600080fd5b506000546104c4565b3480156106aa57600080fd5b506105666106b9366004615872565b61139d565b3480156106ca57600080fd5b506104c4601f5481565b3480156106e057600080fd5b5061053661140e565b3480156106f557600080fd5b50610536610704366004615977565b6115f0565b34801561071557600080fd5b5061071e600981565b60405160ff90911681526020016104ce565b34801561073c57600080fd5b5061053661074b3660046159c6565b611612565b34801561075c57600080fd5b5061056661076b366004615872565b6116bc565b34801561077c57600080fd5b5061056661078b366004615846565b611742565b34801561079c57600080fd5b506105366107ab36600461588b565b60046020526000908152604090205460ff1681565b3480156107cc57600080fd5b506105666107db366004615872565b6118df565b3480156107ec57600080fd5b506104c460285481565b34801561080257600080fd5b50610566610811366004615872565b611964565b34801561082257600080fd5b506104c4601c5481565b34801561083857600080fd5b506108416119e9565b6040805192151583526020830191909152016104ce565b610566610866366004615872565b611a28565b61053661087936600461588b565b611d2a565b34801561088a57600080fd5b5060026104c4565b34801561089e57600080fd5b506105666108ad366004615846565b611d9b565b3480156108be57600080fd5b506105666108cd366004615872565b611fdc565b3480156108de57600080fd5b506105666108ed366004615872565b6120ab565b3480156108fe57600080fd5b5061053661090d36600461588b565b612130565b34801561091e57600080fd5b506104c460265481565b34801561093457600080fd5b50610566610943366004615872565b61222c565b34801561095457600080fd5b5061053661096336600461588b565b6001600160a01b031660009081526009602052604090205460ff1690565b34801561098d57600080fd5b506104c461099c36600461588b565b61230a565b3480156109ad57600080fd5b506104c4600281565b3480156109c257600080fd5b506104c460215481565b3480156109d857600080fd5b50600354610671906001600160a01b031681565b3480156109f857600080fd5b50610566610a07366004615872565b612315565b348015610a1857600080fd5b50600c546001600160a01b0316610671565b348015610a3657600080fd5b50602a546104c4565b348015610a4b57600080fd5b50610566610a5a36600461588b565b612375565b348015610a6b57600080fd5b506104c4601d5481565b348015610a8157600080fd5b50610536610a9036600461588b565b6001600160a01b03166000908152602e602052604090205460ff1690565b348015610aba57600080fd5b50610566610ac9366004615872565b612407565b348015610ada57600080fd5b506104c460275481565b348015610af057600080fd5b50600a54610671906001600160a01b031681565b348015610b1057600080fd5b506104c460175481565b348015610b2657600080fd5b506040805180820190915260078152665355444f52554760c81b6020820152610509565b348015610b5657600080fd5b50610566610b65366004615872565b612474565b348015610b7657600080fd5b50610536610b8536600461588b565b6001600160a01b03166000908152602d602052604090205460ff1690565b348015610baf57600080fd5b506104c460165481565b348015610bc557600080fd5b50610566610bd4366004615872565b6124e2565b348015610be557600080fd5b50610566610bf4366004615872565b6125c4565b348015610c0557600080fd5b50610536610c14366004615846565b612692565b348015610c2557600080fd5b50610536610c3436600461588b565b61269f565b348015610c4557600080fd5b50610536610c5436600461588b565b6127d7565b348015610c6557600080fd5b506104c460255481565b348015610c7b57600080fd5b50610566610c8a366004615ad5565b61285c565b348015610c9b57600080fd5b50610536610caa36600461588b565b60056020526000908152604090205460ff1681565b348015610ccb57600080fd5b50610566610cda366004615872565b612b65565b348015610ceb57600080fd5b50610566610cfa366004615872565b612beb565b348015610d0b57600080fd5b506104c460225481565b348015610d2157600080fd5b50610566610d30366004615872565b612c54565b348015610d4157600080fd5b506104c460155481565b348015610d5757600080fd5b50610d60612cc5565b6040805193151584526001600160a01b039092166020840152908201526060016104ce565b348015610d9157600080fd5b506104c4601b5481565b348015610da757600080fd5b506104c460235481565b348015610dbd57600080fd5b50610536610dcc36600461588b565b612d39565b348015610ddd57600080fd5b50610566610dec366004615872565b612d44565b348015610dfd57600080fd5b50610566610e0c366004615872565b612da9565b348015610e1d57600080fd5b506104c4610e2c366004615b97565b612e5e565b348015610e3d57600080fd5b50610566610e4c36600461588b565b612e8b565b348015610e5d57600080fd5b50610566610e6c36600461588b565b612f06565b348015610e7d57600080fd5b506104c4612f86565b348015610e9257600080fd5b50610536610ea136600461588b565b612fa8565b348015610eb257600080fd5b50610536613024565b348015610ec757600080fd5b50602c546104c4565b348015610edc57600080fd5b50610536610eeb36600461588b565b613059565b348015610efc57600080fd5b50610566610f0b366004615872565b6130db565b348015610f1c57600080fd5b506104c460245481565b6000610f3130613196565b905090565b6000610f433384846131b1565b5060015b92915050565b600a546001600160a01b03163314610f805760405162461bcd60e51b8152600401610f7790615bc5565b60405180910390fd5b6103e8811115610fcd5760405162461bcd60e51b8152602060048201526018602482015277056616c75652063616e6e6f742065786365656420313030360441b6044820152606401610f77565b80602254111561101f5760405162461bcd60e51b815260206004820181905260248201527f4d696e2063616e6e6f742065786365656420657863656564206e6577206d61786044820152606401610f77565b602355565b600061102f82613213565b8061105257506001600160a01b03821660009081526004602052604090205460ff165b80610f475750506001600160a01b031660009081526005602052604090205460ff1690565b6000610f3161327f565b600061108e600d54151590565b156110b257603c61109e600e5490565b6110a89042615c26565b610f319190615c4f565b50600090565b600a546000906001600160a01b031633146111305760405162461bcd60e51b815260206004820152603260248201527f4d757374206265206f776e657220746f2063616c6c2072656d6f76654e4654436044820152711bdb9d1c9858dd119c9bdb509d5e531a5cdd60721b6064820152608401610f77565b611139826132ad565b506001919050565b600a546001600160a01b031633146111a75760405162461bcd60e51b815260206004820152602360248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744f776044820152623732b960e91b6064820152608401610f77565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152602e602052604081205460ff16156112325760405162461bcd60e51b815260206004820152601760248201527f416c726561647920627579696e672074686973206f6e650000000000000000006044820152606401610f77565b6001600160a01b0382166000908152602d602052604090205460ff1661128d5760405162461bcd60e51b815260206004820152601060248201526f139bdd081a5b881dda1a5d195b1a5cdd60821b6044820152606401610f77565b600354600a546001600160a01b0391821691163314611394576015546112b233613196565b101561130e5760405162461bcd60e51b815260206004820152602560248201527f4e6f7420656e6f75676820746f6b656e7320746f20616464204e465420636f6e6044820152641d1c9858dd60da1b6064820152608401610f77565b60165434101561136b5760405162461bcd60e51b815260206004820152602260248201527f4e6f7420656e6f7567682045544820746f20616464204e465420636f6e74726160448201526118dd60f21b6064820152608401610f77565b601554600061137a8280615c26565b90506113873330846133ee565b6113913382613528565b50505b610f4383613584565b600a546001600160a01b0316331461140b5760405162461bcd60e51b815260206004820152603e6024820152600080516020615f5883398151915260448201527f6e507269636550657263656e74496e637265617365546f53656c6c4e465400006064820152608401610f77565b50565b6000611418613673565b6000611422613874565b9050600061142e610f26565b8211156114d35761143d610f26565b6114479083615c26565b90506000611455606461397f565b60245411801591506114d157600061146b6139f2565b90506001600160a01b038116156114cf57600060646114898361230a565b6025546114969190615c63565b6114a09190615c4f565b905060008482106114b157846114b3565b815b90506114c08330836133ee565b6114ca8186615c26565b945050505b505b505b80156114e3576114e33082613ab7565b60006114ee83613b42565b905081156115115761151161150b600c546001600160a01b031690565b83613528565b600c546001600160a01b03166001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561155757600080fd5b505af115801561156b573d6000803e3d6000fd5b5050508115801591506115bc5742601f55604080518581526020810184905233917f9a5178ff42681b627314726ddac5afb7bf7f43659a3d45fba04e4cac720d0936910160405180910390a26115e8565b60405133907f2c58021a2da7aa3664cfb8e7baa4497f73c94ae0974ce255e30904702935844790600090a25b949350505050565b60006115fd843384613b8a565b611608848484613c39565b5060019392505050565b600a546000906001600160a01b0316331461166f5760405162461bcd60e51b815260206004820152601a60248201527f4f6e6c79206f776e65722063616e2063616c6c20616464426f740000000000006044820152606401610f77565b818015611680575061168083613213565b1561168d57506000610f47565b506001600160a01b0382166000908152600460205260409020805482151560ff19909116179055600192915050565b600a546001600160a01b031633146117305760405162461bcd60e51b815260206004820152603160248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657441636044820152701d1a5bdb919c995c5d595b98de54d95b99607a1b6064820152608401610f77565b61173c60275482613d9d565b50602755565b600a546001600160a01b031633146117a85760405162461bcd60e51b8152602060048201526024808201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2072657363756044820152631953919560e21b6064820152608401610f77565b6040516331a9108f60e11b81526004810182905230906001600160a01b03841690636352211e90602401602060405180830381865afa1580156117ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118139190615c82565b6001600160a01b0316146118755760405162461bcd60e51b8152602060048201526024808201527f5375646f527567206973206e6f7420746865206f776e6572206f6620746869736044820152630813919560e21b6064820152608401610f77565b6040516323b872dd60e01b8152306004820152336024820152604481018290526001600160a01b038316906323b872dd90606401600060405180830381600087803b1580156118c357600080fd5b505af11580156118d7573d6000803e3d6000fd5b505050505050565b600a546001600160a01b0316331461195f5760405162461bcd60e51b815260206004820152603760248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574436f60448201527f7374546f4164644e4654436f6e7472616374496e4554480000000000000000006064820152608401610f77565b601655565b600a546001600160a01b031633146119e45760405162461bcd60e51b815260206004820152603a60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574436f60448201527f7374546f4164644e4654436f6e7472616374496e546f6b656e730000000000006064820152608401610f77565b601555565b600a5460009081906001600160a01b03163314611a185760405162461bcd60e51b8152600401610f7790615c9f565b611a20613ea2565b915091509091565b600a546001600160a01b03163314611a825760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722063616e2063616c6c206164644c69717569646974796044820152606401610f77565b60008111611ad25760405162461bcd60e51b815260206004820152601860248201527f4e6f20746f6b656e7320666f72206c69717569646974792100000000000000006044820152606401610f77565b60003411611b1a5760405162461bcd60e51b81526020600482015260156024820152744e6f2045544820666f72206c69717569646974792160581b6044820152606401610f77565b600b54600c546001600160a01b039182169116611b38333085613c39565b611b433083856131b1565b6001600160a01b03821663f305d719343086808333611b6342600f615ce0565b60405160e089901b6001600160e01b03191681526001600160a01b039687166004820152602481019590955260448501939093526064840191909152909216608482015260a481019190915260c40160606040518083038185885af1158015611bd0573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611bf59190615cf3565b50505034826001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5b9190615c82565b6040516370a0823160e01b81526001600160a01b03848116600483015291909116906370a0823190602401602060405180830381865afa158015611ca3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc79190615d21565b1015611d215760405162461bcd60e51b815260206004820152602360248201527f455448206469646e27742067657420746f20746865207061697220636f6e74726044820152621858dd60ea1b6064820152608401610f77565b505043600d5550565b6000611d358261269f565b50610f43826001600160a01b03166347ccca026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d77573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106529190615c82565b600a546001600160a01b03163314611e105760405162461bcd60e51b815260206004820152603260248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207265736375604482015271654e46545f416464546f547265617375727960701b6064820152608401610f77565b6040516331a9108f60e11b81526004810182905230906001600160a01b03841690636352211e90602401602060405180830381865afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190615c82565b6001600160a01b031614611edf5760405162461bcd60e51b815260206004820152602560248201527f5375646f47617465206973206e6f7420746865206f776e6572206f66207468696044820152641cc813919560da1b6064820152608401610f77565b6001600160a01b0382166000908152602d602052604090205460ff16611f475760405162461bcd60e51b815260206004820152601e60248201527f4e465420636f6e7472616374206e6f7420696e20616c6c6f772d6c69737400006044820152606401610f77565b604080518082019091526001600160a01b03928316815260208101918252602a805460018101825560009190915290517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2600290920291820180546001600160a01b0319169190941617909255517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d390910155565b600a546001600160a01b031633146120555760405162461bcd60e51b815260206004820152603660248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744d616044820152753c2832b931b2b73a2932b0b8383934b7b930ba34b7b760511b6064820152608401610f77565b60648111156120a65760405162461bcd60e51b815260206004820152601860248201527f56616c75652063616e6e6f7420657863656564203130302500000000000000006044820152606401610f77565b602455565b600a546001600160a01b0316331461211e5760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574416360448201526f74696f6e4672657175656e637942757960801b6064820152608401610f77565b61212a60265482613d9d565b50602655565b6040516308f25a8f60e01b815260009073b16c1342e617a5b6e4b631eb114483fdb289c0a49081906308f25a8f9061216e9086908690600401615d3a565b602060405180830381865afa15801561218b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121af9190615d67565b8061222557506040516308f25a8f60e01b81526001600160a01b038216906308f25a8f906121e4908690600190600401615d3a565b602060405180830381865afa158015612201573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122259190615d67565b9392505050565b600a546001600160a01b0316331461229e5760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574436f60448201526e7374546f527567496e546f6b656e7360881b6064820152608401610f77565b600054601e5411156123055760405162461bcd60e51b815260206004820152602a60248201527f43616e277420636861726765206d6f7265207468616e20616c6c206578697374604482015269696e6720746f6b656e7360b01b6064820152608401610f77565b601e55565b6000610f4782613196565b600a546001600160a01b031633146123705760405162461bcd60e51b815260206004820152602a6024820152600080516020615f588339815191526044820152696e53656c6c507269636560b01b6064820152608401610f77565b601a55565b600a546001600160a01b031633146123e55760405162461bcd60e51b815260206004820152602d60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574537560448201526c646f476174654164647265737360981b6064820152608401610f77565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600a546001600160a01b0316331461246f5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657453656044820152640d8d8a8c2f60db1b6064820152608401610f77565b601b55565b600a546001600160a01b031633146120555760405162461bcd60e51b815260206004820152602b60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574507260448201526a6f62436f6d6d756e69736d60a81b6064820152608401610f77565b600a546001600160a01b031633146125625760405162461bcd60e51b815260206004820152603b60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744d6160448201527f7850657263656e744f66546f74616c537570706c7950657252756700000000006064820152608401610f77565b60648111156125bf5760405162461bcd60e51b8152602060048201526024808201527f50657263656e74206f6620737570706c792063616e6e6f7420657863656564206044820152633130302560e01b6064820152608401610f77565b602055565b600a546001600160a01b031633146125ee5760405162461bcd60e51b8152600401610f7790615bc5565b6103e881111561263b5760405162461bcd60e51b8152602060048201526018602482015277056616c75652063616e6e6f742065786365656420313030360441b6044820152606401610f77565b60235481111561268d5760405162461bcd60e51b815260206004820181905260248201527f4e6577206d696e2063616e6e6f742065786365656420657863656564206d61786044820152606401610f77565b602255565b6000610f43338484613c39565b60006126aa82612130565b6126ec5760405162461bcd60e51b8152602060048201526013602482015272139bdd0818481cdd591bdcddd85c081c1bdbdb606a1b6044820152606401610f77565b6003546040516366fe44d560e11b81526001600160a01b0384811660048301526000921690819063cdfc89aa90602401602060405180830381865afa158015612739573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275d9190615d67565b6127d0576040516355ec842360e11b81526001600160a01b03858116600483015282169063abd90846906024016020604051808303816000875af11580156127a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cd9190615d67565b91505b5092915050565b600a546000906001600160a01b031633146128345760405162461bcd60e51b815260206004820152601b60248201527f43616e206f6e6c792062652063616c6c6564206279206f776e657200000000006044820152606401610f77565b611139826001600160a01b03166000908152600f60205260409020805460ff19166001179055565b80518251146128c65760405162461bcd60e51b815260206004820152603060248201527f41646472657373657320616e6420746f6b656e2076616c756573206d7573742060448201526f0d0c2ecca40e6c2daca40d8cadccee8d60831b6064820152608401610f77565b600a546001600160a01b03163314806128f7575060026128e461327f565b60028111156128f5576128f56158a8565b145b6129435760405162461bcd60e51b815260206004820152601760248201527f596f752063616e27742063616c6c2074686973207965740000000000000000006044820152606401610f77565b3360009081526004602052604090205460ff1615801561297357503360009081526005602052604090205460ff16155b6129bf5760405162461bcd60e51b815260206004820152601760248201527f536f7272792c206e6f7420626f747320616c6c6f7765640000000000000000006044820152606401610f77565b600080808080805b8751811015612ace578781815181106129e2576129e2615d84565b602002602001015191508681815181106129fe576129fe615d84565b602002602001015194508486612a149190615ce0565b6001600160a01b0383166000908152600160205260409020549096509350612a3c8585615ce0565b6001600160a01b03831660008181526001602052604090819020839055519194509033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612a8f9089815260200190565b60405180910390a360175483118015612aae5750612aac82611024565b155b15612abc57612abc826141af565b80612ac681615d9a565b9150506129c7565b5033600090815260016020526040902054851115612b2e5760405162461bcd60e51b815260206004820152601d60248201527f4e6f7420656e6f75676820746f6b656e7320666f722061697264726f700000006044820152606401610f77565b3360009081526001602052604081208054879290612b4d908490615c26565b90915550612b5c905033614222565b50505050505050565b600a546001600160a01b03163314612bd95760405162461bcd60e51b815260206004820152603160248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657441636044820152701d1a5bdb919c995c5d595b98de54d95b1b607a1b6064820152608401610f77565b612be560285482613d9d565b50602855565b600a546001600160a01b03163314612c4f5760405162461bcd60e51b81526020600482015260336024820152600080516020615f588339815191526044820152726e4d696e757465734265747765656e5275677360681b6064820152608401610f77565b602155565b600a546001600160a01b03163314612cc05760405162461bcd60e51b815260206004820152602960248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744d6160448201526878427579507269636560b81b6064820152608401610f77565b601955565b600a54600090819081906001600160a01b03163314612d265760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722063616e2063616c6c2062757952616e646f6d4e46546044820152606401610f77565b612d2e614296565b925092509250909192565b6000610f47826142cc565b600a546001600160a01b03163314612da45760405162461bcd60e51b815260206004820152602f6024820152600080516020615f5883398151915260448201526e6e456c696769626c65546f6b656e7360881b6064820152608401610f77565b601755565b600a546001600160a01b03163314612e0f5760405162461bcd60e51b8152602060048201526024808201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657442756044820152630f2a8c2f60e31b6064820152608401610f77565b6064811115612e595760405162461bcd60e51b81526020600482015260166024820152755461782063616e6e6f7420657863656564203130302560501b6044820152606401610f77565b601c55565b6001600160a01b038083166000908152600260209081526040808320938516835292905290812054612225565b600a546001600160a01b03163314612efd5760405162461bcd60e51b815260206004820152602f60248201527f4d757374206265206f776e657220746f2063616c6c206164644e4654436f6e7460448201526e1c9858dd151bd05b1b1bddd31a5cdd608a1b6064820152608401610f77565b61140b816142ea565b600a546001600160a01b03163314612f7d5760405162461bcd60e51b815260206004820152603460248201527f4d757374206265206f776e657220746f2063616c6c2072656d6f76654e4654436044820152731bdb9d1c9858dd119c9bdb505b1b1bddd31a5cdd60621b6064820152608401610f77565b61140b81614371565b6000601f54600003612f985750600090565b603c601f54426110a89190615c26565b600a546000906001600160a01b0316331461301b5760405162461bcd60e51b815260206004820152602d60248201527f4d757374206265206f776e657220746f2063616c6c206164644e4654436f6e7460448201526c1c9858dd151bd09d5e531a5cdd609a1b6064820152608401610f77565b61113982613584565b600a546000906001600160a01b031633146130515760405162461bcd60e51b8152600401610f7790615c9f565b610f3161448b565b600a546000906001600160a01b031633146130b65760405162461bcd60e51b815260206004820152601b60248201527f43616e206f6e6c792062652063616c6c6564206279206f776e657200000000006044820152606401610f77565b611139826001600160a01b03166000908152600f60205260409020805460ff19169055565b600a546001600160a01b031633146131475760405162461bcd60e51b815260206004820152602960248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657453616044820152680dcc8eed2c6d0a8c2f60bb1b6064820152608401610f77565b60648111156131915760405162461bcd60e51b81526020600482015260166024820152755461782063616e6e6f7420657863656564203130302560501b6044820152606401610f77565b601d55565b6001600160a01b031660009081526001602052604090205490565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006001600160a01b03821630148061323357506001600160a01b038216155b8061324b5750600a546001600160a01b038381169116145b8061325a575061325a826142cc565b80610f475750506001600160a01b03166000908152602d602052604090205460ff1690565b600061328c600d54151590565b156110b257600261329b614643565b10156132a75750600190565b50600290565b6001600160a01b0381166000908152602e602052604090205460ff161561140b576001600160a01b0381166000908152602e60205260408120805460ff19169055602c545b8082101561334457826001600160a01b0316602a600201838154811061331a5761331a615d84565b6000918252602090912001546001600160a01b0316146133445761333d82615d9a565b91506132f2565b602c613351600183615c26565b8154811061336157613361615d84565b600091825260209091200154602c80546001600160a01b03909216918490811061338d5761338d615d84565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055602c8054806133c7576133c7615db3565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b6001600160a01b03831660009081526001602052604090205481111561344d5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610f77565b6001600160a01b03831660009081526001602052604081208054839290613475908490615c26565b9091555050600c546001600160a01b038481169116146134985761349883614222565b6001600160a01b038216600090815260016020526040812080548392906134c0908490615ce0565b9091555050600c546001600160a01b038381169116146134e3576134e382614222565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161320691815260200190565b8061353283613196565b10156135745760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b6044820152606401610f77565b613580826000836133ee565b5050565b6001600160a01b0381166000908152602d602052604090205460ff166135ec5760405162461bcd60e51b815260206004820152601e60248201527f4e465420636f6e7472616374206e6f7420696e20616c6c6f77206c69737400006044820152606401610f77565b6001600160a01b0381166000908152602e602052604090205460ff1661140b57602c805460018181019092557f7416c943b4a09859521022fd2e90eac0dd9026dad28fa317782a135f28a860910180546001600160a01b0384166001600160a01b031990911681179091556000908152602e60205260409020805460ff1916909117905550565b600261367d611077565b600281111561368e5761368e6158a8565b146136cc5760405162461bcd60e51b815260206004820152600e60248201526d43616e277420727567207965742160901b6044820152606401610f77565b601f54600e54116137175760405162461bcd60e51b81526020600482015260156024820152744d75737420627579206265747765656e207275677360581b6044820152606401610f77565b601f54156137785760215461372a612f86565b10156137785760405162461bcd60e51b815260206004820152601860248201527f486f6c6420796f757220686f72736573207275676765727300000000000000006044820152606401610f77565b600a546001600160a01b031633146137e9573360009081526009602052604090205460ff166137e95760405162461bcd60e51b815260206004820152601760248201527f527567676572206d75737420626520656c696769626c650000000000000000006044820152606401610f77565b600a546001600160a01b0316331480159061380657506000601e54115b1561387257601e546138173361230a565b10156138655760405162461bcd60e51b815260206004820152601d60248201527f4e6f7420656e6f75676820746f6b656e7320666f722072756767696e670000006044820152606401610f77565b6138723330601e546133ee565b565b602254602354600091908110156138b05760006022546023546138979190615c26565b90506138a28161397f565b6138ac9083615ce0565b9150505b6103e88111156139155760405162461bcd60e51b815260206004820152602a60248201527f52616e646f6d20707269636520696d706163742073686f756c64206e6f7420656044820152697863656564203130302560b01b6064820152608401610f77565b600061392c61099c600c546001600160a01b031690565b90506103e861393b8383615c63565b6139459190615c4f565b92506000606461395460005490565b6020546139619190615c63565b61396b9190615c4f565b905080841115613979578093505b50505090565b60008082116139df5760405162461bcd60e51b815260206004820152602660248201527f43616e6e6f742067656e65726174652072616e646f6d206e756d626572206d6f604482015265064756c6f20360d41b6064820152608401610f77565b816139e8614653565b610f479190615dc9565b6000806139fd6146c0565b90506000613a096146c0565b90506000613a156146c0565b905060006001600160a01b03841615613a3657613a3184613196565b613a39565b60005b905060006001600160a01b03841615613a5a57613a5584613196565b613a5d565b60005b905060006001600160a01b03841615613a7e57613a7984613196565b613a81565b60005b9050818311613a9d57808211613a975783613aac565b84613aac565b808311613aaa5783613aac565b855b965050505050505090565b80600080016000828254613acb9190615ce0565b90915550506001600160a01b03821660009081526001602052604081208054839290613af8908490615ce0565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600c54600090600160a01b900460ff16613b85576000613b60610f26565b905082811015613b705780613b72565b825b92508215613b835761222583614702565b505b919050565b6001600160a01b03808416600090815260026020908152604080832093861683529290522054811115613bf85760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610f77565b6001600160a01b03808416600090815260026020908152604080832093861683529290529081208054839290613c2f908490615c26565b9091555050505050565b6001600160a01b038316301480613c5857506001600160a01b03821630145b80613c705750600a546001600160a01b038481169116145b15613c8557613c808383836133ee565b505050565b600d54613cea5760405162461bcd60e51b815260206004820152602d60248201527f43616e6e6f74207472616e7366657220746f6b656e73206265666f7265206c6960448201526c1c5d5a591a5d1e481859191959609a1b6064820152608401610f77565b600c54600160a01b900460ff1615613d0757613c808383836133ee565b6001613d1161327f565b6002811115613d2257613d226158a8565b03613d9257613d30836142cc565b15613d8757613d3e82614917565b15613d8757816001600160a01b03167f83efabacf9f7cf6e679b0fd9de0113ad1e05f72b1955dedadf0e01422a52234a82604051613d7e91815260200190565b60405180910390a25b613c808383836133ee565b613c80838383614934565b60006064821115613dfc5760405162461bcd60e51b815260206004820152602360248201527f4e65772070657263656e742076616c75652063616e6e6f74206578636565642060448201526203130360ec1b6064820152608401610f77565b6000602854602754602654613e119190615ce0565b613e1b9190615ce0565b90506000613e298583615c26565b90506000613e378583615ce0565b90506064811115613e995760405162461bcd60e51b815260206004820152602660248201527f436f6d62696e65642070657263656e74616765732063616e6e6f74206578636560448201526506564203130360d41b6064820152608401610f77565b50505092915050565b6000806000613eb0602a5490565b905080156141aa576000613ec38261397f565b90506000602a6000018281548110613edd57613edd615d84565b6000918252602080832060029290920290910180546001600160a01b03908116808552602f845260408086206001850154875290945293839020546003549351636ec9facd60e11b81526004810195909552919450909291169063dd93f59a906024016040805180830381865afa158015613f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f809190615ddd565b5094508085118015613f945750601a548510155b156141a65760018115613fd1576000613fad8388615c26565b9050600083613fbd836064615c63565b613fc79190615c4f565b6018541115925050505b80156141a457825460018401546040516331a9108f60e11b8152600481019190915230916001600160a01b031690636352211e90602401602060405180830381865afa158015614025573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140499190615c82565b6001600160a01b0316036141a4578254600354600185015460405163095ea7b360e01b81526001600160a01b039283166004820152602481019190915291169063095ea7b390604401600060405180830381600087803b1580156140ac57600080fd5b505af11580156140c0573d6000803e3d6000fd5b505060035485546001870154604051636c197ff560e01b81526001600160a01b039283166004820152602481019190915291169250636c197ff591506044016060604051808303816000875af115801561411e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141429190615e02565b50909750955086156141a45761415784614f3d565b8254600184015460408051918252602082018990526001600160a01b03909216917f3148efce73b39b088f8c1497d8e056a6e8d58e3ffa171525862a6d4238397b90910160405180910390a25b505b5050505b509091565b6001600160a01b03166000818152600960209081526040808320805460ff19166001908117909155600780546008909452918420839055820181559091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319169091179055565b60175461422e82613196565b108061423e575061423e81611024565b1561426d576001600160a01b03811660009081526009602052604090205460ff161561140b5761140b816150b2565b6001600160a01b03811660009081526009602052604090205460ff1661140b5761140b816141af565b60008080806142a4602c5490565b11156142c75760006142b46151bb565b90506142bf8161525c565b509094509150505b909192565b6001600160a01b03166000908152600f602052604090205460ff1690565b6001600160a01b0381166000908152602d602052604090205460ff1661140b57602b805460018181019092557f11c44e4875b74d31ff9fd779bf2566af7bd15b87fc985d01f5094b89e3669e4f0180546001600160a01b0384166001600160a01b031990911681179091556000908152602d60205260409020805460ff1916909117905550565b6001600160a01b0381166000908152602d602052604090205460ff161561140b576001600160a01b0381166000908152602d60205260408120805460ff19169055602b545b8082101561440857826001600160a01b0316602a60010183815481106143de576143de615d84565b6000918252602090912001546001600160a01b0316146144085761440182615d9a565b91506143b6565b602b614415600183615c26565b8154811061442557614425615d84565b600091825260209091200154602b80546001600160a01b03909216918490811061445157614451615d84565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055602b8054806133c7576133c7615db3565b600080614497602a5490565b9050801561463f5760006144a96139f2565b90506144b481611024565b61463d5760006144c38361397f565b90506000602a60000182815481106144dd576144dd615d84565b60009182526020909120600290910201805460018201546040516331a9108f60e11b8152600481019190915291925030916001600160a01b0390911690636352211e90602401602060405180830381865afa158015614540573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145649190615c82565b6001600160a01b03160361463157805460018201546040516323b872dd60e01b81523060048201526001600160a01b03868116602483015260448201929092529116906323b872dd90606401600060405180830381600087803b1580156145ca57600080fd5b505af11580156145de573d6000803e3d6000fd5b5050825460018401546040519081526001600160a01b03878116945090911691507f0ab2d5a490c8d5451470363f35341c42582170bbaf5bf4cd96b1afc7304e22ae9060200160405180910390a3600194505b61463a82614f3d565b50505b505b5090565b600d54600090610f319043615c26565b60006001602960008282546146689190615ce0565b90915550506029546040516bffffffffffffffffffffffff193360601b16602082015260348101919091524260548201524460748201526094016040516020818303038152906040528051906020012060001c905090565b600754600090801561463f5760076146d78261397f565b815481106146e7576146e7615d84565b6000918252602090912001546001600160a01b031691505090565b600047821580159061471c57508261471930613196565b10155b156148c557600c805460ff60a01b1916600160a01b179055600b546040805160028082526060820183526001600160a01b0390931692600092602083019080368337019050509050308160008151811061477857614778615d84565b60200260200101906001600160a01b031690816001600160a01b031681525050816001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156147d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147fa9190615c82565b8160018151811061480d5761480d615d84565b60200260200101906001600160a01b031690816001600160a01b0316815250506148383083876131b1565b6040516318cbafe560e01b81526001600160a01b038316906318cbafe59061486d908890600090869030904290600401615e39565b6000604051808303816000875af115801561488c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526148b49190810190615eaa565b5050600c805460ff60a01b19169055505b8047101561490d5760405162461bcd60e51b8152602060048201526015602482015274486f7720646964207765206c6f736520455448213f60581b6044820152606401610f77565b6122258147615c26565b60008061492383615511565b90508015610f47576127d032615511565b600261493e61327f565b600281111561494f5761494f6158a8565b146149b55760405162461bcd60e51b815260206004820152603060248201527f53686f756c646e277420726561636820746869732070617468206f6e2061697260448201526f191c9bdc081bdc881a1bdb995e5c1bdd60821b6064820152608401610f77565b6001600160a01b03831660009081526004602052604090205460ff1615614a1e5760405162461bcd60e51b815260206004820152601c60248201527f536f72727920626f742c2063616e2774206c657420796f75206f7574000000006044820152606401610f77565b6000614a29836142cc565b90506000614a36856142cc565b90508080614a415750815b15614b5b578015614a80576001600160a01b0385166000908152601260205260408120805460019290614a75908490615ce0565b90915550614ab59050565b8115614ab5576001600160a01b0384166000908152601260205260408120805460019290614aaf908490615ce0565b90915550505b60065415801590614adf57506001600160a01b03851660009081526005602052604090205460ff16155b8015614b0457506001600160a01b03841660009081526005602052604090205460ff16155b8015614b2957506001600160a01b03851660009081526004602052604090205460ff16155b8015614b4e57506001600160a01b03841660009081526004602052604090205460ff16155b15614b5b57614b5b6155b3565b82600080838015614b9057506001600160a01b038088166000908152601160209081526040808320938c168352929052205443145b8015614bd657506001600160a01b038088166000908152601460209081526040808320938c16835292815282822054601290915291902054600191614bd491615c26565b115b15614c42576000614be688615664565b90508015614c3c5760006064601d5489614c009190615c63565b614c0a9190615c4f565b9050614c17600282615c4f565b614c219085615ce0565b9350614c2e600282615c4f565b614c389084615ce0565b9250505b50614d21565b848015614c7357506001600160a01b038089166000908152601060209081526040808320938b168352929052205443145b8015614cb957506001600160a01b038089166000908152601360209081526040808320938b16835292815282822054601290915291902054600191614cb791615c26565b115b15614d21576000614cc989615664565b90508015614d1f5760006064601d5489614ce39190615c63565b614ced9190615c4f565b9050614cfa600282615c4f565b614d049085615ce0565b9350614d11600282615c4f565b614d1b9084615ce0565b9250505b505b6000614d2d8284615ce0565b905080841015614da55760405162461bcd60e51b815260206004820152603760248201527f43616e27742074616b652061776179206d6f7265207468616e20746865206f7260448201527f6967696e616c206e756d626572206f6620746f6b656e730000000000000000006064820152608401610f77565b6000614db18286615c26565b9050858015614dc257506000601c54115b15614e035760006064601c5483614dd99190615c63565b614de39190615c4f565b9050614def8185615ce0565b9350614dfb8183615c26565b915050614e4f565b868015614e1257506000601b54115b15614e4f5760006064601b5483614e299190615c63565b614e339190615c4f565b9050614e3f8185615ce0565b9350614e4b8183615c26565b9150505b8315614e5f57614e5f8a85613528565b8215614e7057614e708a30856133ee565b8015614e8157614e818a8a836133ee565b614e89615681565b50508515614ee25742600e556001600160a01b03808a166000818152601060209081526040808320948f168084529482528083204390556012825280832054938352601382528083209483529390529190912055614f31565b8615614f31576001600160a01b03808b166000818152601160209081526040808320948e1680845294825280832043905560128252808320549383526014825280832094835293905291909120555b50505050505050505050565b602a54818111614f9d5760405162461bcd60e51b815260206004820152602560248201527f4e465420696e64657820746f2062652072656d6f766564206f7574206f6620626044820152646f756e647360d81b6064820152608401610f77565b6000602a6000018381548110614fb557614fb5615d84565b60009182526020808320600290920290910180546001808301546001600160a01b03909216808652602f85526040808720848852909552938520949094559093509091602a906150059086615c26565b8154811061501557615015615d84565b9060005260206000209060020201602a600001868154811061503957615039615d84565b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b03909216919091178155600191820154910155602a80548061508257615082615db3565b60008281526020812060026000199093019283020180546001600160a01b03191681556001015590555050505050565b6001600160a01b0381166000908152600960205260408120805460ff191690556007546150e190600190615c26565b6001600160a01b0383166000908152600860205260409020549091508181101561518d5760006007600001838154811061511d5761511d615d84565b60009182526020808320909101546001600160a01b0316808352600890915260409091208390556007805491925082918490811061515d5761515d615d84565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505b6001600160a01b0383166000908152600860205260409020600019905560078054806133c7576133c7615db3565b6000806151c7602c5490565b116152145760405162461bcd60e51b815260206004820152601860248201527f4e6f204e465420636f6e74726163747320746f206275792100000000000000006044820152606401610f77565b602c8054801561525257816152288261397f565b8154811061523857615238615d84565b6000918252602090912001546001600160a01b0316615255565b60005b9250505090565b600354600090819081906001600160a01b03166152bb5760405162461bcd60e51b815260206004820152601e60248201527f5375646f4761746520616464726573732063616e2774206265207a65726f00006044820152606401610f77565b6003546040516001600160a01b038681166024830152909116906000908190839060440160408051601f198184030181529181526020820180516001600160e01b03166337404c6160e21b179052516153149190615f3b565b6000604051808303816000865af19150503d8060008114615351576040519150601f19603f3d011682016040523d82523d6000602084013e615356565b606091505b5091509150811561550757600080828060200190518101906153789190615ddd565b90925090506001600160a01b0381161580159061539457504782105b80156153a257506019548211155b156155045760405163ba5bddd760e01b81526001600160a01b0382811660048301526001995086169063ba5bddd790849060240160206040518083038185885af11580156153f4573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906154199190615d21565b6040805180820182526001600160a01b038c81168083526020808401868152602a8054600181018255600091825295517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2600290970296870180546001600160a01b0319169190961617909455517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d390940193909355808252602f8352838220858352835290839020869055825184815291820186905292995093975087937fd99878669b9e12c01419b6a5f8f4669400ae8da15fcdfb466066e2c785c4d5c2910160405180910390a25b50505b5050509193909250565b600061551c82613213565b1561552957506000919050565b6001600160a01b03821660009081526005602052604090205460ff1661113957506001600160a01b03166000818152600560205260408120805460ff1916600190811790915560068054808301825592527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90910180546001600160a01b03191690921790915590565b600654801561140b5760006155c9600183615c26565b9050600060066155da600185615c26565b815481106155ea576155ea615d84565b600091825260209091200154600680546001600160a01b039092169250908061561557615615615db3565b600082815260209020810160001990810180546001600160a01b031916905501905561564081615777565b506001600160a01b03166000908152600560205260409020805460ff191690555050565b60008061567083615777565b90508015610f47576127d032615777565b6000806000615690606461397f565b90506026548110156156a557600092506156f7565b6027546026546156b59190615ce0565b8110156156c557600192506156f7565b6028546027546026546156d89190615ce0565b6156e29190615ce0565b8110156156f257600292506156f7565b600392505b600091508183600381111561570e5761570e6158a8565b036157265761571b614296565b509092506141aa9050565b600183600381111561573a5761573a6158a8565b0361574e5761574761448b565b9150509091565b6002836003811115615762576157626158a8565b036141aa5761576f613ea2565b509150509091565b600061578282613213565b1561578f57506000919050565b6001600160a01b03821660009081526004602052604090205460ff16611139576001600160a01b0382166000908152600460205260409020805460ff19166001179055506001919050565b60005b838110156157f55781810151838201526020016157dd565b50506000910152565b602081526000825180602084015261581d8160408501602087016157da565b601f01601f19169190910160400192915050565b6001600160a01b038116811461140b57600080fd5b6000806040838503121561585957600080fd5b823561586481615831565b946020939093013593505050565b60006020828403121561588457600080fd5b5035919050565b60006020828403121561589d57600080fd5b813561222581615831565b634e487b7160e01b600052602160045260246000fd5b60208101600383106158d2576158d26158a8565b91905290565b6000806000806000608086880312156158f057600080fd5b85356158fb81615831565b9450602086013561590b81615831565b935060408601359250606086013567ffffffffffffffff8082111561592f57600080fd5b818801915088601f83011261594357600080fd5b81358181111561595257600080fd5b89602082850101111561596457600080fd5b9699959850939650602001949392505050565b60008060006060848603121561598c57600080fd5b833561599781615831565b925060208401356159a781615831565b929592945050506040919091013590565b801515811461140b57600080fd5b600080604083850312156159d957600080fd5b82356159e481615831565b915060208301356159f4816159b8565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715615a3e57615a3e6159ff565b604052919050565b600067ffffffffffffffff821115615a6057615a606159ff565b5060051b60200190565b600082601f830112615a7b57600080fd5b81356020615a90615a8b83615a46565b615a15565b82815260059290921b84018101918181019086841115615aaf57600080fd5b8286015b84811015615aca5780358352918301918301615ab3565b509695505050505050565b60008060408385031215615ae857600080fd5b823567ffffffffffffffff80821115615b0057600080fd5b818501915085601f830112615b1457600080fd5b81356020615b24615a8b83615a46565b82815260059290921b84018101918181019089841115615b4357600080fd5b948201945b83861015615b6a578535615b5b81615831565b82529482019490820190615b48565b96505086013592505080821115615b8057600080fd5b50615b8d85828601615a6a565b9150509250929050565b60008060408385031215615baa57600080fd5b8235615bb581615831565b915060208301356159f481615831565b6020808252603a90820152600080516020615f5883398151915260408201527f6e5275675072696365496d7061637450657254686f7573616e64000000000000606082015260800190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f4757610f47615c10565b634e487b7160e01b600052601260045260246000fd5b600082615c5e57615c5e615c39565b500490565b6000816000190483118215151615615c7d57615c7d615c10565b500290565b600060208284031215615c9457600080fd5b815161222581615831565b60208082526021908201527f4f6e6c79206f776e65722063616e2063616c6c2073656e6452616e646f6d4e466040820152601560fa1b606082015260800190565b80820180821115610f4757610f47615c10565b600080600060608486031215615d0857600080fd5b8351925060208401519150604084015190509250925092565b600060208284031215615d3357600080fd5b5051919050565b6001600160a01b03831681526040810160048310615d5a57615d5a6158a8565b8260208301529392505050565b600060208284031215615d7957600080fd5b8151612225816159b8565b634e487b7160e01b600052603260045260246000fd5b600060018201615dac57615dac615c10565b5060010190565b634e487b7160e01b600052603160045260246000fd5b600082615dd857615dd8615c39565b500690565b60008060408385031215615df057600080fd5b8251915060208301516159f481615831565b600080600060608486031215615e1757600080fd5b8351615e22816159b8565b602085015160409095015190969495509392505050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b81811015615e895784516001600160a01b031683529383019391830191600101615e64565b50506001600160a01b03969096166060850152505050608001529392505050565b60006020808385031215615ebd57600080fd5b825167ffffffffffffffff811115615ed457600080fd5b8301601f81018513615ee557600080fd5b8051615ef3615a8b82615a46565b81815260059190911b82018301908381019087831115615f1257600080fd5b928401925b82841015615f3057835182529284019290840190615f17565b979650505050505050565b60008251615f4d8184602087016157da565b919091019291505056fe4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744d69a264697066735822122003b7a432b53fee78df5836de40516a7034b850577127775e91ebea41ded5d81764736f6c63430008100033
Deployed Bytecode
0x6080604052600436106104a35760003560e01c80637f399bcb11610260578063b8c1825f11610144578063dc1052e2116100c1578063e98491ce11610085578063e98491ce14610e86578063ea336c7414610ea6578063eb4072db14610ebb578063f54d474414610ed0578063f9b12b0714610ef0578063fa656f4a14610f1057600080fd5b8063dc1052e214610df1578063dd62ed3e14610e11578063e26467be14610e31578063e33ad33c14610e51578063e879780214610e7157600080fd5b8063c5296a0f11610108578063c5296a0f14610d4b578063cc1776d314610d85578063d3428cfd14610d9b578063d46b6a3014610db1578063d66bbec714610dd157600080fd5b8063b8c1825f14610cbf578063bed7a20614610cdf578063beecd38b14610cff578063c1bf048a14610d15578063c241417814610d3557600080fd5b80639a2421eb116101dd578063a9059cbb116101a1578063a9059cbb14610bf9578063ac7f90d514610c19578063adce4cbf14610c39578063af99cc4f14610c59578063b0e9895d14610c6f578063b72995c814610c8f57600080fd5b80639a2421eb14610b4a5780639e21d7db14610b6a578063a3c7783b14610ba3578063a403fbd114610bb9578063a4a9860514610bd957600080fd5b80638cd09d50116102245780638cd09d5014610aae5780638ce4832414610ace5780638da5cb5b14610ae45780639182e0b114610b0457806395d89b4114610b1a57600080fd5b80637f399bcb14610a0c578063820941e214610a2a5780638253747e14610a3f57806388399f4d14610a5f578063896c034914610a7557600080fd5b80633bbac579116103875780635db231621161030457806366e305fd116102c857806366e305fd1461094857806370a082311461098157806370b65246146109a15780637160598d146109b657806373845954146109cc5780637f22bed8146109ec57600080fd5b80635db23162146108b25780635dcb14d2146108d25780636479255d146108f2578063651f8c851461091257806365c3d0511461092857600080fd5b80635098d5fb1161034b5780635098d5fb1461082c57806351c6590a1461085857806352a00fbb1461086b57806354fd4d501461087e5780635cc6780e1461089257600080fd5b80633bbac579146107905780633edb223f146107c057806340fb5698146107e05780634bd7ccfb146107f65780634f7041a51461081657600080fd5b8063154dca2c116104205780632137ede9116103e45780632137ede9146106d457806323b872dd146106e9578063313ce56714610709578063342aa8b51461073057806336ed48c01461075057806338a55f0e1461077057600080fd5b8063154dca2c146106445780631694505e1461065757806318160ddd146106895780631ab82d6d1461069e5780631f632cb2146106be57600080fd5b80630c3f6acf116104675780630c3f6acf146105885780630d326463146105aa5780631307d65a146105bf57806313af4035146105df578063150b7a02146105ff57600080fd5b8063052d1d48146104af57806306fdde03146104d7578063095ea7b3146105165780630ae96731146105465780630b13ace21461056857600080fd5b366104aa57005b600080fd5b3480156104bb57600080fd5b506104c4610f26565b6040519081526020015b60405180910390f35b3480156104e357600080fd5b5060408051808201909152600d81526c29bab237a93ab3902a37b5b2b760991b60208201525b6040516104ce91906157fe565b34801561052257600080fd5b50610536610531366004615846565b610f36565b60405190151581526020016104ce565b34801561055257600080fd5b50610566610561366004615872565b610f4d565b005b34801561057457600080fd5b5061053661058336600461588b565b611024565b34801561059457600080fd5b5061059d611077565b6040516104ce91906158be565b3480156105b657600080fd5b506104c4611081565b3480156105cb57600080fd5b506105366105da36600461588b565b6110b8565b3480156105eb57600080fd5b506105666105fa36600461588b565b611141565b34801561060b57600080fd5b5061062b61061a3660046158d8565b630a85bd0160e11b95945050505050565b6040516001600160e01b031990911681526020016104ce565b61053661065236600461588b565b6111c9565b34801561066357600080fd5b50600b546001600160a01b03165b6040516001600160a01b0390911681526020016104ce565b34801561069557600080fd5b506000546104c4565b3480156106aa57600080fd5b506105666106b9366004615872565b61139d565b3480156106ca57600080fd5b506104c4601f5481565b3480156106e057600080fd5b5061053661140e565b3480156106f557600080fd5b50610536610704366004615977565b6115f0565b34801561071557600080fd5b5061071e600981565b60405160ff90911681526020016104ce565b34801561073c57600080fd5b5061053661074b3660046159c6565b611612565b34801561075c57600080fd5b5061056661076b366004615872565b6116bc565b34801561077c57600080fd5b5061056661078b366004615846565b611742565b34801561079c57600080fd5b506105366107ab36600461588b565b60046020526000908152604090205460ff1681565b3480156107cc57600080fd5b506105666107db366004615872565b6118df565b3480156107ec57600080fd5b506104c460285481565b34801561080257600080fd5b50610566610811366004615872565b611964565b34801561082257600080fd5b506104c4601c5481565b34801561083857600080fd5b506108416119e9565b6040805192151583526020830191909152016104ce565b610566610866366004615872565b611a28565b61053661087936600461588b565b611d2a565b34801561088a57600080fd5b5060026104c4565b34801561089e57600080fd5b506105666108ad366004615846565b611d9b565b3480156108be57600080fd5b506105666108cd366004615872565b611fdc565b3480156108de57600080fd5b506105666108ed366004615872565b6120ab565b3480156108fe57600080fd5b5061053661090d36600461588b565b612130565b34801561091e57600080fd5b506104c460265481565b34801561093457600080fd5b50610566610943366004615872565b61222c565b34801561095457600080fd5b5061053661096336600461588b565b6001600160a01b031660009081526009602052604090205460ff1690565b34801561098d57600080fd5b506104c461099c36600461588b565b61230a565b3480156109ad57600080fd5b506104c4600281565b3480156109c257600080fd5b506104c460215481565b3480156109d857600080fd5b50600354610671906001600160a01b031681565b3480156109f857600080fd5b50610566610a07366004615872565b612315565b348015610a1857600080fd5b50600c546001600160a01b0316610671565b348015610a3657600080fd5b50602a546104c4565b348015610a4b57600080fd5b50610566610a5a36600461588b565b612375565b348015610a6b57600080fd5b506104c4601d5481565b348015610a8157600080fd5b50610536610a9036600461588b565b6001600160a01b03166000908152602e602052604090205460ff1690565b348015610aba57600080fd5b50610566610ac9366004615872565b612407565b348015610ada57600080fd5b506104c460275481565b348015610af057600080fd5b50600a54610671906001600160a01b031681565b348015610b1057600080fd5b506104c460175481565b348015610b2657600080fd5b506040805180820190915260078152665355444f52554760c81b6020820152610509565b348015610b5657600080fd5b50610566610b65366004615872565b612474565b348015610b7657600080fd5b50610536610b8536600461588b565b6001600160a01b03166000908152602d602052604090205460ff1690565b348015610baf57600080fd5b506104c460165481565b348015610bc557600080fd5b50610566610bd4366004615872565b6124e2565b348015610be557600080fd5b50610566610bf4366004615872565b6125c4565b348015610c0557600080fd5b50610536610c14366004615846565b612692565b348015610c2557600080fd5b50610536610c3436600461588b565b61269f565b348015610c4557600080fd5b50610536610c5436600461588b565b6127d7565b348015610c6557600080fd5b506104c460255481565b348015610c7b57600080fd5b50610566610c8a366004615ad5565b61285c565b348015610c9b57600080fd5b50610536610caa36600461588b565b60056020526000908152604090205460ff1681565b348015610ccb57600080fd5b50610566610cda366004615872565b612b65565b348015610ceb57600080fd5b50610566610cfa366004615872565b612beb565b348015610d0b57600080fd5b506104c460225481565b348015610d2157600080fd5b50610566610d30366004615872565b612c54565b348015610d4157600080fd5b506104c460155481565b348015610d5757600080fd5b50610d60612cc5565b6040805193151584526001600160a01b039092166020840152908201526060016104ce565b348015610d9157600080fd5b506104c4601b5481565b348015610da757600080fd5b506104c460235481565b348015610dbd57600080fd5b50610536610dcc36600461588b565b612d39565b348015610ddd57600080fd5b50610566610dec366004615872565b612d44565b348015610dfd57600080fd5b50610566610e0c366004615872565b612da9565b348015610e1d57600080fd5b506104c4610e2c366004615b97565b612e5e565b348015610e3d57600080fd5b50610566610e4c36600461588b565b612e8b565b348015610e5d57600080fd5b50610566610e6c36600461588b565b612f06565b348015610e7d57600080fd5b506104c4612f86565b348015610e9257600080fd5b50610536610ea136600461588b565b612fa8565b348015610eb257600080fd5b50610536613024565b348015610ec757600080fd5b50602c546104c4565b348015610edc57600080fd5b50610536610eeb36600461588b565b613059565b348015610efc57600080fd5b50610566610f0b366004615872565b6130db565b348015610f1c57600080fd5b506104c460245481565b6000610f3130613196565b905090565b6000610f433384846131b1565b5060015b92915050565b600a546001600160a01b03163314610f805760405162461bcd60e51b8152600401610f7790615bc5565b60405180910390fd5b6103e8811115610fcd5760405162461bcd60e51b8152602060048201526018602482015277056616c75652063616e6e6f742065786365656420313030360441b6044820152606401610f77565b80602254111561101f5760405162461bcd60e51b815260206004820181905260248201527f4d696e2063616e6e6f742065786365656420657863656564206e6577206d61786044820152606401610f77565b602355565b600061102f82613213565b8061105257506001600160a01b03821660009081526004602052604090205460ff165b80610f475750506001600160a01b031660009081526005602052604090205460ff1690565b6000610f3161327f565b600061108e600d54151590565b156110b257603c61109e600e5490565b6110a89042615c26565b610f319190615c4f565b50600090565b600a546000906001600160a01b031633146111305760405162461bcd60e51b815260206004820152603260248201527f4d757374206265206f776e657220746f2063616c6c2072656d6f76654e4654436044820152711bdb9d1c9858dd119c9bdb509d5e531a5cdd60721b6064820152608401610f77565b611139826132ad565b506001919050565b600a546001600160a01b031633146111a75760405162461bcd60e51b815260206004820152602360248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744f776044820152623732b960e91b6064820152608401610f77565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0381166000908152602e602052604081205460ff16156112325760405162461bcd60e51b815260206004820152601760248201527f416c726561647920627579696e672074686973206f6e650000000000000000006044820152606401610f77565b6001600160a01b0382166000908152602d602052604090205460ff1661128d5760405162461bcd60e51b815260206004820152601060248201526f139bdd081a5b881dda1a5d195b1a5cdd60821b6044820152606401610f77565b600354600a546001600160a01b0391821691163314611394576015546112b233613196565b101561130e5760405162461bcd60e51b815260206004820152602560248201527f4e6f7420656e6f75676820746f6b656e7320746f20616464204e465420636f6e6044820152641d1c9858dd60da1b6064820152608401610f77565b60165434101561136b5760405162461bcd60e51b815260206004820152602260248201527f4e6f7420656e6f7567682045544820746f20616464204e465420636f6e74726160448201526118dd60f21b6064820152608401610f77565b601554600061137a8280615c26565b90506113873330846133ee565b6113913382613528565b50505b610f4383613584565b600a546001600160a01b0316331461140b5760405162461bcd60e51b815260206004820152603e6024820152600080516020615f5883398151915260448201527f6e507269636550657263656e74496e637265617365546f53656c6c4e465400006064820152608401610f77565b50565b6000611418613673565b6000611422613874565b9050600061142e610f26565b8211156114d35761143d610f26565b6114479083615c26565b90506000611455606461397f565b60245411801591506114d157600061146b6139f2565b90506001600160a01b038116156114cf57600060646114898361230a565b6025546114969190615c63565b6114a09190615c4f565b905060008482106114b157846114b3565b815b90506114c08330836133ee565b6114ca8186615c26565b945050505b505b505b80156114e3576114e33082613ab7565b60006114ee83613b42565b905081156115115761151161150b600c546001600160a01b031690565b83613528565b600c546001600160a01b03166001600160a01b031663fff6cae96040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561155757600080fd5b505af115801561156b573d6000803e3d6000fd5b5050508115801591506115bc5742601f55604080518581526020810184905233917f9a5178ff42681b627314726ddac5afb7bf7f43659a3d45fba04e4cac720d0936910160405180910390a26115e8565b60405133907f2c58021a2da7aa3664cfb8e7baa4497f73c94ae0974ce255e30904702935844790600090a25b949350505050565b60006115fd843384613b8a565b611608848484613c39565b5060019392505050565b600a546000906001600160a01b0316331461166f5760405162461bcd60e51b815260206004820152601a60248201527f4f6e6c79206f776e65722063616e2063616c6c20616464426f740000000000006044820152606401610f77565b818015611680575061168083613213565b1561168d57506000610f47565b506001600160a01b0382166000908152600460205260409020805482151560ff19909116179055600192915050565b600a546001600160a01b031633146117305760405162461bcd60e51b815260206004820152603160248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657441636044820152701d1a5bdb919c995c5d595b98de54d95b99607a1b6064820152608401610f77565b61173c60275482613d9d565b50602755565b600a546001600160a01b031633146117a85760405162461bcd60e51b8152602060048201526024808201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2072657363756044820152631953919560e21b6064820152608401610f77565b6040516331a9108f60e11b81526004810182905230906001600160a01b03841690636352211e90602401602060405180830381865afa1580156117ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118139190615c82565b6001600160a01b0316146118755760405162461bcd60e51b8152602060048201526024808201527f5375646f527567206973206e6f7420746865206f776e6572206f6620746869736044820152630813919560e21b6064820152608401610f77565b6040516323b872dd60e01b8152306004820152336024820152604481018290526001600160a01b038316906323b872dd90606401600060405180830381600087803b1580156118c357600080fd5b505af11580156118d7573d6000803e3d6000fd5b505050505050565b600a546001600160a01b0316331461195f5760405162461bcd60e51b815260206004820152603760248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574436f60448201527f7374546f4164644e4654436f6e7472616374496e4554480000000000000000006064820152608401610f77565b601655565b600a546001600160a01b031633146119e45760405162461bcd60e51b815260206004820152603a60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574436f60448201527f7374546f4164644e4654436f6e7472616374496e546f6b656e730000000000006064820152608401610f77565b601555565b600a5460009081906001600160a01b03163314611a185760405162461bcd60e51b8152600401610f7790615c9f565b611a20613ea2565b915091509091565b600a546001600160a01b03163314611a825760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722063616e2063616c6c206164644c69717569646974796044820152606401610f77565b60008111611ad25760405162461bcd60e51b815260206004820152601860248201527f4e6f20746f6b656e7320666f72206c69717569646974792100000000000000006044820152606401610f77565b60003411611b1a5760405162461bcd60e51b81526020600482015260156024820152744e6f2045544820666f72206c69717569646974792160581b6044820152606401610f77565b600b54600c546001600160a01b039182169116611b38333085613c39565b611b433083856131b1565b6001600160a01b03821663f305d719343086808333611b6342600f615ce0565b60405160e089901b6001600160e01b03191681526001600160a01b039687166004820152602481019590955260448501939093526064840191909152909216608482015260a481019190915260c40160606040518083038185885af1158015611bd0573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190611bf59190615cf3565b50505034826001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c37573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c5b9190615c82565b6040516370a0823160e01b81526001600160a01b03848116600483015291909116906370a0823190602401602060405180830381865afa158015611ca3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc79190615d21565b1015611d215760405162461bcd60e51b815260206004820152602360248201527f455448206469646e27742067657420746f20746865207061697220636f6e74726044820152621858dd60ea1b6064820152608401610f77565b505043600d5550565b6000611d358261269f565b50610f43826001600160a01b03166347ccca026040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d77573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106529190615c82565b600a546001600160a01b03163314611e105760405162461bcd60e51b815260206004820152603260248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207265736375604482015271654e46545f416464546f547265617375727960701b6064820152608401610f77565b6040516331a9108f60e11b81526004810182905230906001600160a01b03841690636352211e90602401602060405180830381865afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190615c82565b6001600160a01b031614611edf5760405162461bcd60e51b815260206004820152602560248201527f5375646f47617465206973206e6f7420746865206f776e6572206f66207468696044820152641cc813919560da1b6064820152608401610f77565b6001600160a01b0382166000908152602d602052604090205460ff16611f475760405162461bcd60e51b815260206004820152601e60248201527f4e465420636f6e7472616374206e6f7420696e20616c6c6f772d6c69737400006044820152606401610f77565b604080518082019091526001600160a01b03928316815260208101918252602a805460018101825560009190915290517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2600290920291820180546001600160a01b0319169190941617909255517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d390910155565b600a546001600160a01b031633146120555760405162461bcd60e51b815260206004820152603660248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744d616044820152753c2832b931b2b73a2932b0b8383934b7b930ba34b7b760511b6064820152608401610f77565b60648111156120a65760405162461bcd60e51b815260206004820152601860248201527f56616c75652063616e6e6f7420657863656564203130302500000000000000006044820152606401610f77565b602455565b600a546001600160a01b0316331461211e5760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574416360448201526f74696f6e4672657175656e637942757960801b6064820152608401610f77565b61212a60265482613d9d565b50602655565b6040516308f25a8f60e01b815260009073b16c1342e617a5b6e4b631eb114483fdb289c0a49081906308f25a8f9061216e9086908690600401615d3a565b602060405180830381865afa15801561218b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121af9190615d67565b8061222557506040516308f25a8f60e01b81526001600160a01b038216906308f25a8f906121e4908690600190600401615d3a565b602060405180830381865afa158015612201573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122259190615d67565b9392505050565b600a546001600160a01b0316331461229e5760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574436f60448201526e7374546f527567496e546f6b656e7360881b6064820152608401610f77565b600054601e5411156123055760405162461bcd60e51b815260206004820152602a60248201527f43616e277420636861726765206d6f7265207468616e20616c6c206578697374604482015269696e6720746f6b656e7360b01b6064820152608401610f77565b601e55565b6000610f4782613196565b600a546001600160a01b031633146123705760405162461bcd60e51b815260206004820152602a6024820152600080516020615f588339815191526044820152696e53656c6c507269636560b01b6064820152608401610f77565b601a55565b600a546001600160a01b031633146123e55760405162461bcd60e51b815260206004820152602d60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574537560448201526c646f476174654164647265737360981b6064820152608401610f77565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b600a546001600160a01b0316331461246f5760405162461bcd60e51b815260206004820152602560248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657453656044820152640d8d8a8c2f60db1b6064820152608401610f77565b601b55565b600a546001600160a01b031633146120555760405162461bcd60e51b815260206004820152602b60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c20736574507260448201526a6f62436f6d6d756e69736d60a81b6064820152608401610f77565b600a546001600160a01b031633146125625760405162461bcd60e51b815260206004820152603b60248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744d6160448201527f7850657263656e744f66546f74616c537570706c7950657252756700000000006064820152608401610f77565b60648111156125bf5760405162461bcd60e51b8152602060048201526024808201527f50657263656e74206f6620737570706c792063616e6e6f7420657863656564206044820152633130302560e01b6064820152608401610f77565b602055565b600a546001600160a01b031633146125ee5760405162461bcd60e51b8152600401610f7790615bc5565b6103e881111561263b5760405162461bcd60e51b8152602060048201526018602482015277056616c75652063616e6e6f742065786365656420313030360441b6044820152606401610f77565b60235481111561268d5760405162461bcd60e51b815260206004820181905260248201527f4e6577206d696e2063616e6e6f742065786365656420657863656564206d61786044820152606401610f77565b602255565b6000610f43338484613c39565b60006126aa82612130565b6126ec5760405162461bcd60e51b8152602060048201526013602482015272139bdd0818481cdd591bdcddd85c081c1bdbdb606a1b6044820152606401610f77565b6003546040516366fe44d560e11b81526001600160a01b0384811660048301526000921690819063cdfc89aa90602401602060405180830381865afa158015612739573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275d9190615d67565b6127d0576040516355ec842360e11b81526001600160a01b03858116600483015282169063abd90846906024016020604051808303816000875af11580156127a9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127cd9190615d67565b91505b5092915050565b600a546000906001600160a01b031633146128345760405162461bcd60e51b815260206004820152601b60248201527f43616e206f6e6c792062652063616c6c6564206279206f776e657200000000006044820152606401610f77565b611139826001600160a01b03166000908152600f60205260409020805460ff19166001179055565b80518251146128c65760405162461bcd60e51b815260206004820152603060248201527f41646472657373657320616e6420746f6b656e2076616c756573206d7573742060448201526f0d0c2ecca40e6c2daca40d8cadccee8d60831b6064820152608401610f77565b600a546001600160a01b03163314806128f7575060026128e461327f565b60028111156128f5576128f56158a8565b145b6129435760405162461bcd60e51b815260206004820152601760248201527f596f752063616e27742063616c6c2074686973207965740000000000000000006044820152606401610f77565b3360009081526004602052604090205460ff1615801561297357503360009081526005602052604090205460ff16155b6129bf5760405162461bcd60e51b815260206004820152601760248201527f536f7272792c206e6f7420626f747320616c6c6f7765640000000000000000006044820152606401610f77565b600080808080805b8751811015612ace578781815181106129e2576129e2615d84565b602002602001015191508681815181106129fe576129fe615d84565b602002602001015194508486612a149190615ce0565b6001600160a01b0383166000908152600160205260409020549096509350612a3c8585615ce0565b6001600160a01b03831660008181526001602052604090819020839055519194509033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612a8f9089815260200190565b60405180910390a360175483118015612aae5750612aac82611024565b155b15612abc57612abc826141af565b80612ac681615d9a565b9150506129c7565b5033600090815260016020526040902054851115612b2e5760405162461bcd60e51b815260206004820152601d60248201527f4e6f7420656e6f75676820746f6b656e7320666f722061697264726f700000006044820152606401610f77565b3360009081526001602052604081208054879290612b4d908490615c26565b90915550612b5c905033614222565b50505050505050565b600a546001600160a01b03163314612bd95760405162461bcd60e51b815260206004820152603160248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657441636044820152701d1a5bdb919c995c5d595b98de54d95b1b607a1b6064820152608401610f77565b612be560285482613d9d565b50602855565b600a546001600160a01b03163314612c4f5760405162461bcd60e51b81526020600482015260336024820152600080516020615f588339815191526044820152726e4d696e757465734265747765656e5275677360681b6064820152608401610f77565b602155565b600a546001600160a01b03163314612cc05760405162461bcd60e51b815260206004820152602960248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744d6160448201526878427579507269636560b81b6064820152608401610f77565b601955565b600a54600090819081906001600160a01b03163314612d265760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722063616e2063616c6c2062757952616e646f6d4e46546044820152606401610f77565b612d2e614296565b925092509250909192565b6000610f47826142cc565b600a546001600160a01b03163314612da45760405162461bcd60e51b815260206004820152602f6024820152600080516020615f5883398151915260448201526e6e456c696769626c65546f6b656e7360881b6064820152608401610f77565b601755565b600a546001600160a01b03163314612e0f5760405162461bcd60e51b8152602060048201526024808201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657442756044820152630f2a8c2f60e31b6064820152608401610f77565b6064811115612e595760405162461bcd60e51b81526020600482015260166024820152755461782063616e6e6f7420657863656564203130302560501b6044820152606401610f77565b601c55565b6001600160a01b038083166000908152600260209081526040808320938516835292905290812054612225565b600a546001600160a01b03163314612efd5760405162461bcd60e51b815260206004820152602f60248201527f4d757374206265206f776e657220746f2063616c6c206164644e4654436f6e7460448201526e1c9858dd151bd05b1b1bddd31a5cdd608a1b6064820152608401610f77565b61140b816142ea565b600a546001600160a01b03163314612f7d5760405162461bcd60e51b815260206004820152603460248201527f4d757374206265206f776e657220746f2063616c6c2072656d6f76654e4654436044820152731bdb9d1c9858dd119c9bdb505b1b1bddd31a5cdd60621b6064820152608401610f77565b61140b81614371565b6000601f54600003612f985750600090565b603c601f54426110a89190615c26565b600a546000906001600160a01b0316331461301b5760405162461bcd60e51b815260206004820152602d60248201527f4d757374206265206f776e657220746f2063616c6c206164644e4654436f6e7460448201526c1c9858dd151bd09d5e531a5cdd609a1b6064820152608401610f77565b61113982613584565b600a546000906001600160a01b031633146130515760405162461bcd60e51b8152600401610f7790615c9f565b610f3161448b565b600a546000906001600160a01b031633146130b65760405162461bcd60e51b815260206004820152601b60248201527f43616e206f6e6c792062652063616c6c6564206279206f776e657200000000006044820152606401610f77565b611139826001600160a01b03166000908152600f60205260409020805460ff19169055565b600a546001600160a01b031633146131475760405162461bcd60e51b815260206004820152602960248201527f4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c2073657453616044820152680dcc8eed2c6d0a8c2f60bb1b6064820152608401610f77565b60648111156131915760405162461bcd60e51b81526020600482015260166024820152755461782063616e6e6f7420657863656564203130302560501b6044820152606401610f77565b601d55565b6001600160a01b031660009081526001602052604090205490565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b60006001600160a01b03821630148061323357506001600160a01b038216155b8061324b5750600a546001600160a01b038381169116145b8061325a575061325a826142cc565b80610f475750506001600160a01b03166000908152602d602052604090205460ff1690565b600061328c600d54151590565b156110b257600261329b614643565b10156132a75750600190565b50600290565b6001600160a01b0381166000908152602e602052604090205460ff161561140b576001600160a01b0381166000908152602e60205260408120805460ff19169055602c545b8082101561334457826001600160a01b0316602a600201838154811061331a5761331a615d84565b6000918252602090912001546001600160a01b0316146133445761333d82615d9a565b91506132f2565b602c613351600183615c26565b8154811061336157613361615d84565b600091825260209091200154602c80546001600160a01b03909216918490811061338d5761338d615d84565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055602c8054806133c7576133c7615db3565b600082815260209020810160001990810180546001600160a01b0319169055019055505050565b6001600160a01b03831660009081526001602052604090205481111561344d5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610f77565b6001600160a01b03831660009081526001602052604081208054839290613475908490615c26565b9091555050600c546001600160a01b038481169116146134985761349883614222565b6001600160a01b038216600090815260016020526040812080548392906134c0908490615ce0565b9091555050600c546001600160a01b038381169116146134e3576134e382614222565b816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161320691815260200190565b8061353283613196565b10156135745760405162461bcd60e51b81526020600482015260116024820152704e6f7420656e6f75676820746f6b656e7360781b6044820152606401610f77565b613580826000836133ee565b5050565b6001600160a01b0381166000908152602d602052604090205460ff166135ec5760405162461bcd60e51b815260206004820152601e60248201527f4e465420636f6e7472616374206e6f7420696e20616c6c6f77206c69737400006044820152606401610f77565b6001600160a01b0381166000908152602e602052604090205460ff1661140b57602c805460018181019092557f7416c943b4a09859521022fd2e90eac0dd9026dad28fa317782a135f28a860910180546001600160a01b0384166001600160a01b031990911681179091556000908152602e60205260409020805460ff1916909117905550565b600261367d611077565b600281111561368e5761368e6158a8565b146136cc5760405162461bcd60e51b815260206004820152600e60248201526d43616e277420727567207965742160901b6044820152606401610f77565b601f54600e54116137175760405162461bcd60e51b81526020600482015260156024820152744d75737420627579206265747765656e207275677360581b6044820152606401610f77565b601f54156137785760215461372a612f86565b10156137785760405162461bcd60e51b815260206004820152601860248201527f486f6c6420796f757220686f72736573207275676765727300000000000000006044820152606401610f77565b600a546001600160a01b031633146137e9573360009081526009602052604090205460ff166137e95760405162461bcd60e51b815260206004820152601760248201527f527567676572206d75737420626520656c696769626c650000000000000000006044820152606401610f77565b600a546001600160a01b0316331480159061380657506000601e54115b1561387257601e546138173361230a565b10156138655760405162461bcd60e51b815260206004820152601d60248201527f4e6f7420656e6f75676820746f6b656e7320666f722072756767696e670000006044820152606401610f77565b6138723330601e546133ee565b565b602254602354600091908110156138b05760006022546023546138979190615c26565b90506138a28161397f565b6138ac9083615ce0565b9150505b6103e88111156139155760405162461bcd60e51b815260206004820152602a60248201527f52616e646f6d20707269636520696d706163742073686f756c64206e6f7420656044820152697863656564203130302560b01b6064820152608401610f77565b600061392c61099c600c546001600160a01b031690565b90506103e861393b8383615c63565b6139459190615c4f565b92506000606461395460005490565b6020546139619190615c63565b61396b9190615c4f565b905080841115613979578093505b50505090565b60008082116139df5760405162461bcd60e51b815260206004820152602660248201527f43616e6e6f742067656e65726174652072616e646f6d206e756d626572206d6f604482015265064756c6f20360d41b6064820152608401610f77565b816139e8614653565b610f479190615dc9565b6000806139fd6146c0565b90506000613a096146c0565b90506000613a156146c0565b905060006001600160a01b03841615613a3657613a3184613196565b613a39565b60005b905060006001600160a01b03841615613a5a57613a5584613196565b613a5d565b60005b905060006001600160a01b03841615613a7e57613a7984613196565b613a81565b60005b9050818311613a9d57808211613a975783613aac565b84613aac565b808311613aaa5783613aac565b855b965050505050505090565b80600080016000828254613acb9190615ce0565b90915550506001600160a01b03821660009081526001602052604081208054839290613af8908490615ce0565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35050565b600c54600090600160a01b900460ff16613b85576000613b60610f26565b905082811015613b705780613b72565b825b92508215613b835761222583614702565b505b919050565b6001600160a01b03808416600090815260026020908152604080832093861683529290522054811115613bf85760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610f77565b6001600160a01b03808416600090815260026020908152604080832093861683529290529081208054839290613c2f908490615c26565b9091555050505050565b6001600160a01b038316301480613c5857506001600160a01b03821630145b80613c705750600a546001600160a01b038481169116145b15613c8557613c808383836133ee565b505050565b600d54613cea5760405162461bcd60e51b815260206004820152602d60248201527f43616e6e6f74207472616e7366657220746f6b656e73206265666f7265206c6960448201526c1c5d5a591a5d1e481859191959609a1b6064820152608401610f77565b600c54600160a01b900460ff1615613d0757613c808383836133ee565b6001613d1161327f565b6002811115613d2257613d226158a8565b03613d9257613d30836142cc565b15613d8757613d3e82614917565b15613d8757816001600160a01b03167f83efabacf9f7cf6e679b0fd9de0113ad1e05f72b1955dedadf0e01422a52234a82604051613d7e91815260200190565b60405180910390a25b613c808383836133ee565b613c80838383614934565b60006064821115613dfc5760405162461bcd60e51b815260206004820152602360248201527f4e65772070657263656e742076616c75652063616e6e6f74206578636565642060448201526203130360ec1b6064820152608401610f77565b6000602854602754602654613e119190615ce0565b613e1b9190615ce0565b90506000613e298583615c26565b90506000613e378583615ce0565b90506064811115613e995760405162461bcd60e51b815260206004820152602660248201527f436f6d62696e65642070657263656e74616765732063616e6e6f74206578636560448201526506564203130360d41b6064820152608401610f77565b50505092915050565b6000806000613eb0602a5490565b905080156141aa576000613ec38261397f565b90506000602a6000018281548110613edd57613edd615d84565b6000918252602080832060029290920290910180546001600160a01b03908116808552602f845260408086206001850154875290945293839020546003549351636ec9facd60e11b81526004810195909552919450909291169063dd93f59a906024016040805180830381865afa158015613f5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f809190615ddd565b5094508085118015613f945750601a548510155b156141a65760018115613fd1576000613fad8388615c26565b9050600083613fbd836064615c63565b613fc79190615c4f565b6018541115925050505b80156141a457825460018401546040516331a9108f60e11b8152600481019190915230916001600160a01b031690636352211e90602401602060405180830381865afa158015614025573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140499190615c82565b6001600160a01b0316036141a4578254600354600185015460405163095ea7b360e01b81526001600160a01b039283166004820152602481019190915291169063095ea7b390604401600060405180830381600087803b1580156140ac57600080fd5b505af11580156140c0573d6000803e3d6000fd5b505060035485546001870154604051636c197ff560e01b81526001600160a01b039283166004820152602481019190915291169250636c197ff591506044016060604051808303816000875af115801561411e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141429190615e02565b50909750955086156141a45761415784614f3d565b8254600184015460408051918252602082018990526001600160a01b03909216917f3148efce73b39b088f8c1497d8e056a6e8d58e3ffa171525862a6d4238397b90910160405180910390a25b505b5050505b509091565b6001600160a01b03166000818152600960209081526040808320805460ff19166001908117909155600780546008909452918420839055820181559091527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319169091179055565b60175461422e82613196565b108061423e575061423e81611024565b1561426d576001600160a01b03811660009081526009602052604090205460ff161561140b5761140b816150b2565b6001600160a01b03811660009081526009602052604090205460ff1661140b5761140b816141af565b60008080806142a4602c5490565b11156142c75760006142b46151bb565b90506142bf8161525c565b509094509150505b909192565b6001600160a01b03166000908152600f602052604090205460ff1690565b6001600160a01b0381166000908152602d602052604090205460ff1661140b57602b805460018181019092557f11c44e4875b74d31ff9fd779bf2566af7bd15b87fc985d01f5094b89e3669e4f0180546001600160a01b0384166001600160a01b031990911681179091556000908152602d60205260409020805460ff1916909117905550565b6001600160a01b0381166000908152602d602052604090205460ff161561140b576001600160a01b0381166000908152602d60205260408120805460ff19169055602b545b8082101561440857826001600160a01b0316602a60010183815481106143de576143de615d84565b6000918252602090912001546001600160a01b0316146144085761440182615d9a565b91506143b6565b602b614415600183615c26565b8154811061442557614425615d84565b600091825260209091200154602b80546001600160a01b03909216918490811061445157614451615d84565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055602b8054806133c7576133c7615db3565b600080614497602a5490565b9050801561463f5760006144a96139f2565b90506144b481611024565b61463d5760006144c38361397f565b90506000602a60000182815481106144dd576144dd615d84565b60009182526020909120600290910201805460018201546040516331a9108f60e11b8152600481019190915291925030916001600160a01b0390911690636352211e90602401602060405180830381865afa158015614540573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145649190615c82565b6001600160a01b03160361463157805460018201546040516323b872dd60e01b81523060048201526001600160a01b03868116602483015260448201929092529116906323b872dd90606401600060405180830381600087803b1580156145ca57600080fd5b505af11580156145de573d6000803e3d6000fd5b5050825460018401546040519081526001600160a01b03878116945090911691507f0ab2d5a490c8d5451470363f35341c42582170bbaf5bf4cd96b1afc7304e22ae9060200160405180910390a3600194505b61463a82614f3d565b50505b505b5090565b600d54600090610f319043615c26565b60006001602960008282546146689190615ce0565b90915550506029546040516bffffffffffffffffffffffff193360601b16602082015260348101919091524260548201524460748201526094016040516020818303038152906040528051906020012060001c905090565b600754600090801561463f5760076146d78261397f565b815481106146e7576146e7615d84565b6000918252602090912001546001600160a01b031691505090565b600047821580159061471c57508261471930613196565b10155b156148c557600c805460ff60a01b1916600160a01b179055600b546040805160028082526060820183526001600160a01b0390931692600092602083019080368337019050509050308160008151811061477857614778615d84565b60200260200101906001600160a01b031690816001600160a01b031681525050816001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa1580156147d6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147fa9190615c82565b8160018151811061480d5761480d615d84565b60200260200101906001600160a01b031690816001600160a01b0316815250506148383083876131b1565b6040516318cbafe560e01b81526001600160a01b038316906318cbafe59061486d908890600090869030904290600401615e39565b6000604051808303816000875af115801561488c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526148b49190810190615eaa565b5050600c805460ff60a01b19169055505b8047101561490d5760405162461bcd60e51b8152602060048201526015602482015274486f7720646964207765206c6f736520455448213f60581b6044820152606401610f77565b6122258147615c26565b60008061492383615511565b90508015610f47576127d032615511565b600261493e61327f565b600281111561494f5761494f6158a8565b146149b55760405162461bcd60e51b815260206004820152603060248201527f53686f756c646e277420726561636820746869732070617468206f6e2061697260448201526f191c9bdc081bdc881a1bdb995e5c1bdd60821b6064820152608401610f77565b6001600160a01b03831660009081526004602052604090205460ff1615614a1e5760405162461bcd60e51b815260206004820152601c60248201527f536f72727920626f742c2063616e2774206c657420796f75206f7574000000006044820152606401610f77565b6000614a29836142cc565b90506000614a36856142cc565b90508080614a415750815b15614b5b578015614a80576001600160a01b0385166000908152601260205260408120805460019290614a75908490615ce0565b90915550614ab59050565b8115614ab5576001600160a01b0384166000908152601260205260408120805460019290614aaf908490615ce0565b90915550505b60065415801590614adf57506001600160a01b03851660009081526005602052604090205460ff16155b8015614b0457506001600160a01b03841660009081526005602052604090205460ff16155b8015614b2957506001600160a01b03851660009081526004602052604090205460ff16155b8015614b4e57506001600160a01b03841660009081526004602052604090205460ff16155b15614b5b57614b5b6155b3565b82600080838015614b9057506001600160a01b038088166000908152601160209081526040808320938c168352929052205443145b8015614bd657506001600160a01b038088166000908152601460209081526040808320938c16835292815282822054601290915291902054600191614bd491615c26565b115b15614c42576000614be688615664565b90508015614c3c5760006064601d5489614c009190615c63565b614c0a9190615c4f565b9050614c17600282615c4f565b614c219085615ce0565b9350614c2e600282615c4f565b614c389084615ce0565b9250505b50614d21565b848015614c7357506001600160a01b038089166000908152601060209081526040808320938b168352929052205443145b8015614cb957506001600160a01b038089166000908152601360209081526040808320938b16835292815282822054601290915291902054600191614cb791615c26565b115b15614d21576000614cc989615664565b90508015614d1f5760006064601d5489614ce39190615c63565b614ced9190615c4f565b9050614cfa600282615c4f565b614d049085615ce0565b9350614d11600282615c4f565b614d1b9084615ce0565b9250505b505b6000614d2d8284615ce0565b905080841015614da55760405162461bcd60e51b815260206004820152603760248201527f43616e27742074616b652061776179206d6f7265207468616e20746865206f7260448201527f6967696e616c206e756d626572206f6620746f6b656e730000000000000000006064820152608401610f77565b6000614db18286615c26565b9050858015614dc257506000601c54115b15614e035760006064601c5483614dd99190615c63565b614de39190615c4f565b9050614def8185615ce0565b9350614dfb8183615c26565b915050614e4f565b868015614e1257506000601b54115b15614e4f5760006064601b5483614e299190615c63565b614e339190615c4f565b9050614e3f8185615ce0565b9350614e4b8183615c26565b9150505b8315614e5f57614e5f8a85613528565b8215614e7057614e708a30856133ee565b8015614e8157614e818a8a836133ee565b614e89615681565b50508515614ee25742600e556001600160a01b03808a166000818152601060209081526040808320948f168084529482528083204390556012825280832054938352601382528083209483529390529190912055614f31565b8615614f31576001600160a01b03808b166000818152601160209081526040808320948e1680845294825280832043905560128252808320549383526014825280832094835293905291909120555b50505050505050505050565b602a54818111614f9d5760405162461bcd60e51b815260206004820152602560248201527f4e465420696e64657820746f2062652072656d6f766564206f7574206f6620626044820152646f756e647360d81b6064820152608401610f77565b6000602a6000018381548110614fb557614fb5615d84565b60009182526020808320600290920290910180546001808301546001600160a01b03909216808652602f85526040808720848852909552938520949094559093509091602a906150059086615c26565b8154811061501557615015615d84565b9060005260206000209060020201602a600001868154811061503957615039615d84565b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b03909216919091178155600191820154910155602a80548061508257615082615db3565b60008281526020812060026000199093019283020180546001600160a01b03191681556001015590555050505050565b6001600160a01b0381166000908152600960205260408120805460ff191690556007546150e190600190615c26565b6001600160a01b0383166000908152600860205260409020549091508181101561518d5760006007600001838154811061511d5761511d615d84565b60009182526020808320909101546001600160a01b0316808352600890915260409091208390556007805491925082918490811061515d5761515d615d84565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550505b6001600160a01b0383166000908152600860205260409020600019905560078054806133c7576133c7615db3565b6000806151c7602c5490565b116152145760405162461bcd60e51b815260206004820152601860248201527f4e6f204e465420636f6e74726163747320746f206275792100000000000000006044820152606401610f77565b602c8054801561525257816152288261397f565b8154811061523857615238615d84565b6000918252602090912001546001600160a01b0316615255565b60005b9250505090565b600354600090819081906001600160a01b03166152bb5760405162461bcd60e51b815260206004820152601e60248201527f5375646f4761746520616464726573732063616e2774206265207a65726f00006044820152606401610f77565b6003546040516001600160a01b038681166024830152909116906000908190839060440160408051601f198184030181529181526020820180516001600160e01b03166337404c6160e21b179052516153149190615f3b565b6000604051808303816000865af19150503d8060008114615351576040519150601f19603f3d011682016040523d82523d6000602084013e615356565b606091505b5091509150811561550757600080828060200190518101906153789190615ddd565b90925090506001600160a01b0381161580159061539457504782105b80156153a257506019548211155b156155045760405163ba5bddd760e01b81526001600160a01b0382811660048301526001995086169063ba5bddd790849060240160206040518083038185885af11580156153f4573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906154199190615d21565b6040805180820182526001600160a01b038c81168083526020808401868152602a8054600181018255600091825295517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d2600290970296870180546001600160a01b0319169190961617909455517fbeced09521047d05b8960b7e7bcc1d1292cf3e4b2a6b63f48335cbde5f7545d390940193909355808252602f8352838220858352835290839020869055825184815291820186905292995093975087937fd99878669b9e12c01419b6a5f8f4669400ae8da15fcdfb466066e2c785c4d5c2910160405180910390a25b50505b5050509193909250565b600061551c82613213565b1561552957506000919050565b6001600160a01b03821660009081526005602052604090205460ff1661113957506001600160a01b03166000818152600560205260408120805460ff1916600190811790915560068054808301825592527ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f90910180546001600160a01b03191690921790915590565b600654801561140b5760006155c9600183615c26565b9050600060066155da600185615c26565b815481106155ea576155ea615d84565b600091825260209091200154600680546001600160a01b039092169250908061561557615615615db3565b600082815260209020810160001990810180546001600160a01b031916905501905561564081615777565b506001600160a01b03166000908152600560205260409020805460ff191690555050565b60008061567083615777565b90508015610f47576127d032615777565b6000806000615690606461397f565b90506026548110156156a557600092506156f7565b6027546026546156b59190615ce0565b8110156156c557600192506156f7565b6028546027546026546156d89190615ce0565b6156e29190615ce0565b8110156156f257600292506156f7565b600392505b600091508183600381111561570e5761570e6158a8565b036157265761571b614296565b509092506141aa9050565b600183600381111561573a5761573a6158a8565b0361574e5761574761448b565b9150509091565b6002836003811115615762576157626158a8565b036141aa5761576f613ea2565b509150509091565b600061578282613213565b1561578f57506000919050565b6001600160a01b03821660009081526004602052604090205460ff16611139576001600160a01b0382166000908152600460205260409020805460ff19166001179055506001919050565b60005b838110156157f55781810151838201526020016157dd565b50506000910152565b602081526000825180602084015261581d8160408501602087016157da565b601f01601f19169190910160400192915050565b6001600160a01b038116811461140b57600080fd5b6000806040838503121561585957600080fd5b823561586481615831565b946020939093013593505050565b60006020828403121561588457600080fd5b5035919050565b60006020828403121561589d57600080fd5b813561222581615831565b634e487b7160e01b600052602160045260246000fd5b60208101600383106158d2576158d26158a8565b91905290565b6000806000806000608086880312156158f057600080fd5b85356158fb81615831565b9450602086013561590b81615831565b935060408601359250606086013567ffffffffffffffff8082111561592f57600080fd5b818801915088601f83011261594357600080fd5b81358181111561595257600080fd5b89602082850101111561596457600080fd5b9699959850939650602001949392505050565b60008060006060848603121561598c57600080fd5b833561599781615831565b925060208401356159a781615831565b929592945050506040919091013590565b801515811461140b57600080fd5b600080604083850312156159d957600080fd5b82356159e481615831565b915060208301356159f4816159b8565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715615a3e57615a3e6159ff565b604052919050565b600067ffffffffffffffff821115615a6057615a606159ff565b5060051b60200190565b600082601f830112615a7b57600080fd5b81356020615a90615a8b83615a46565b615a15565b82815260059290921b84018101918181019086841115615aaf57600080fd5b8286015b84811015615aca5780358352918301918301615ab3565b509695505050505050565b60008060408385031215615ae857600080fd5b823567ffffffffffffffff80821115615b0057600080fd5b818501915085601f830112615b1457600080fd5b81356020615b24615a8b83615a46565b82815260059290921b84018101918181019089841115615b4357600080fd5b948201945b83861015615b6a578535615b5b81615831565b82529482019490820190615b48565b96505086013592505080821115615b8057600080fd5b50615b8d85828601615a6a565b9150509250929050565b60008060408385031215615baa57600080fd5b8235615bb581615831565b915060208301356159f481615831565b6020808252603a90820152600080516020615f5883398151915260408201527f6e5275675072696365496d7061637450657254686f7573616e64000000000000606082015260800190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610f4757610f47615c10565b634e487b7160e01b600052601260045260246000fd5b600082615c5e57615c5e615c39565b500490565b6000816000190483118215151615615c7d57615c7d615c10565b500290565b600060208284031215615c9457600080fd5b815161222581615831565b60208082526021908201527f4f6e6c79206f776e65722063616e2063616c6c2073656e6452616e646f6d4e466040820152601560fa1b606082015260800190565b80820180821115610f4757610f47615c10565b600080600060608486031215615d0857600080fd5b8351925060208401519150604084015190509250925092565b600060208284031215615d3357600080fd5b5051919050565b6001600160a01b03831681526040810160048310615d5a57615d5a6158a8565b8260208301529392505050565b600060208284031215615d7957600080fd5b8151612225816159b8565b634e487b7160e01b600052603260045260246000fd5b600060018201615dac57615dac615c10565b5060010190565b634e487b7160e01b600052603160045260246000fd5b600082615dd857615dd8615c39565b500690565b60008060408385031215615df057600080fd5b8251915060208301516159f481615831565b600080600060608486031215615e1757600080fd5b8351615e22816159b8565b602085015160409095015190969495509392505050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b81811015615e895784516001600160a01b031683529383019391830191600101615e64565b50506001600160a01b03969096166060850152505050608001529392505050565b60006020808385031215615ebd57600080fd5b825167ffffffffffffffff811115615ed457600080fd5b8301601f81018513615ee557600080fd5b8051615ef3615a8b82615a46565b81815260059190911b82018301908381019087831115615f1257600080fd5b928401925b82841015615f3057835182529284019290840190615f17565b979650505050505050565b60008251615f4d8184602087016157da565b919091019291505056fe4f6e6c79206f776e657220616c6c6f77656420746f2063616c6c207365744d69a264697066735822122003b7a432b53fee78df5836de40516a7034b850577127775e91ebea41ded5d81764736f6c63430008100033
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.