ERC-20
Overview
Max Total Supply
1,000,000 IGMI
Holders
137
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
IGMI
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
/* SPDX-License-Identifier: MIT */ /** * * * * "we're gonna make it"? fuck yall, I'M gonna make it * * * https://igmi.tech * * * @title IGMI - good traders may profit, but only one buyer is gonna make it. * * @notice * Increase your balanace above qualifying tiers to earn entries for the prize, decrease your balance below those tiers to lose them. * Once the timeframe has elapsed, only one current entrant will win the entire LP. * * IMPORTANT: THE ABILITY TO TRADE THIS TOKEN WILL END WHEN A WINNER IS REQUESTED. * * @notice * ONE ENTRY - 500 tokens (500 * 10 ** 18) // .05% * TWO ENTRIES - 1_000 tokens (1_000 * 10 ** 18) // .1% * THREE ENTRIES - 1_500 tokens (1_500 * 10 ** 18) // .15% * FOUR ENTRIES - 2_000 tokens (2_000 * 10 ** 18) // .2% * FIVE ENTRIES - 2_500 tokens (2_500 * 10 ** 18) // .25% * SEVEN ENTRIES - 3_500 tokens (3_500 * 10 ** 18) // .35% * TEN ENTRIES - 5_000 tokens (5_000 * 10 ** 18) // .5% * * @notice * DETAILS: * After 24 hours, owner will close trading permanently and request a random number off-chain. * The random number is automatically used to find a random user by their entry index. * When the winner is found, liquidity is completely pulled by the contract, and the winning user gets ALL of the ETH pulled from the liquidity pool. * You are free to swap in and out of the pool, earning and losing entries as you wish, until that point. * Exit the game and take your profits, or risk it for a chance at the big prize. Are you gonna make it? * * NOTE: The contract owner is permanently incapable of pulling liquidity for themself. */ pragma solidity ^0.8.20; import {VRFV2WrapperConsumerBase} from "@chainlink/v0.8/vrf/VRFV2WrapperConsumerBase.sol"; import {IUniswapV2Pair} from "@uniswap-core/interfaces/IUniswapV2Pair.sol"; import {IUniswapV2Router02} from "@uniswap-periphery/interfaces/IUniswapV2Router02.sol"; import {IUniswapV2Factory} from "@uniswap-core/interfaces/IUniswapV2Factory.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function balanceOf(address holder) external returns (uint256); } contract IGMI is ERC20, Ownable, VRFV2WrapperConsumerBase { /*////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ /** * @dev comments on structs denote the bit size of the element */ /** * @dev struct assigned to all users * @param buy user's buy block * @param exemptfee sets user exempt from fees * @param exemptlimit sets user exempt from limits * @param index the user's entry index (represents the user in the global entries) */ struct USER { uint256 buy; // 32 uint256 exemptfee; // 8 uint256 exemptlimit; // 8 uint256 index; // 24 } /** * @dev struct which stores values used in transfer checks * @param changeblock the block on which trading begins * @param limitsblock the block after which limits are no longer checked * @param standardmode when enabled, there are no fees, restrictions, or entry logging * @param feesenabled when enabled, fees are taken * @param cooldown the minimum block count that must pass before a user can perform another transfer * @param eoatransfers when enabled, wallet-to-wallet transfers (externally-owned addresses, EOAs) are allowed */ struct CHECKS { uint256 changeblock; // 32 uint256 limitsblock; // 32 uint256 standardmode; // 8 uint256 feesenabled; // 8 uint256 cooldown; // 8 uint256 eoatransfers; // 8 } /** * @dev struct which stores fee values * @param feebuy fee on buy * @param feesell fee on sell * @param feeliq fee for liquidity on both buys and sells */ struct FEES { uint256 feebuy; // 8 uint256 feesell; // 8 uint256 feeliq; // 8 } /** * @dev struct which stores max amounts at the 0th decimal (1 vs. 1 * 1e18) * @param maxtx max transaction amount for non-exempt users within the limits window * @param maxbal max balance for non-exempt users within the limits window */ struct MAX { uint256 maxtx; // 16 uint256 maxbal; // 24 } /*////////////////////////////////////////////////////////////// CONSTANTS //////////////////////////////////////////////////////////////*/ // minimum amount of tokens held to qualify for corresponding entry counts uint256 private constant ONE_ENTRY = 500 * 1e18; uint256 private constant TWO_ENTRIES = 1_000 * 1e18; uint256 private constant THREE_ENTRIES = 1_500 * 1e18; uint256 private constant FOUR_ENTRIES = 2_000 * 1e18; uint256 private constant FIVE_ENTRIES = 2_500 * 1e18; uint256 private constant SEVEN_ENTRIES = 3_500 * 1e18; uint256 private constant TEN_ENTRIES = 5_000 * 1e18; uint256 private constant DECIMAL_MULTIPLIER = 1e18; uint256 private constant ROLL_IN_PROGRESS = 9999999; /*////////////////////////////////////////////////////////////// STORAGE //////////////////////////////////////////////////////////////*/ /** * @dev * this uint256 holds these values in this order: CHECKS, FEES, MAX, currentUserIndex, currentEntryIndex * see getAllData() */ uint256 private data_; uint128 public _randomResult; uint48 public _closeLimitBlock; uint48 public _closedAtTimestamp; uint32 public _linkFee; uint256 public _pureRandomNumber; // general user storage mapping(address => uint256) private _users; // individual user entry tracking mapping(address => uint256) private _userEntries; // entries 'array' mapping(uint256 => uint256) private _allEntries; // user index matching mapping(uint256 => address) private _indexUser; address private immutable WETH; IUniswapV2Router02 public immutable ROUTER; address private _pair; address private _wrapper; address public _winner; /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event FeesUpdated(uint256 buy, uint256 sell, uint256 liq); event MaxUpdated(uint256 maxtx, uint256 maxbal); event FeesToggled(bool feesenabled); event StandardModeToggled(bool standardmode); event EOATransfersToggled(bool eoatransfers); event LimitBlockReduced(uint256 newblock); event CooldownReduced(uint256 newcooldown); event LinkFeeUpdated(uint256 newfee); event LiqBoosted(address token, uint256 amount); event EntriesGained(address user, uint256 amount); event EntriesLost(address user, uint256 amount); event DiceRolled(uint256 indexed requestId); event DiceLanded(uint256 indexed requestId, uint256 indexed result); event SentToWinner(address _holder); /*////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ error sendToZero(); error notOpen(); error alreadyOpen(); error vrfCallbackNotComplete(); error closeConditionsUnmet(); error notAuthorized(); error exceedMaxBalance(); error belowMinBalance(); error exceedMaxTx(); error valueTooLow(); error valueTooHigh(); error txCooldown(); error noEOAtoEOATransfers(); error failedToSendETH(); error castOverflow(uint256 value, uint256 bytecount); /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(address router_, address linkAddress, address wrapperAddress) payable ERC20("IGMI", "IGMI") VRFV2WrapperConsumerBase(linkAddress, wrapperAddress) { _wrapper = wrapperAddress; _setUserData(address(this), 0, 1, 1, 0); _setUserData(msg.sender, 0, 1, 1, 0); _mint(address(this), 1_000_000 * DECIMAL_MULTIPLIER); ROUTER = IUniswapV2Router02(router_); WETH = ROUTER.WETH(); _linkFee = uint32(1_000_000); } /*////////////////////////////////////////////////////////////// STANDARD LOGIC //////////////////////////////////////////////////////////////*/ receive() external payable {} // ERC20 override function _transfer(address sender, address recipient, uint256 amount) internal override { uint256 data = data_; CHECKS memory checks = _getChecksData(data); USER memory senderData = _getUserData(_users[sender]); USER memory recipientData = _getUserData(_users[recipient]); // common conditions for no fee/limit transfers if ( sender == address(this) // mid-swap || checks.standardmode != 0 // no fees, no restrictions for anyone || (senderData.exemptfee != 0 && senderData.exemptlimit != 0) // token contract, owner, or, after trading close, the router || (recipientData.exemptfee != 0 && recipientData.exemptlimit != 0) // token contract, owner, or, after trading close, the router ) { super._transfer(sender, recipient, amount); // fee/limit logic } else { // check if trading is open if (checks.changeblock == 0) { revert notOpen(); } bool buy; address pair = _pair; MAX memory max = _getMaxData(data); FEES memory fees = _getFeesData(data); USER memory origData = _getUserData(_users[tx.origin]); // ------BUY------ // if (pair == sender) { // buy restrictions if (recipientData.exemptlimit == 0) { // restrictions - launch window if (checks.limitsblock > block.number) { if (block.number < checks.changeblock + 2) { // first two blocks get 20% buy fees fees.feebuy = 10; fees.feeliq = 10; } if (amount > max.maxtx * DECIMAL_MULTIPLIER) { revert exceedMaxTx(); } if ((balanceOf(recipient) + amount) > max.maxbal * DECIMAL_MULTIPLIER) { revert exceedMaxBalance(); } // cooldown unchecked { if ( recipientData.buy + checks.cooldown > block.number || origData.buy + checks.cooldown > block.number ) { revert txCooldown(); } } // 10% buy first 10 minutes fees.feebuy = 7; fees.feeliq = 3; } // set user's buy block recipientData.buy = block.number; // update user buy block if they have previously bought (this is otherwise handled in _checkEligibility) if (recipientData.index != 0) { _setUserData( recipient, recipientData.buy, recipientData.exemptfee, recipientData.exemptlimit, recipientData.index ); } _checkEligibility( recipient, recipientData, amount, data, fees, true, checks.feesenabled != 0 ? true : false ); // assigning a buy block to tx.origin if (tx.origin != recipient && checks.limitsblock > block.number) { _setUserData( tx.origin, recipientData.buy, recipientData.exemptfee, recipientData.exemptlimit, recipientData.index ); } } buy = true; } else { // ------SELL------ // if (pair == recipient) { // restrictions - permanent if (senderData.exemptlimit == 0 && checks.cooldown != 0) { unchecked { if ( senderData.buy + checks.cooldown > block.number || origData.buy + checks.cooldown > block.number ) { revert txCooldown(); } } } _checkEligibility( sender, senderData, amount, data, fees, false, checks.feesenabled != 0 ? true : false ); uint256 contractBalance = balanceOf(address(this)); // only attempt to sell an amount that uniswap shouldnt complain about (INSUFFICIENT_OUTPUT_AMOUNT) if (contractBalance > ONE_ENTRY) { // perform fee swap for maximum 5% price impact uint256 priceImpactLimiter = (balanceOf(recipient) * 5) / 100; _nestedSwap(contractBalance > priceImpactLimiter ? priceImpactLimiter : (contractBalance - 1)); } } } // take fees on swaps to/from pair only, and perform final transfer if ( checks.feesenabled != 0 && ( ((recipientData.exemptfee == 0) && pair == sender) || ((senderData.exemptfee == 0) && pair == recipient) ) ) { _collectAndTransfer(sender, recipient, amount, buy, fees); // EOA to EOA transfer (no fees) } else { // if recipient is not exempt from limits, assign highest limit between sender and recipient to recipient if (pair != sender && pair != recipient) { // if EOA to EOA transfers are disabled, revert if (checks.eoatransfers == 0) revert noEOAtoEOATransfers(); if (recipientData.exemptfee == 0 && recipientData.buy < senderData.buy) { recipientData.buy = senderData.buy; } // check if sender loses entries _checkEligibility(sender, senderData, amount, data, fees, false, false); // check if recipient gains entries _checkEligibility(recipient, recipientData, amount, data, fees, true, false); } super._transfer(sender, recipient, amount); } } } /*////////////////////////////////////////////////////////////// PRIVATE/INTERNAL WRITE //////////////////////////////////////////////////////////////*/ /** * @dev * use this function to take fees and perform the final transfer * although this function is only used once, it's separated due to stack-too-deep error * @param sender the address of the sender * @param recipient the address of the recipient * @param amount the amount being sent * @param buy whether or not this is a buy * @param fees the FEES struct */ function _collectAndTransfer(address sender, address recipient, uint256 amount, bool buy, FEES memory fees) private { (uint256 fee, uint256 liqFee) = buy ? (fees.feebuy, fees.feeliq) : (fees.feesell, fees.feeliq); uint256 collection = (amount * fee) / 100; uint256 liq = (amount * liqFee) / 100; uint256 remainder = amount - collection - liq; if (buy) { // on buy, keep liq fee amount in the pair super._transfer(sender, recipient, remainder); } else { // ensures liq fee tokens are not counted as part of the amountIn if (liq != 0) { super._transfer(sender, recipient, liq); IUniswapV2Pair(recipient).sync(); } super._transfer(sender, recipient, remainder); } if (collection != 0) { super._transfer(sender, address(this), collection); } } function _nestedSwap(uint256 amount) private { address[] memory path = new address[](2); path[0] = address(this); path[1] = WETH; ROUTER.swapExactTokensForETHSupportingFeeOnTransferTokens(amount, 0, path, address(this), block.timestamp); } /** * @dev * this function determines if user will gain or lose entries for this transaction, and adds/removes them accordingly * this function also sets all data for this user and assigns them an index if they are receiving tokens for the first time * @param user address of the user being checked * @param userData the user's USER struct * @param amount the amount being sent * @param data the global data_ value, sent through memory * @param buy used to determine whether we should check if user is gaining or losing entries */ function _checkEligibility( address user, USER memory userData, uint256 amount, uint256 data, FEES memory fees, bool buy, bool checkFees ) private { uint256 entriesCount = _getUserEntryCount(user); uint256 eligibleCount; // balance is increasing if (buy) { if (checkFees) { if (fees.feebuy != 0 && fees.feeliq != 0) { eligibleCount = getEligibleCount( balanceOf(user) + (amount - ((amount * fees.feebuy) / 100) - ((amount * fees.feeliq) / 100)) ); } else if (fees.feebuy != 0 && fees.feeliq == 0) { eligibleCount = getEligibleCount(balanceOf(user) + (amount - ((amount * fees.feebuy) / 100))); } else if (fees.feebuy == 0 && fees.feeliq != 0) { eligibleCount = getEligibleCount(balanceOf(user) + (amount - ((amount * fees.feeliq) / 100))); } else { // feebuy == 0 && feeliq == 0, but feesell != 0 eligibleCount = getEligibleCount(balanceOf(user) + amount); } // EOA to EOA transfer } else { eligibleCount = getEligibleCount(balanceOf(user) + amount); } uint256 userIndex = userData.index; uint256 newUserIndex = userData.index; // store user and assign an index if not yet assigned (first buy) if (userIndex == 0) { userIndex = _getCurrentUserIndex(data); newUserIndex = userIndex; _setUserData(user, userData.buy, userData.exemptfee, userData.exemptlimit, userIndex); _indexUser[userIndex] = user; unchecked { ++newUserIndex; } } // skip remaining logic and only update userIndex if user is new and entry count is unchanged if ((eligibleCount == 0 || eligibleCount == entriesCount) && userIndex != newUserIndex) { _setCurrentUserIndex(data, newUserIndex); return; } if (eligibleCount > entriesCount) { uint256 entryIndex = _getCurrentEntryIndex(data); // add user entries to the user's entries 'array' (uint256 newEntriesAmount) = _addEntriesToUserEntries(user, eligibleCount - entriesCount, entryIndex); // add user entries to the total entries 'array' uint256 newEntryIndex = _addEntriesToAllEntries(userIndex, newEntriesAmount, entryIndex); if (userIndex != newUserIndex) { // update both current user index and entry index if adding a qualifying user on this buy _setCurrentIndeces(data, newUserIndex, newEntryIndex); } else { // only update entry index _setCurrentEntryIndex(data, newEntryIndex); } emit EntriesGained(user, eligibleCount - entriesCount); } // balance is decreasing } else { // avoid underflow if (balanceOf(user) < amount) return; eligibleCount = getEligibleCount(balanceOf(user) - amount); if (eligibleCount < entriesCount) { uint256 subAmount = entriesCount - eligibleCount; uint24[] memory removedEntries = new uint24[](subAmount); // remove user entries from the user's entries 'array' removedEntries = _removeEntriesFromUserEntries(user, subAmount); // remove user entries from the total entries 'array' _removeEntriesFromAllEntries(removedEntries); emit EntriesLost(user, subAmount); } } } /** * @dev * this function iteratively adds entries to the _allEntries mapping * the _allEntries mapping is treated as an object which contains sequential arrays of 10 numbers each. * entries are stored as such: _allEntries[0] = [0,1,2,3,4,5,6,7,8,9], _allEntries[1] = [10,11,12,13,14,15,16,17,18,19], etc. * we can use division and modulo on a given entry index to always find the key of the 'array' it's in, and its position in that 'array' * note that 24 in the following function represents the maximum bit size of an index. * @param indexUser the index of the user being assigned entries * @param entryCount the number of entries to assign this user * @param currentEntryIndex the next entry index to assign a user * @return currentEntryIndex the new value of currentEntryIndex, after adding entries */ function _addEntriesToAllEntries(uint256 indexUser, uint256 entryCount, uint256 currentEntryIndex) private returns (uint256) { uint256 currentKey; unchecked { currentKey = currentEntryIndex / 10; } uint256 currentBitObject = _allEntries[currentKey]; for (uint256 i; i < entryCount;) { // retrieve key of current bit object uint256 key; unchecked { key = currentEntryIndex / 10; } // determine position within that bit object // ex. currentPosition = 35 // key = 35 / 10 = 3 // position within bit object = 35 % (3 * 10) = 5 // cannot modulo by 0, so just use currentPosition if key is 0 uint256 position; unchecked { position = currentEntryIndex > 9 ? currentEntryIndex % (key * 10) : currentEntryIndex; } // determine starting position // ex. position within bit object is 2 // startingPosition = 24 (length) * 2 = 48 uint256 startingPosition; unchecked { startingPosition = 24 * position; } if (startingPosition != 0) { currentBitObject |= indexUser << startingPosition; } else { currentBitObject = indexUser << startingPosition; } // update storage if at the end of the uint, or the loop is complete unchecked { if (position == 9 || i + 1 == entryCount) { _allEntries[key] = currentBitObject; } ++currentEntryIndex; ++i; } } // return new entry index, to be stored in calling function return currentEntryIndex; } /** * @dev adds entries to a user's entries 'array' * @param user the address of the user * @param addAmount the amount of entries to add * @param currentEntryIndex the global current entry index, which was not affected by this function * @return addAmount the amount of entries added */ function _addEntriesToUserEntries(address user, uint256 addAmount, uint256 currentEntryIndex) private returns (uint256) { uint256 currentBitObject = _userEntries[user]; // get the next entry position (, uint256 nextEntryPosition) = _getCurrentEntryCountAndNextEntryPosition(currentBitObject); // although a 10th entry means the next entry bit position is 240 (24 * 10), // nextEntryPosition doesn't get a final 24 added to it in _getCurrentEntryCountAndNextEntryPosition() before the loop ends. // this would matter if we had a tier that qualifies for 9 entries, but we don't, so it doesn't. // it's cheaper not to perform that check and addition. if (nextEntryPosition == 216) return (addAmount); for (uint256 i; i < addAmount;) { currentBitObject |= currentEntryIndex << nextEntryPosition; unchecked { ++currentEntryIndex; ++i; } if (nextEntryPosition == 216) { // ensure we don't attempt to add more entries than will fit (216 means user is in the 10-entry tier already) break; } unchecked { nextEntryPosition += 24; } } _userEntries[user] = currentBitObject; return (addAmount); } /** * @dev this function accepts an array of entries to find and remove from the global entries 'array' * @param entries an array of entries to remove */ function _removeEntriesFromAllEntries(uint24[] memory entries) private { uint256 entriesLength = entries.length; uint256 previousKey; uint256 currentBitObject; for (uint256 i; i < entriesLength;) { uint256 entry = entries[i]; uint256 currentKey; // get the key for the current entry unchecked { currentKey = entry / 10; } if (i == 0) { currentBitObject = _allEntries[currentKey]; } if (i != 0 && previousKey != currentKey) { // store previous changes _allEntries[previousKey] = currentBitObject; // get current key's 'bit object' and store it to memory currentBitObject = _allEntries[currentKey]; } // determine position within that bit object // cannot modulo by 0, so just use currentPosition if key is 0 uint256 position; unchecked { position = entry > 9 ? entry % (currentKey * 10) : entry; } uint256 startingPosition; unchecked { startingPosition = 24 * position; } // update the bit object by removing this entry currentBitObject = _clearBits(currentBitObject, startingPosition, 24); // retain the updated bit object in memory, unless this is the last iteration of the loop unchecked { if (i + 1 == entriesLength) { _allEntries[currentKey] = currentBitObject; } previousKey = currentKey; ++i; } } } /** * @dev this function removes entries from a user's entries 'array', starting at the most recently-added entry * @param user the address of the user to remove entries from * @param subAmount the amount of entries to remove * @return removedEntries the entries that were removed, which now must be removed from the global entries 'array' */ function _removeEntriesFromUserEntries(address user, uint256 subAmount) private returns (uint24[] memory) { // get existing entry count uint256 entryCount = _getUserEntryCount(user); // get the user's bit object uint256 entriesBits = _userEntries[user]; // initialize array of entries being removed uint24[] memory removedEntries = new uint24[](subAmount); // start bitPosition at the user's last entry uint256 bitPosition = (entryCount * 24); // add entries being removed to memory array and find starting point for mask for (uint256 i; i < subAmount;) { // move to the beginning of entry's bit space unchecked { bitPosition -= 24; } removedEntries[i] = uint24(entriesBits >> bitPosition); unchecked { ++i; } } // update the bit object by removing this entry _userEntries[user] = _clearBits(entriesBits, bitPosition, (24 * subAmount)); // return an array of the user's removed entries to remove from the total entries return removedEntries; } /** * @dev * sets the entire global data_ value at once * the bitSize array holds the size of each sequential element to ensure they are put in the right position * @param tempData an array of all of the values in the global data_ value. they are as follows, with corresponding bit size: * @dev uint256 changeblock, // 32 * @dev uint256 limitsblock, // 32 * @dev uint256 standardmode, // 8 * @dev uint256 feesenabled, // 8 * @dev uint256 cooldown, // 8 * @dev uint256 feebuy, // 8 * @dev uint256 feesell, // 8 * @dev uint256 feeliq, // 8 * @dev uint256 maxtx, // 16 * @dev uint256 maxbal, // 24 * @dev uint256 userIndex, // 24 * @dev uint256 entryIndex, // 24 */ function _setData(uint256[13] memory tempData) private { uint256 length = tempData.length; uint256 shift; uint256 data; uint8[13] memory bitSize = [32, 32, 8, 8, 8, 8, 8, 8, 8, 16, 24, 24, 24]; // bit size for each element require(length == 13); for (uint256 i; i < length;) { _overflowCheck(tempData[i], bitSize[i]); data |= tempData[i] << shift; unchecked { shift += bitSize[i]; ++i; } } data_ = data; } /** * @dev sets data assigned to a user * @param user the address of the user * @param buy the user's buy block * @param exemptfee whether or not the user is exempt from fees (0 is false, 1 is true) * @param exemptlimit whether or not the user is exempt from limits (0 is false, 1 is true) * @param index the user's index, used when giving them entries */ function _setUserData( address user, uint256 buy, // 32 uint256 exemptfee, // 8 uint256 exemptlimit, // 8 uint256 index // 24 ) private { _overflowCheck(buy, 32); uint256 data = buy; _overflowCheck(exemptfee, 8); data |= exemptfee << 32; _overflowCheck(exemptlimit, 8); data |= exemptlimit << 40; _overflowCheck(index, 24); data |= index << 48; _users[user] = data; } /** * @dev sets just the CHECKS struct in the global data_ value * @param changeblock the block on which trading begins * @param limitsblock the block after which limits are no longer checked * @param standardmode when enabled, there are no fees, restrictions, or entry logging * @param feesenabled when enabled, fees are taken * @param cooldown the minimum block count that must pass before a user can perform another transfer * @param eoatransfers when enabled, allow transfers from one EOA to another (wallet to wallet) */ function _setChecksData( uint256 changeblock, // 32 uint256 limitsblock, // 32 uint256 standardmode, // 8 uint256 feesenabled, // 8 uint256 cooldown, // 8 uint256 eoatransfers // 8 ) private { uint256 data = _clearBits(data_, 0, 96); _overflowCheck(changeblock, 32); data |= changeblock << 0; _overflowCheck(limitsblock, 32); data |= limitsblock << 32; _overflowCheck(standardmode, 8); data |= standardmode << 64; _overflowCheck(feesenabled, 8); data |= feesenabled << 72; _overflowCheck(cooldown, 8); data |= cooldown << 80; _overflowCheck(eoatransfers, 8); data |= eoatransfers << 88; data_ = data; } /** * @dev sets the changeblock to 0 to halt trading */ function _setChecksDataCloseTrading() private { data_ = _clearBits(data_, 0, 32); } /** * @dev sets just the FEES struct in the global data_ value * @param feebuy fee on buy * @param feesell fee on sell * @param feeliq fee for liquidity on both buys and sells */ function _setFeesData( uint256 feebuy, // 8 uint256 feesell, // 8 uint256 feeliq // 8 ) private { uint256 data = _clearBits(data_, 96, 24); _overflowCheck(feebuy, 8); data |= feebuy << 96; _overflowCheck(feesell, 8); data |= feesell << 104; _overflowCheck(feeliq, 8); data |= feeliq << 112; data_ = data; } /** * @dev sets just the MAX struct in the global data_ value * @param maxtx max transaction amount for non-exempt users within the limits window * @param maxbal max balance for non-exempt users within the limits window */ function _setMaxData( uint256 maxtx, // 16 uint256 maxbal // 24 ) private { uint256 data = _clearBits(data_, 120, 40); _overflowCheck(maxtx, 16); data |= maxtx << 120; _overflowCheck(maxbal, 24); data |= maxbal << 136; data_ = data; } /** * @dev sets the next user index * @param data the global data_ value * @param index the next user index to assign a user */ function _setCurrentUserIndex(uint256 data, uint256 index) private { data = _clearBits(data, 160, 24); _overflowCheck(index, 24); data |= index << 160; data_ = data; } /** * @dev sets the next entry index * @param data the global data_ value * @param index the next entry index to assign a user */ function _setCurrentEntryIndex(uint256 data, uint256 index) private { data = _clearBits(data, 184, 24); _overflowCheck(index, 24); data |= index << 184; data_ = data; } /** * @dev sets both the next user index and the next entry index * @param data the global data_ value * @param userIndex the next index to assign a user * @param entryIndex the next entry index to assign a user */ function _setCurrentIndeces(uint256 data, uint256 userIndex, uint256 entryIndex) private { data = _clearBits(data, 160, 48); _overflowCheck(userIndex, 24); data |= userIndex << 160; _overflowCheck(entryIndex, 24); data |= entryIndex << 184; data_ = data; } /** * @dev sets a user exempt from fees, limits, or both * @param userAddress the address of the user * @param exemptfee whether or not the user is exempt from fees (0 is false, 1 is true) * @param exemptlimit whether or not the user is exempt from limits (0 is false, 1 is true) */ function _setUserExempt(address userAddress, bool exemptfee, bool exemptlimit) private { USER memory user = _getUserData(_users[userAddress]); uint256 fee = exemptfee ? uint256(1) : 0; uint256 limit = exemptlimit ? uint256(1) : 0; _setUserData(userAddress, user.buy, fee, limit, user.index); } /** * @dev * this function is run as the result of a callback from the VRF coordinator * we are taking the huge random number we get back, and getting a random entry index <= the total number of entries recorded * @param _requestId the id created by the original request * @param _randomWords the random number */ function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal override { uint256 finalIndex = _getCurrentEntryIndex(data_); unchecked { --finalIndex; // last entry index assigned is one less than current value of currentEntryIndex } _pureRandomNumber = _randomWords[0]; uint128 randomResult = uint128(_pureRandomNumber % (finalIndex)); _randomResult = randomResult; emit DiceLanded(_requestId, uint256(randomResult)); // perform an encodeCall so that the values above can get set successfully even if this function call fails // it is possible for this function to fail if it consumes more gas than the coordinator expects it to // in that case, dev will run the external sendToWinner function and pay the gas themself (bool success,) = address(this).call(abi.encodeCall(this.sendToWinner, (uint256(randomResult), finalIndex))); success; } /** * @dev * first, we attempt to get a winner at the previously-defined winner entry index * if there is no user index at this position (because the user that was here sold and lost this entry), * we iterate up through the entries looking for a user index that is not 0 * if there are none above this point, we go back to the original winner entry index and iterate down * we do not accept any circumstance in which the user index is 0, as this index is not assigned to anyone. * when we find a winner, we pull all liquidity and send the winner all of the ETH. * @param randomResult the currently-selected random entry index * @param finalIndex the very last recorded entry index (used for finding a new entry if the selected index has no entrant) */ function _sendToWinner(uint256 randomResult, uint256 finalIndex) private { uint256 winnerIndex = randomResult; address winner; (, winner) = _getEntrantIdAndAddressAtIndex(winnerIndex); // if address at this index is unassigned (sold their entry), find the next entry index assigned to a user if (winner == address(0)) { // if not at the end of the entry list, increment through entries if (winnerIndex < finalIndex) { uint256 diff = finalIndex - winnerIndex; for (uint256 i; i < diff;) { unchecked { ++winnerIndex; } (, winner) = _getEntrantIdAndAddressAtIndex(winnerIndex); if (winner != address(0)) { break; } unchecked { ++i; } } } // contingency for reaching the end of the list - decrement from originally-selected entry index if (winner == address(0) && winnerIndex == finalIndex) { winnerIndex = randomResult; for (uint256 i; i < randomResult;) { unchecked { --winnerIndex; } (, winner) = _getEntrantIdAndAddressAtIndex(winnerIndex); if (winner != address(0)) { break; } unchecked { ++i; } } } require(winner != address(0)); _randomResult = uint128(winnerIndex); } _winner = winner; IERC20(_pair).approve(address(ROUTER), type(uint256).max); (, uint256 lpEth) = ROUTER.removeLiquidityETH( address(this), IERC20(_pair).balanceOf(address(this)), 0, 0, address(this), block.timestamp ); (bool sent,) = winner.call{value: lpEth}(""); require(sent, "Failed to send!"); emit SentToWinner(winner); } /*////////////////////////////////////////////////////////////// PRIVATE/INTERNAL VIEW/PURE //////////////////////////////////////////////////////////////*/ /** * @dev checks amount qualifies for entries * @param amount amount being transferred * @return entryCount the amount of entries this amount qualifies for */ function getEligibleCount(uint256 amount) private pure returns (uint256) { if (amount < ONE_ENTRY) { return 0; } else if (amount < TWO_ENTRIES) { return 1; } else if (amount < THREE_ENTRIES) { return 2; } else if (amount < FOUR_ENTRIES) { return 3; } else if (amount < FIVE_ENTRIES) { return 4; } else if (amount < SEVEN_ENTRIES) { return 5; } else if (amount < TEN_ENTRIES) { return 7; } else { return 10; } } /** * @param user address of the user being checked * @param position the position of the entry being retrieved in the user's entries 'array' (0 through 9, 10 total possible positions) * @return entryId the entry id at that position */ function _getUserEntries(address user, uint256 position) private view returns (uint24) { require(position < 10, "Out of range"); uint256 bitPosition = position * 24; uint256 bitObj = _userEntries[user]; uint24 entryId = uint24(bitObj >> bitPosition); return (entryId); } /** * @param user address of the user being checked * @return count the amount of entries user has */ function _getUserEntryCount(address user) private view returns (uint256) { uint256 currentBitObject = _userEntries[user]; // get the current entry count (uint256 count,) = _getCurrentEntryCountAndNextEntryPosition(currentBitObject); return count; } /** * @dev performs bit masking. see comments in function for step-by-step description of behavior * @param bitObject the bits to be manipulated * @param startingPosition the position within the bits to start the mask * @param bitSize the total bit size to mask from the starting position * @return clearedBits the original bit 'object' with the targeted bit space cleared */ function _clearBits(uint256 bitObject, uint256 startingPosition, uint256 bitSize) private pure returns (uint256 clearedBits) { uint256 mask = ~(uint256(2 ** bitSize - 1) << startingPosition); // set all 1s for the length of the bit space (as in a uint24), shift it left x bits to make it the appropriate entry, and then invert it to set those bits to zero // ex. mask = 11110001111 clearedBits = bitObject & mask; // takes the existing bits and overwrites with the new 0 value bits // ex. currentBits = 10110110110 // ex. new value = 10110000110 } /** * @dev * the _allEntries mapping is treated as an object which contains sequential arrays of 10 numbers each. * entries are stored as such: _allEntries[0] = [0,1,2,3,4,5,6,7,8,9], _allEntries[1] = [10,11,12,13,14,15,16,17,18,19], etc. * we can use division and modulo on a given entry index to always find the key of the 'array' its in, and its position in that 'array' * note that 24 in the following function represents the maximum bit size of an index. * @param index the entry index * @return userIndex the user index at that entry position * @return userAddress the address of the user with that userIndex */ function _getEntrantIdAndAddressAtIndex(uint256 index) private view returns (uint24, address) { uint256 key = index / 10; uint256 position = index > 9 ? index % (key * 10) : index; uint256 bitPosition = position * 24; uint256 bitObj = _allEntries[key]; uint24 userIndex = uint24(bitObj >> bitPosition); return (userIndex, _indexUser[userIndex]); } /** * @dev this function finds the existing entry count of a user, and the bit space after their most recently recorded entry * @param bitObject the entries bit 'object' of the user * @return count the amount of entries the user already has * @return nextEntryPosition the bit position where the next entry can be inserted */ function _getCurrentEntryCountAndNextEntryPosition(uint256 bitObject) private pure returns (uint256 count, uint256 nextEntryPosition) { for (; count < 10;) { uint24 entry; nextEntryPosition = count * 24; entry = uint24(bitObject >> nextEntryPosition); if (entry == 0) { break; } unchecked { ++count; } } } /** * @dev returns all of the values in the global data_ value * @param data the global data_ value * @return checks the CHECKS struct * @return fees the FEES struct * @return max the MAX struct * @return currentUserIndex the next user index to be assigned to a user * @return currentEntryIndex the next entry index to be assigned to a user */ function _getAllData(uint256 data) private pure returns ( CHECKS memory checks, FEES memory fees, MAX memory max, uint256 currentUserIndex, uint256 currentEntryIndex ) { checks.changeblock = uint256(uint32(data)); checks.limitsblock = uint256(uint32(data >> 32)); checks.standardmode = uint256(uint8(data >> 64)); checks.feesenabled = uint256(uint8(data >> 72)); checks.cooldown = uint256(uint8(data >> 80)); checks.eoatransfers = uint256(uint8(data >> 88)); fees.feebuy = uint256(uint8(data >> 96)); fees.feesell = uint256(uint8(data >> 104)); fees.feeliq = uint256(uint8(data >> 112)); max.maxtx = uint256(uint16(data >> 120)); max.maxbal = uint256(uint24(data >> 136)); currentUserIndex = uint256(uint24(data >> 160)); currentEntryIndex = uint256(uint24(data >> 184)); } function _getUserData(uint256 user) private pure returns (USER memory user_) { user_.buy = uint256(uint32(user)); user_.exemptfee = uint256(uint8(user >> 32)); user_.exemptlimit = uint256(uint8(user >> 40)); user_.index = uint256(uint24(user >> 48)); } function _getChecksData(uint256 data) private pure returns (CHECKS memory checks) { checks.changeblock = uint256(uint32(data)); checks.limitsblock = uint256(uint32(data >> 32)); checks.standardmode = uint256(uint8(data >> 64)); checks.feesenabled = uint256(uint8(data >> 72)); checks.cooldown = uint256(uint8(data >> 80)); checks.eoatransfers = uint256(uint8(data >> 88)); } function _getFeesData(uint256 data) private pure returns (FEES memory fees) { fees.feebuy = uint256(uint8(data >> 96)); fees.feesell = uint256(uint8(data >> 104)); fees.feeliq = uint256(uint8(data >> 112)); } function _getMaxData(uint256 data) private pure returns (MAX memory max) { max.maxtx = uint256(uint16(data >> 120)); max.maxbal = uint256(uint24(data >> 136)); } function _getCurrentUserIndex(uint256 data) private pure returns (uint256) { return uint256(uint24(data >> 160)); } function _getCurrentEntryIndex(uint256 data) private pure returns (uint256) { return uint256(uint24(data >> 184)); } function _overflowCheck(uint256 value, uint256 bytecount) private pure { //checks if value fits in target uint type if (value >= uint256(1 << bytecount)) { revert castOverflow(uint256(value), uint256(bytecount)); } } function _hasCode(address _address) private view returns (bool) { return _address.code.length != 0; } /*////////////////////////////////////////////////////////////// EXTERNAL VIEW //////////////////////////////////////////////////////////////*/ function getUserData(address user) external view returns (USER memory user_) { return _getUserData(_users[user]); } function getUserEntryCount(address sender) external view returns (uint256) { return _getUserEntryCount(sender); } function getAllUserEntries(address user) external view returns (uint24[] memory) { uint256 bitObj = _userEntries[user]; uint24[] memory entries = new uint24[](10); for (uint256 i; i < 10;) { uint256 bitPosition = i * 24; entries[i] = uint24(bitObj >> bitPosition); unchecked { ++i; } } return entries; } function getAllData() external view returns ( CHECKS memory checks, FEES memory fees, MAX memory max, uint256 currentUserIndex, uint256 currentEntryIndex ) { return _getAllData(data_); } function getEntryMinimums() external pure returns (uint256[] memory) { uint256[] memory entries = new uint256[](7); entries[0] = ONE_ENTRY; entries[1] = TWO_ENTRIES; entries[2] = THREE_ENTRIES; entries[3] = FOUR_ENTRIES; entries[4] = FIVE_ENTRIES; entries[5] = SEVEN_ENTRIES; entries[6] = TEN_ENTRIES; return entries; } function getWETH() external view returns (address) { return WETH; } function getPair() external view returns (address) { return _pair; } function getIndexUser(uint256 index) external view returns (address) { return _indexUser[index]; } function getEntrantIdAndAddressAtIndex(uint256 index) external view returns (uint24, address) { return _getEntrantIdAndAddressAtIndex(index); } /*////////////////////////////////////////////////////////////// EXTERNAL WRITE //////////////////////////////////////////////////////////////*/ function deploy(uint48 duration) public payable onlyOwner { // can only be deployed once if (_pair != address(0)) { revert alreadyOpen(); } // close limit must exceed one hour if (duration <= 300) { // (60 minutes * 60 seconds) / 12 seconds per block = 300 revert valueTooLow(); } _approve(address(this), address(ROUTER), type(uint256).max); ROUTER.addLiquidityETH{value: address(this).balance}( address(this), balanceOf(address(this)) - 1, 0, 0, address(this), block.timestamp ); address factory = ROUTER.factory(); address pair = IUniswapV2Factory(factory).getPair(WETH, address(this)); _setUserData(pair, 0, 1, 0, 0); _pair = pair; _closeLimitBlock = uint48(block.number + duration); // userIndex must start at 1, as 0 needs to mean 'no user' // entryIndex must start at 1 for edge case in which first user adds to existing entries with multiple buys uint256[13] memory data = [ block.number, // launch block block.number + 50, // limits window ((~12-second block time * 50) / 60 seconds) = ~10 minutes 0, // standard mode 1, // fees enabled 3, // min blocks for cooldown 1, // allow EOA to EOA transfers 4, // buy fee 4, // sell fee 1, // liq fee 6_000, // max tx - (fee + liq fee + amount for ten entries) * 1.2 (120%) to try and account for price action 10_000, // max balance 1, // userIndex 1 // entryIndex ]; _setData(data); } /** * @dev * closes trading by setting launch block to 0, performs a final price-impact-limited contract swap, * and requests a random number from chainlink VRF * this can only be done if trading is open, if it has not already been successfully run, and the specified time has passed (24 hours) */ function closeTradingAndRollDice() external onlyOwner returns (uint256 requestId) { CHECKS memory checks = _getChecksData(data_); uint256 currentEntryIndex = _getCurrentEntryIndex(data_); if ( checks.changeblock == 0 // not launched, or this has been run already || _closedAtTimestamp != 0 // this has been run already || block.number < uint256(_closeLimitBlock) // timeframe has not elapsed || currentEntryIndex == 1 // no entries have been registered yet ) { revert closeConditionsUnmet(); } uint256 contractTokenBalance = balanceOf(address(this)); // only attempt to sell an amount that uniswap shouldnt complain about (INSUFFICIENT_OUTPUT_AMOUNT) if (contractTokenBalance > ONE_ENTRY) { // perform final fee swap uint256 impactSell = (balanceOf(_pair) * 20) / 100; if (contractTokenBalance > impactSell) { contractTokenBalance = impactSell; } _nestedSwap(contractTokenBalance - 1); } uint256 contractETHBalance = address(this).balance; // don't require the fee transfer to succeed. dev can collect fees on their own later, if necessary if (contractETHBalance != 0) { (bool success,) = owner().call{value: address(this).balance}(""); success; } // for display purposes _closedAtTimestamp = uint48(block.timestamp); // reset changeblock to zero, halting trading _setChecksDataCloseTrading(); // exempt router from limits for the liquidity removal _setUserData(address(ROUTER), 0, 1, 1, 0); requestId = requestRandomness(uint32(_linkFee), uint16(3), uint32(1)); // actual gas cost is roughly 300_000 _randomResult = uint128(ROLL_IN_PROGRESS); emit DiceRolled(requestId); } /** * @dev * this function is external as a contingency for the possible scenario in which this function fails when executed in the VRF callback. * ideally, this is not needed, but better to be safe than sorry. * because this function is used internally, and we are using memory values in order to minimize gas, it must accept parameters. * if this function is called externally by owner, * whatever parameters they provided are ignored, and correct ones are pulled from existing contract logic * this eliminates unnecessary work to retrieve correct values, and prevents exploitation by the owner * @param randomResult the random index set in fulfillRandomWords (pass 0 when calling as owner) * @param currentEntryIndex the final entry index assigned to a user before trading closed (pass 0 when calling as owner) */ function sendToWinner(uint256 randomResult, uint256 currentEntryIndex) external { if (msg.sender != address(this) && msg.sender != address(_wrapper) && msg.sender != owner()) { revert notAuthorized(); } if (msg.sender == owner()) { // cannot be run if random result was not already requested and received if (_closedAtTimestamp == 0 || _randomResult == ROLL_IN_PROGRESS || _randomResult == 0) { revert vrfCallbackNotComplete(); } // when owner is the caller, ignore the values they passed and get the correct ones // this prevents exploitation by owner to assign winner to whomever they want // if owner can successfully call this function, we have already received a random number and set the random winner index randomResult = _randomResult; currentEntryIndex = _getCurrentEntryIndex(data_); unchecked { --currentEntryIndex; // last entry index assigned is one less than current value of currentEntryIndex } } // run the actual winner selection and payout logic _sendToWinner(randomResult, currentEntryIndex); } function setUserExempt(address userAddress, bool exemptfee, bool exemptlimit) external onlyOwner { // cannot alter significant contracts externally if (userAddress == _pair || userAddress == address(ROUTER) || userAddress == address(this)) { revert notAuthorized(); } _setUserExempt(userAddress, exemptfee, exemptlimit); } function updateMax(uint256 maxTx, uint256 maxBalance) external onlyOwner { MAX memory currentMax = _getMaxData(data_); CHECKS memory currentChecks = _getChecksData(data_); if (currentChecks.changeblock != 0) { // neither value can be reduced if (maxTx < currentMax.maxtx || maxBalance < currentMax.maxbal) { revert valueTooLow(); } } _setMaxData(maxTx, maxBalance); emit MaxUpdated(maxTx, maxBalance); } function updateFees(uint256 buy, uint256 sell, uint256 liq) external onlyOwner { if (((buy + liq) > 10) || ((sell + liq) > 10)) { revert valueTooHigh(); } _setFeesData(buy, sell, liq); emit FeesUpdated(buy, sell, liq); } function reduceLimitBlock(uint256 newBlock) external onlyOwner { // once this block has passed, max tx, max balance, and buy cooldown are ignored CHECKS memory checks = _getChecksData(data_); uint256 oldBlock = checks.limitsblock; if (newBlock > oldBlock) { revert valueTooHigh(); } _setChecksData( checks.changeblock, newBlock, checks.standardmode, checks.feesenabled, checks.cooldown, checks.eoatransfers ); emit LimitBlockReduced(newBlock); } function reduceCooldown(uint256 newCooldown) external onlyOwner { // the number of blocks that must pass before user can perform another tx CHECKS memory checks = _getChecksData(data_); uint256 oldCooldown = checks.cooldown; if (newCooldown > oldCooldown) { revert valueTooHigh(); } _setChecksData( checks.changeblock, checks.limitsblock, checks.standardmode, checks.feesenabled, newCooldown, checks.eoatransfers ); emit CooldownReduced(newCooldown); } function toggleStandardMode() external onlyOwner { // standard mode eliminates all custom transfer logic CHECKS memory checks = _getChecksData(data_); uint256 standardmode = checks.standardmode != 0 ? 0 : uint256(1); require(standardmode != uint256(checks.standardmode), "same value"); _setChecksData( checks.changeblock, checks.limitsblock, standardmode, checks.feesenabled, checks.cooldown, checks.eoatransfers ); if (standardmode != 0) { emit StandardModeToggled(true); } else { emit StandardModeToggled(false); } } function toggleFees() external onlyOwner { CHECKS memory checks = _getChecksData(data_); uint256 feesenabled = checks.feesenabled != 0 ? 0 : uint256(1); require(feesenabled != uint256(checks.feesenabled), "same value"); _setChecksData( checks.changeblock, checks.limitsblock, checks.standardmode, feesenabled, checks.cooldown, checks.eoatransfers ); if (feesenabled != 0) { emit FeesToggled(true); } else { emit FeesToggled(false); } } function toggleEOATransfers() external onlyOwner { // enable or disable transferring tokens between user-owned wallets // NOTE: this has no effect on buying or selling CHECKS memory checks = _getChecksData(data_); uint256 eoatransfers = checks.eoatransfers != 0 ? 0 : uint256(1); require(eoatransfers != uint256(checks.eoatransfers), "same value"); _setChecksData( checks.changeblock, checks.limitsblock, checks.standardmode, checks.feesenabled, checks.cooldown, eoatransfers ); if (eoatransfers != 0) { emit EOATransfersToggled(true); } else { emit EOATransfersToggled(false); } } function manualDistribute(address recipient, uint256 amount) external onlyOwner { if (recipient == address(0)) { revert sendToZero(); } bool sent; // send entire ETH balance if (amount == 0) { (sent,) = recipient.call{value: address(this).balance}(""); if (!sent) { revert failedToSendETH(); } } require(_pair != recipient, "Use addToPair instead."); uint256 amountInFinney = amount * 1e15; (sent,) = recipient.call{value: (amountInFinney)}(""); // sending 1 ETH = '1000', .1 ETH = '100', .01 ETH = '10' if (!sent) { revert failedToSendETH(); } } function addToPair(uint256 amount) external onlyOwner { if (_pair == address(0)) { revert notOpen(); } uint256 amountInFinney = amount * 1e15; IWETH(WETH).deposit{value: amountInFinney}(); // sending 1 ETH = '1000', .1 ETH = '100', .01 ETH = '10' bool sent = IWETH(WETH).transfer(_pair, IWETH(WETH).balanceOf(address(this))); if (!sent) { revert failedToSendETH(); } IUniswapV2Pair(_pair).sync(); emit LiqBoosted(WETH, amountInFinney); } /** * @dev * This value is used by Chainlink to determine how much gas the callback function is allowed to consume. * it has no effect on users or swaps. */ function updateLinkFee(uint256 newValue) external onlyOwner { // this function is only needed in case the dev needs to increase the gas cost of the callback function if (newValue < _linkFee) { revert valueTooLow(); } _linkFee = uint32(newValue); emit LinkFeeUpdated(newValue); } function recoverLink() external onlyOwner { // can only reclaim unused LINK after winner has received payout require(_winner != address(0)); LINK.transfer(owner(), LINK.balanceOf(address(this))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../interfaces/LinkTokenInterface.sol"; import "../interfaces/VRFV2WrapperInterface.sol"; /** ******************************************************************************* * @notice Interface for contracts using VRF randomness through the VRF V2 wrapper * ******************************************************************************** * @dev PURPOSE * * @dev Create VRF V2 requests without the need for subscription management. Rather than creating * @dev and funding a VRF V2 subscription, a user can use this wrapper to create one off requests, * @dev paying up front rather than at fulfillment. * * @dev Since the price is determined using the gas price of the request transaction rather than * @dev the fulfillment transaction, the wrapper charges an additional premium on callback gas * @dev usage, in addition to some extra overhead costs associated with the VRFV2Wrapper contract. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFV2WrapperConsumerBase. The consumer must be funded * @dev with enough LINK to make the request, otherwise requests will revert. To request randomness, * @dev call the 'requestRandomness' function with the desired VRF parameters. This function handles * @dev paying for the request based on the current pricing. * * @dev Consumers must implement the fullfillRandomWords function, which will be called during * @dev fulfillment with the randomness result. */ abstract contract VRFV2WrapperConsumerBase { LinkTokenInterface internal immutable LINK; VRFV2WrapperInterface internal immutable VRF_V2_WRAPPER; /** * @param _link is the address of LinkToken * @param _vrfV2Wrapper is the address of the VRFV2Wrapper contract */ constructor(address _link, address _vrfV2Wrapper) { LINK = LinkTokenInterface(_link); VRF_V2_WRAPPER = VRFV2WrapperInterface(_vrfV2Wrapper); } /** * @dev Requests randomness from the VRF V2 wrapper. * * @param _callbackGasLimit is the gas limit that should be used when calling the consumer's * fulfillRandomWords function. * @param _requestConfirmations is the number of confirmations to wait before fulfilling the * request. A higher number of confirmations increases security by reducing the likelihood * that a chain re-org changes a published randomness outcome. * @param _numWords is the number of random words to request. * * @return requestId is the VRF V2 request ID of the newly created randomness request. */ function requestRandomness( uint32 _callbackGasLimit, uint16 _requestConfirmations, uint32 _numWords ) internal returns (uint256 requestId) { LINK.transferAndCall( address(VRF_V2_WRAPPER), VRF_V2_WRAPPER.calculateRequestPrice(_callbackGasLimit), abi.encode(_callbackGasLimit, _requestConfirmations, _numWords) ); return VRF_V2_WRAPPER.lastRequestId(); } /** * @notice fulfillRandomWords handles the VRF V2 wrapper response. The consuming contract must * @notice implement it. * * @param _requestId is the VRF V2 request ID. * @param _randomWords is the randomness result. */ function fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal virtual; function rawFulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) external { require(msg.sender == address(VRF_V2_WRAPPER), "only VRF V2 wrapper can fulfill"); fulfillRandomWords(_requestId, _randomWords); } }
pragma solidity >=0.5.0; 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; }
pragma solidity >=0.6.2; import './IUniswapV2Router01.sol'; 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; }
pragma solidity >=0.5.0; 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; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.0; import "./IERC20.sol"; import "./extensions/IERC20Metadata.sol"; import "../../utils/Context.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC20 * applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20, IERC20Metadata { mapping(address => uint256) private _balances; mapping(address => mapping(address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * All two of these values are immutable: they can only be set once during * construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual override returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address to, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _transfer(owner, to, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { address owner = _msgSender(); _approve(owner, spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. * - the caller must have allowance for ``from``'s tokens of at least * `amount`. */ function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, amount); _transfer(from, to, amount); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, allowance(owner, spender) + addedValue); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { address owner = _msgSender(); uint256 currentAllowance = allowance(owner, spender); require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); unchecked { _approve(owner, spender, currentAllowance - subtractedValue); } return true; } /** * @dev Moves `amount` of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `from` must have a balance of at least `amount`. */ function _transfer(address from, address to, uint256 amount) internal virtual { require(from != address(0), "ERC20: transfer from the zero address"); require(to != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(from, to, amount); uint256 fromBalance = _balances[from]; require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); unchecked { _balances[from] = fromBalance - amount; // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by // decrementing then incrementing. _balances[to] += amount; } emit Transfer(from, to, amount); _afterTokenTransfer(from, to, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply += amount; unchecked { // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above. _balances[account] += amount; } emit Transfer(address(0), account, amount); _afterTokenTransfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements: * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); uint256 accountBalance = _balances[account]; require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); unchecked { _balances[account] = accountBalance - amount; // Overflow not possible: amount <= accountBalance <= totalSupply. _totalSupply -= amount; } emit Transfer(account, address(0), amount); _afterTokenTransfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Updates `owner` s allowance for `spender` based on spent `amount`. * * Does not update the allowance amount in case of infinite allowance. * Revert if not enough allowance is available. * * Might emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 amount) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance != type(uint256).max) { require(currentAllowance >= amount, "ERC20: insufficient allowance"); unchecked { _approve(owner, spender, currentAllowance - amount); } } } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * has been transferred to `to`. * - when `from` is zero, `amount` tokens have been minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens have been burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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 pragma solidity ^0.8.0; interface LinkTokenInterface { function allowance(address owner, address spender) external view returns (uint256 remaining); function approve(address spender, uint256 value) external returns (bool success); function balanceOf(address owner) external view returns (uint256 balance); function decimals() external view returns (uint8 decimalPlaces); function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); function increaseApproval(address spender, uint256 subtractedValue) external; function name() external view returns (string memory tokenName); function symbol() external view returns (string memory tokenSymbol); function totalSupply() external view returns (uint256 totalTokensIssued); function transfer(address to, uint256 value) external returns (bool success); function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); function transferFrom(address from, address to, uint256 value) external returns (bool success); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface VRFV2WrapperInterface { /** * @return the request ID of the most recent VRF V2 request made by this wrapper. This should only * be relied option within the same transaction that the request was made. */ function lastRequestId() external view returns (uint256); /** * @notice Calculates the price of a VRF request with the given callbackGasLimit at the current * @notice block. * * @dev This function relies on the transaction gas price which is not automatically set during * @dev simulation. To estimate the price at a specific gas price, use the estimatePrice function. * * @param _callbackGasLimit is the gas limit used to estimate the price. */ function calculateRequestPrice(uint32 _callbackGasLimit) external view returns (uint256); /** * @notice Estimates the price of a VRF request with a specific gas limit and gas price. * * @dev This is a convenience function that can be called in simulation to better understand * @dev pricing. * * @param _callbackGasLimit is the gas limit used to estimate the price. * @param _requestGasPriceWei is the gas price in wei used for the estimation. */ function estimateRequestPrice(uint32 _callbackGasLimit, uint256 _requestGasPriceWei) external view returns (uint256); }
pragma solidity >=0.6.2; 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// 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); }
{ "remappings": [ "@chainlink/=lib/chainlink/contracts/src/", "@openzeppelin/=lib/openzeppelin-contracts/", "@permit2/=lib/permit2/src/", "@solmate/=lib/solmate/src/", "@uniswap-core-local/=lib/v2-core/local-contracts/", "@uniswap-core/=lib/v2-core/contracts/", "@uniswap-lib-local/=lib/solidity-lib/local-contracts/", "@uniswap-periphery-local/=lib/v2-periphery/local-contracts/", "@uniswap-periphery/=lib/v2-periphery/contracts/", "chainlink/=lib/chainlink/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "permit2/=lib/permit2/", "solidity-lib/=lib/solidity-lib/", "solmate/=lib/solmate/src/", "sstore2/=lib/sstore2/contracts/", "v2-core/=lib/v2-core/", "v2-periphery/=lib/v2-periphery/", "lib/forge-std:ds-test/=lib/forge-std/lib/ds-test/src/", "lib/openzeppelin-contracts:ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "lib/openzeppelin-contracts:erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "lib/openzeppelin-contracts:forge-std/=lib/openzeppelin-contracts/lib/forge-std/src/", "lib/openzeppelin-contracts:openzeppelin/=lib/openzeppelin-contracts/contracts/", "lib/permit2:ds-test/=lib/permit2/lib/forge-std/lib/ds-test/src/", "lib/permit2:forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/", "lib/permit2:forge-std/=lib/permit2/lib/forge-std/src/", "lib/permit2:openzeppelin-contracts/=lib/permit2/lib/openzeppelin-contracts/", "lib/permit2:solmate/=lib/permit2/lib/solmate/", "lib/solmate:ds-test/=lib/solmate/lib/ds-test/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "shanghai", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"router_","type":"address"},{"internalType":"address","name":"linkAddress","type":"address"},{"internalType":"address","name":"wrapperAddress","type":"address"}],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"alreadyOpen","type":"error"},{"inputs":[],"name":"belowMinBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"bytecount","type":"uint256"}],"name":"castOverflow","type":"error"},{"inputs":[],"name":"closeConditionsUnmet","type":"error"},{"inputs":[],"name":"exceedMaxBalance","type":"error"},{"inputs":[],"name":"exceedMaxTx","type":"error"},{"inputs":[],"name":"failedToSendETH","type":"error"},{"inputs":[],"name":"noEOAtoEOATransfers","type":"error"},{"inputs":[],"name":"notAuthorized","type":"error"},{"inputs":[],"name":"notOpen","type":"error"},{"inputs":[],"name":"sendToZero","type":"error"},{"inputs":[],"name":"txCooldown","type":"error"},{"inputs":[],"name":"valueTooHigh","type":"error"},{"inputs":[],"name":"valueTooLow","type":"error"},{"inputs":[],"name":"vrfCallbackNotComplete","type":"error"},{"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":false,"internalType":"uint256","name":"newcooldown","type":"uint256"}],"name":"CooldownReduced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"result","type":"uint256"}],"name":"DiceLanded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"DiceRolled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"eoatransfers","type":"bool"}],"name":"EOATransfersToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EntriesGained","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EntriesLost","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"feesenabled","type":"bool"}],"name":"FeesToggled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"buy","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sell","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"liq","type":"uint256"}],"name":"FeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newblock","type":"uint256"}],"name":"LimitBlockReduced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newfee","type":"uint256"}],"name":"LinkFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LiqBoosted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxtx","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxbal","type":"uint256"}],"name":"MaxUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_holder","type":"address"}],"name":"SentToWinner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"standardmode","type":"bool"}],"name":"StandardModeToggled","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":[],"name":"ROUTER","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_closeLimitBlock","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_closedAtTimestamp","outputs":[{"internalType":"uint48","name":"","type":"uint48"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_linkFee","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_pureRandomNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_randomResult","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_winner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addToPair","outputs":[],"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":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"closeTradingAndRollDice","outputs":[{"internalType":"uint256","name":"requestId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint48","name":"duration","type":"uint48"}],"name":"deploy","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getAllData","outputs":[{"components":[{"internalType":"uint256","name":"changeblock","type":"uint256"},{"internalType":"uint256","name":"limitsblock","type":"uint256"},{"internalType":"uint256","name":"standardmode","type":"uint256"},{"internalType":"uint256","name":"feesenabled","type":"uint256"},{"internalType":"uint256","name":"cooldown","type":"uint256"},{"internalType":"uint256","name":"eoatransfers","type":"uint256"}],"internalType":"struct IGMI.CHECKS","name":"checks","type":"tuple"},{"components":[{"internalType":"uint256","name":"feebuy","type":"uint256"},{"internalType":"uint256","name":"feesell","type":"uint256"},{"internalType":"uint256","name":"feeliq","type":"uint256"}],"internalType":"struct IGMI.FEES","name":"fees","type":"tuple"},{"components":[{"internalType":"uint256","name":"maxtx","type":"uint256"},{"internalType":"uint256","name":"maxbal","type":"uint256"}],"internalType":"struct IGMI.MAX","name":"max","type":"tuple"},{"internalType":"uint256","name":"currentUserIndex","type":"uint256"},{"internalType":"uint256","name":"currentEntryIndex","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getAllUserEntries","outputs":[{"internalType":"uint24[]","name":"","type":"uint24[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getEntrantIdAndAddressAtIndex","outputs":[{"internalType":"uint24","name":"","type":"uint24"},{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getEntryMinimums","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getIndexUser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserData","outputs":[{"components":[{"internalType":"uint256","name":"buy","type":"uint256"},{"internalType":"uint256","name":"exemptfee","type":"uint256"},{"internalType":"uint256","name":"exemptlimit","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"}],"internalType":"struct IGMI.USER","name":"user_","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"getUserEntryCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"manualDistribute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_requestId","type":"uint256"},{"internalType":"uint256[]","name":"_randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"recoverLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newCooldown","type":"uint256"}],"name":"reduceCooldown","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newBlock","type":"uint256"}],"name":"reduceLimitBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"randomResult","type":"uint256"},{"internalType":"uint256","name":"currentEntryIndex","type":"uint256"}],"name":"sendToWinner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"},{"internalType":"bool","name":"exemptfee","type":"bool"},{"internalType":"bool","name":"exemptlimit","type":"bool"}],"name":"setUserExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleEOATransfers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"toggleStandardMode","outputs":[],"stateMutability":"nonpayable","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":"amount","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":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"buy","type":"uint256"},{"internalType":"uint256","name":"sell","type":"uint256"},{"internalType":"uint256","name":"liq","type":"uint256"}],"name":"updateFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"updateLinkFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"maxTx","type":"uint256"},{"internalType":"uint256","name":"maxBalance","type":"uint256"}],"name":"updateMax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
61010060405260405162004d0538038062004d0583398101604081905262000027916200037c565b81816040518060400160405280600481526020016349474d4960e01b8152506040518060400160405280600481526020016349474d4960e01b815250816003908162000074919062000462565b50600462000083828262000462565b505050620000a06200009a620001a660201b60201c565b620001aa565b6001600160a01b03918216608052811660a052600e80546001600160a01b031916918316919091179055620000da305f60018082620001fb565b620000ea335f60018082620001fb565b6200010c3062000106670de0b6b3a7640000620f42406200053e565b62000266565b6001600160a01b03831660e0819052604080516315ab88c960e31b8152905163ad5c4648916004808201926020929091908290030181865afa15801562000155573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200017b91906200055e565b6001600160a01b031660c0525050600780546001600160e01b0316613d0960e61b1790555062000597565b3390565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b620002088460206200032c565b83620002168460086200032c565b602084901b17620002298360086200032c565b602883901b176200023c8260186200032c565b6001600160a01b039095165f90815260096020526040902060309190911b94909417909355505050565b6001600160a01b038216620002c25760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064015b60405180910390fd5b8060025f828254620002d5919062000581565b90915550506001600160a01b0382165f81815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35b5050565b6001811b82106200032857604051638f44d83160e01b81526004810183905260248101829052604401620002b9565b505050565b80516001600160a01b038116811462000377575f80fd5b919050565b5f805f606084860312156200038f575f80fd5b6200039a8462000360565b9250620003aa6020850162000360565b9150620003ba6040850162000360565b90509250925092565b634e487b7160e01b5f52604160045260245ffd5b600181811c90821680620003ec57607f821691505b6020821081036200040b57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156200035b575f81815260208120601f850160051c81016020861015620004395750805b601f850160051c820191505b818110156200045a5782815560010162000445565b505050505050565b81516001600160401b038111156200047e576200047e620003c3565b62000496816200048f8454620003d7565b8462000411565b602080601f831160018114620004cc575f8415620004b45750858301515b5f19600386901b1c1916600185901b1785556200045a565b5f85815260208120601f198616915b82811015620004fc57888601518255948401946001909101908401620004db565b50858210156200051a57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52601160045260245ffd5b80820281158282048414176200055857620005586200052a565b92915050565b5f602082840312156200056f575f80fd5b6200057a8262000360565b9392505050565b808201808211156200055857620005586200052a565b60805160a05160c05160e0516146c3620006425f395f8181610477015281816111710152818161119901528181611249015281816116ec01528181611f4801528181612add01528181612b7b01526131a401525f818161078c0152818161098e01528181610a1c01528181610b8f015281816112de015261314d01525f8181610dea0152818161326e015261337201525f818161183e01528181611892015261324401526146c35ff3fe608060405260043610610278575f3560e01c80638d5fcacb1161014a578063cae5f11e116100be578063e461a55e11610078578063e461a55e14610858578063e8891de814610884578063e9cc4edd146108a3578063ef4d5efa146108c2578063f2fde38b146108d6578063ffc9896b146108f5575f80fd5b8063cae5f11e1461077e578063d346b577146107b0578063d7e1a3d9146107ec578063dd62ed3e14610811578063ddf5451214610830578063de9ca28d14610844575f80fd5b8063b2a8116a1161010f578063b2a8116a146106c3578063b4664394146106e2578063beba2126146106f6578063c09d28561461070b578063c1f1b1b514610742578063c1f3c33f1461075f575f80fd5b80638d5fcacb146106125780638da5cb5b1461065457806395d89b4114610671578063a457c2d714610685578063a9059cbb146106a4575f80fd5b806332fe7b26116101ec5780635fd2f823116101a65780635fd2f8231461056e57806367a2b56a1461058257806370a08231146105a1578063715018a6146105c057806377841d59146105d457806382374c13146105f3575f80fd5b806332fe7b261461046657806339509351146104b15780633c3b2a73146104d0578063556d9228146104ef57806355a34e6f146105235780635ac1c61e14610536575f80fd5b80631fe543e31161023d5780631fe543e31461033c578063224290851461035b57806323b872dd1461037a57806325dee0c4146103995780632d10fa28146103b8578063313ce5671461044b575f80fd5b8063051515541461028357806306fdde03146102a4578063095ea7b3146102ce578063128047b5146102fd57806318160ddd1461031e575f80fd5b3661027f57005b5f80fd5b34801561028e575f80fd5b506102a261029d366004613fba565b610947565b005b3480156102af575f80fd5b506102b8610bec565b6040516102c5919061401e565b60405180910390f35b3480156102d9575f80fd5b506102ed6102e8366004614044565b610c7c565b60405190151581526020016102c5565b348015610308575f80fd5b50610311610c95565b6040516102c5919061406e565b348015610329575f80fd5b506002545b6040519081526020016102c5565b348015610347575f80fd5b506102a26103563660046140c5565b610ddf565b348015610366575f80fd5b506102a261037536600461418a565b610e6a565b348015610385575f80fd5b506102ed6103943660046141b3565b610efa565b3480156103a4575f80fd5b506102a26103b3366004613fba565b610f1f565b3480156103c3575f80fd5b506103cc610faa565b6040805186518152602080880151818301528783015182840152606080890151908301526080808901519083015260a09788015197820197909752855160c08201528686015160e0820152940151610100850152825161012085015293909101516101408301526101608201526101808101919091526101a0016102c5565b348015610456575f80fd5b50604051601281526020016102c5565b348015610471575f80fd5b506104997f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102c5565b3480156104bc575f80fd5b506102ed6104cb366004614044565b611004565b3480156104db575f80fd5b506102a26104ea3660046141f1565b611025565b3480156104fa575f80fd5b50610499610509366004613fba565b5f908152600c60205260409020546001600160a01b031690565b6102a2610531366004614211565b61110f565b348015610541575f80fd5b5060075461055990600160e01b900463ffffffff1681565b60405163ffffffff90911681526020016102c5565b348015610579575f80fd5b506102a261143d565b34801561058d575f80fd5b506102a261059c366004614044565b61151d565b3480156105ac575f80fd5b5061032e6105bb366004614236565b61169e565b3480156105cb575f80fd5b506102a26116b8565b3480156105df575f80fd5b506102a26105ee36600461425e565b6116cb565b3480156105fe575f80fd5b50600f54610499906001600160a01b031681565b34801561061d575f80fd5b5061063161062c366004613fba565b611761565b6040805162ffffff90931683526001600160a01b039091166020830152016102c5565b34801561065f575f80fd5b506005546001600160a01b0316610499565b34801561067c575f80fd5b506102b8611775565b348015610690575f80fd5b506102ed61069f366004614044565b611784565b3480156106af575f80fd5b506102ed6106be366004614044565b611809565b3480156106ce575f80fd5b5061032e6106dd366004614236565b611816565b3480156106ed575f80fd5b506102a2611820565b348015610701575f80fd5b5061032e60085481565b348015610716575f80fd5b5060075461072a906001600160801b031681565b6040516001600160801b0390911681526020016102c5565b34801561074d575f80fd5b50600d546001600160a01b0316610499565b34801561076a575f80fd5b506102a2610779366004613fba565b611972565b348015610789575f80fd5b507f0000000000000000000000000000000000000000000000000000000000000000610499565b3480156107bb575f80fd5b506007546107d590600160b01b900465ffffffffffff1681565b60405165ffffffffffff90911681526020016102c5565b3480156107f7575f80fd5b506007546107d590600160801b900465ffffffffffff1681565b34801561081c575f80fd5b5061032e61082b3660046142a6565b611a00565b34801561083b575f80fd5b506102a2611a2a565b34801561084f575f80fd5b506102a2611b02565b348015610863575f80fd5b50610877610872366004614236565b611bda565b6040516102c591906142dd565b34801561088f575f80fd5b506102a261089e366004613fba565b611c6c565b3480156108ae575f80fd5b506102a26108bd3660046141f1565b611cfa565b3480156108cd575f80fd5b5061032e611db9565b3480156108e1575f80fd5b506102a26108f0366004614236565b611fd7565b348015610900575f80fd5b5061091461090f366004614236565b61204d565b6040516102c591908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b61094f612095565b600d546001600160a01b0316610978576040516305835fed60e01b815260040160405180910390fd5b5f61098a8266038d7ea4c6800061432d565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156109e5575f80fd5b505af11580156109f7573d5f803e3d5ffd5b5050600d546040516370a0823160e01b81523060048201525f94506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116945063a9059cbb93509091169083906370a08231906024016020604051808303815f875af1158015610a71573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a959190614344565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015610add573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b01919061435b565b905080610b215760405163062e4f6360e11b815260040160405180910390fd5b600d5f9054906101000a90046001600160a01b03166001600160a01b031663fff6cae96040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610b6d575f80fd5b505af1158015610b7f573d5f803e3d5ffd5b5050604080516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152602081018690527f5c0eec4199f95cf196fdac30f5458f67ba720232c0fce87b1540c0c7dc0e773f93500190505b60405180910390a1505050565b606060038054610bfb90614376565b80601f0160208091040260200160405190810160405280929190818152602001828054610c2790614376565b8015610c725780601f10610c4957610100808354040283529160200191610c72565b820191905f5260205f20905b815481529060010190602001808311610c5557829003601f168201915b5050505050905090565b5f33610c898185856120ef565b60019150505b92915050565b60408051600780825261010082019092526060915f91906020820160e080368337019050509050681b1ae4d6e2ef500000815f81518110610cd857610cd86143ae565b602002602001018181525050683635c9adc5dea0000081600181518110610d0157610d016143ae565b602002602001018181525050685150ae84a8cdf0000081600281518110610d2a57610d2a6143ae565b602002602001018181525050686c6b935b8bbd40000081600381518110610d5357610d536143ae565b60200260200101818152505068878678326eac90000081600481518110610d7c57610d7c6143ae565b60200260200101818152505068bdbc41e0348b30000081600581518110610da557610da56143ae565b60200260200101818152505069010f0cf064dd5920000081600681518110610dcf57610dcf6143ae565b6020908102919091010152919050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e5c5760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792056524620563220777261707065722063616e2066756c66696c6c0060448201526064015b60405180910390fd5b610e668282612212565b5050565b610e72612095565b600a610e7e82856143c2565b1180610e935750600a610e9182846143c2565b115b15610eb157604051633634941560e21b815260040160405180910390fd5b610ebc838383612341565b60408051848152602081018490529081018290527fcf8a1e1d5f09cf3c97dbb653cd9a4d7aace9292fbc1bb8211febf2d400febbdd90606001610bdf565b5f33610f0785828561238e565b610f12858585612400565b60019150505b9392505050565b610f27612095565b600754600160e01b900463ffffffff16811015610f5757604051631c23763d60e01b815260040160405180910390fd5b600780546001600160e01b0316600160e01b63ffffffff8416021790556040518181527f0f7a60a7e1cf3f1b0b1540f0e964947327ad8b2bde2e2ac3e07d922b69e977d99060200160405180910390a150565b610fb2613f8a565b610fd360405180606001604052805f81526020015f81526020015f81525090565b604080518082019091525f80825260208201525f80610ff36006546128ee565b945094509450945094509091929394565b5f33610c898185856110168383611a00565b61102091906143c2565b6120ef565b3330148015906110405750600e546001600160a01b03163314155b801561105757506005546001600160a01b03163314155b1561107557604051636932705760e11b815260040160405180910390fd5b6005546001600160a01b0316330361110557600754600160b01b900465ffffffffffff1615806110b257506007546001600160801b03166298967f145b806110c657506007546001600160801b0316155b156110e4576040516351bf115f60e01b815260040160405180910390fd5b6007546006546001600160801b03909116925060b81c62ffffff165f190190505b610e6682826129c5565b611117612095565b600d546001600160a01b03161561114157604051630cac471160e41b815260040160405180910390fd5b61012c8165ffffffffffff161161116b57604051631c23763d60e01b815260040160405180910390fd5b611197307f00000000000000000000000000000000000000000000000000000000000000005f196120ef565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f305d719473060016111d33061169e565b6111dd91906143d5565b5f8030426040518863ffffffff1660e01b8152600401611202969594939291906143e8565b60606040518083038185885af115801561121e573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906112439190614423565b5050505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112c7919061444e565b60405163e6a4390560e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301523060248301529192505f9183169063e6a4390590604401602060405180830381865afa158015611336573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135a919061444e565b905061136a815f60015f80612d2d565b600d80546001600160a01b0319166001600160a01b03831617905561139765ffffffffffff8416436143c2565b600760106101000a81548165ffffffffffff021916908365ffffffffffff1602179055505f604051806101a001604052804381526020014360326113db91906143c2565b81526020015f815260200160018152602001600381526020016001815260200160048152602001600481526020016001815260200161177081526020016127108152602001600181526020016001815250905061143781612d90565b50505050565b611445612095565b5f611451600654612e91565b90505f81604001515f03611466576001611468565b5f5b90508160400151810361148d5760405162461bcd60e51b8152600401610e5390614469565b6114ae825f0151836020015183856060015186608001518760a00151612ee5565b80156114ed57604051600181527f0f8293c744b66395bf9a745e7b4d95c3b84f65fd0f4cb60bad74975fa315eb1b906020015b60405180910390a15050565b6040515f81527f0f8293c744b66395bf9a745e7b4d95c3b84f65fd0f4cb60bad74975fa315eb1b906020016114e1565b611525612095565b6001600160a01b03821661154c57604051639ed698f560e01b815260040160405180910390fd5b5f815f036115c3576040516001600160a01b0384169047905f81818185875af1925050503d805f811461159a576040519150601f19603f3d011682016040523d82523d5f602084013e61159f565b606091505b505080915050806115c35760405163062e4f6360e11b815260040160405180910390fd5b600d546001600160a01b038085169116036116195760405162461bcd60e51b81526020600482015260166024820152752ab9b29030b2322a37a830b4b91034b739ba32b0b21760511b6044820152606401610e53565b5f61162b8366038d7ea4c6800061432d565b9050836001600160a01b0316816040515f6040518083038185875af1925050503d805f8114611675576040519150601f19603f3d011682016040523d82523d5f602084013e61167a565b606091505b505080925050816114375760405163062e4f6360e11b815260040160405180910390fd5b6001600160a01b03165f9081526020819052604090205490565b6116c0612095565b6116c95f612f63565b565b6116d3612095565b600d546001600160a01b038481169116148061172057507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316145b8061173357506001600160a01b03831630145b1561175157604051636932705760e11b815260040160405180910390fd5b61175c838383612fb4565b505050565b5f8061176c83613015565b91509150915091565b606060048054610bfb90614376565b5f33816117918286611a00565b9050838110156117f15760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610e53565b6117fe82868684036120ef565b506001949350505050565b5f33610c89818585612400565b5f610c8f82613092565b611828612095565b600f546001600160a01b031661183c575f80fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb61187d6005546001600160a01b031690565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156118df573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119039190614344565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af115801561194b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196f919061435b565b50565b61197a612095565b5f611986600654612e91565b6020810151909150808311156119af57604051633634941560e21b815260040160405180910390fd5b6119d0825f0151848460400151856060015186608001518760a00151612ee5565b6040518381527fb32eee1f3b022fecf91130907d354359df3234353a0ee169155ac37dbeed75c090602001610bdf565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b611a32612095565b5f611a3e600654612e91565b90505f81606001515f03611a53576001611a55565b5f5b905081606001518103611a7a5760405162461bcd60e51b8152600401610e5390614469565b611a9b825f0151836020015184604001518486608001518760a00151612ee5565b8015611ad257604051600181527fc97260ffb3df6b903cdfd59e3b5b21a896404903a8e8a83bf60ba3fca365fbe5906020016114e1565b6040515f81527fc97260ffb3df6b903cdfd59e3b5b21a896404903a8e8a83bf60ba3fca365fbe5906020016114e1565b611b0a612095565b5f611b16600654612e91565b90505f8160a001515f03611b2b576001611b2d565b5f5b90508160a001518103611b525760405162461bcd60e51b8152600401610e5390614469565b611b73825f0151836020015184604001518560600151866080015186612ee5565b8015611baa57604051600181527fa8392e314504d0b57633e056d62ab8ededff9020da370c77dd137a25324b5c18906020016114e1565b6040515f81527fa8392e314504d0b57633e056d62ab8ededff9020da370c77dd137a25324b5c18906020016114e1565b6001600160a01b0381165f908152600a602081815260408084205481518481526101608101909252606094909390928201610140803683370190505090505f5b600a811015611c64575f611c2f82601861432d565b90508084901c838381518110611c4757611c476143ae565b62ffffff9092166020928302919091019091015250600101611c1a565b509392505050565b611c74612095565b5f611c80600654612e91565b608081015190915080831115611ca957604051633634941560e21b815260040160405180910390fd5b611cca825f0151836020015184604001518560600151878760a00151612ee5565b6040518381527fb3bf54177f07aa628d24efcbd137a401112718a4d9c8c1a8538b24e21029422990602001610bdf565b611d02612095565b60065460408051808201909152607882901c61ffff16815260889190911c62ffffff1660208201525f611d36600654612e91565b805190915015611d70578151841080611d525750816020015183105b15611d7057604051631c23763d60e01b815260040160405180910390fd5b611d7a84846130bd565b60408051858152602081018590527faa6f6b0a509f2b07cf30d89dbd3bb410883aaa429ad4da41fdf36c02398cf1a0910160405180910390a150505050565b5f611dc2612095565b5f611dce600654612e91565b600654815191925060b81c62ffffff16901580611dfb5750600754600160b01b900465ffffffffffff1615155b80611e165750600754600160801b900465ffffffffffff1643105b80611e215750806001145b15611e3f57604051630cc4134b60e11b815260040160405180910390fd5b5f611e493061169e565b9050681b1ae4d6e2ef500000811115611eae57600d545f90606490611e76906001600160a01b031661169e565b611e8190601461432d565b611e8b91906144a1565b905080821115611e99578091505b611eac611ea76001846143d5565b6130f8565b505b478015611f19575f611ec86005546001600160a01b031690565b6001600160a01b0316476040515f6040518083038185875af1925050503d805f8114611f0f576040519150601f19603f3d011682016040523d82523d5f602084013e611f14565b606091505b505050505b6007805465ffffffffffff60b01b1916600160b01b4265ffffffffffff1602179055611f4361320c565b611f717f00000000000000000000000000000000000000000000000000000000000000005f6001805f612d2d565b600754611f8e90600160e01b900463ffffffff166003600161321f565b600780546001600160801b0319166298967f17905560405190955085907f0c720560a539b13f97fb22b6c1ac4393045cedca3bb997fd2ea1f7a3dfb76a58905f90a25050505090565b611fdf612095565b6001600160a01b0381166120445760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e53565b61196f81612f63565b61207460405180608001604052805f81526020015f81526020015f81526020015f81525090565b6001600160a01b0382165f90815260096020526040902054610c8f906133f8565b6005546001600160a01b031633146116c95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e53565b6001600160a01b0383166121515760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610e53565b6001600160a01b0382166121b25760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610e53565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6006545f9060b81c62ffffff16905080600190039050815f8151811061223a5761223a6143ae565b60200260200101516008819055505f8160085461225791906144b4565b600780546001600160801b0319166001600160801b0383169081179091556040519192509085907f54d97c1f7e5abad75bd421455cd4dd296852a52e1ea721f2cdb66d06fa2082a9905f90a3604080516001600160801b0383166024820152604480820185905282518083039091018152606490910182526020810180516001600160e01b0316633c3b2a7360e01b17905290515f9130916122f991906144c7565b5f604051808303815f865af19150503d805f8114612332576040519150601f19603f3d011682016040523d82523d5f602084013e612337565b606091505b5050505050505050565b5f61235160065460606018613456565b905061235e84600861347f565b606084901b1761236f83600861347f565b606883901b1761238082600861347f565b60709190911b176006555050565b5f6123998484611a00565b90505f19811461143757818110156123f35760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610e53565b61143784848484036120ef565b6006545f61240d82612e91565b6001600160a01b0386165f9081526009602052604081205491925090612432906133f8565b6001600160a01b0386165f9081526009602052604081205491925090612457906133f8565b90506001600160a01b0387163014806124735750604083015115155b8061248f575060208201511580159061248f5750604082015115155b806124ab57506020810151158015906124ab5750604081015115155b156124c0576124bb8787876134ac565b6128e5565b82515f036124e1576040516305835fed60e01b815260040160405180910390fd5b600d5460408051808201909152607886901c61ffff168152608886901c62ffffff1660208201525f916001600160a01b0316905f61251e8861364e565b325f908152600960205260408120549192509061253a906133f8565b90508b6001600160a01b0316846001600160a01b0316036126e35785604001515f036126da5743886020015111156126525787516125799060026143c2565b43101561258b57600a80835260408301525b82516125a090670de0b6b3a76400009061432d565b8a11156125c057604051632d2b153d60e01b815260040160405180910390fd5b670de0b6b3a764000083602001516125d8919061432d565b8a6125e28d61169e565b6125ec91906143c2565b111561260b5760405163cc91297760e01b815260040160405180910390fd5b608088015186514391011180612628575060808801518151439101115b156126465760405163dcafac0960e01b815260040160405180910390fd5b60078252600360408301525b43865260608601511561267b5761267b8b875f0151886020015189604001518a60600151612d2d565b61269d8b878c8c8660018e606001515f03612696575f613697565b6001613697565b326001600160a01b038c16148015906126b95750438860200151115b156126da576126da32875f0151886020015189604001518a60600151612d2d565b600194506127ca565b8a6001600160a01b0316846001600160a01b0316036127ca5760408701511580156127115750608088015115155b1561275157608088015187514391011180612733575060808801518151439101115b156127515760405163dcafac0960e01b815260040160405180910390fd5b61276b8c888c8c865f8e606001515f03612696575f613697565b5f6127753061169e565b9050681b1ae4d6e2ef5000008111156127c8575f60646127948e61169e565b61279f90600561432d565b6127a991906144a1565b90506127c68183116127c057611ea76001846143d5565b816130f8565b505b505b606088015115801590612824575060208601511580156127fb57508b6001600160a01b0316846001600160a01b0316145b806128245750602087015115801561282457508a6001600160a01b0316846001600160a01b0316145b1561283b576128368c8c8c88866139ea565b6128df565b8b6001600160a01b0316846001600160a01b03161415801561286f57508a6001600160a01b0316846001600160a01b031614155b156128d4578760a001515f03612898576040516308090ba360e41b815260040160405180910390fd5b60208601511580156128ab575086518651105b156128b557865186525b6128c48c888c8c865f80613697565b6128d48b878c8c8660015f613697565b6128df8c8c8c6134ac565b50505050505b50505050505050565b6128f6613f8a565b61291760405180606001604052805f81526020015f81526020015f81525090565b60408051808201825263ffffffff8581168552602086811c9091168186015260ff86841c811686850152604887901c8116606080880191909152605088901c82166080880152605888901c821660a0808901919091529088901c82168652606888901c821686840152607088901c9091169385019390935261ffff607887901c16825262ffffff608887901c8116918301919091529395929490939181901c82169260b89190911c90911690565b815f6129d082613015565b9150506001600160a01b038116612aab5782821015612a2b575f6129f483856143d5565b90505f5b81811015612a2857836001019350612a0f84613015565b9350506001600160a01b038316612a28576001016129f8565b50505b6001600160a01b038116158015612a4157508282145b15612a7d578391505f5b84811015612a7b575f1990920191612a6283613015565b9250506001600160a01b038216612a7b57600101612a4b565b505b6001600160a01b038116612a8f575f80fd5b600780546001600160801b0319166001600160801b0384161790555b600f80546001600160a01b0319166001600160a01b0383811691909117909155600d5460405163095ea7b360e01b81527f0000000000000000000000000000000000000000000000000000000000000000831660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af1158015612b32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b56919061435b565b50600d546040516370a0823160e01b815230600482018190525f926001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116936302751cec939291909116906370a0823190602401602060405180830381865afa158015612bcd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bf19190614344565b5f8030426040518763ffffffff1660e01b8152600401612c16969594939291906143e8565b60408051808303815f875af1158015612c31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c5591906144e2565b9150505f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114612ca1576040519150601f19603f3d011682016040523d82523d5f602084013e612ca6565b606091505b5050905080612ce95760405162461bcd60e51b815260206004820152600f60248201526e4661696c656420746f2073656e642160881b6044820152606401610e53565b6040516001600160a01b03841681527f0992f42a6118239e571ca390863e9f148a939f9f0470578217d738d6d665116e9060200160405180910390a1505050505050565b612d3884602061347f565b83612d4484600861347f565b602084901b17612d5583600861347f565b602883901b17612d6682601861347f565b6001600160a01b039095165f90815260096020526040902060309190911b94909417909355505050565b604080516101a0810182526020808252808201526008918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101919091526010610120820152601861014082018190526101608201819052610180820152600d905f9081905f5b84811015612e8757612e428682600d8110612e1e57612e1e6143ae565b60200201518383600d8110612e3557612e356143ae565b602002015160ff1661347f565b838682600d8110612e5557612e556143ae565b6020020151901b831792508181600d8110612e7257612e726143ae565b602002015160ff169390930192600101612e01565b5050600655505050565b612e99613f8a565b63ffffffff8083168252602083811c9091169082015260ff604083811c821690830152604883901c81166060830152605083901c8116608083015260589290921c90911660a082015290565b5f612ef46006545f6060613456565b9050612f0187602061347f565b8617612f0e86602061347f565b602086901b17612f1f85600861347f565b604085901b17612f3084600861347f565b604884901b17612f4183600861347f565b605083901b17612f5282600861347f565b60589190911b176006555050505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0383165f90815260096020526040812054612fd5906133f8565b90505f83612fe3575f612fe6565b60015b90505f83612ff4575f612ff7565b60015b905061300d86845f015184848760600151612d2d565b505050505050565b5f8080613023600a856144a1565b90505f600985116130345784613049565b61303f82600a61432d565b61304990866144b4565b90505f61305782601861432d565b5f938452600b602090815260408086205490921c62ffffff81168652600c90915293205492966001600160a01b039093169550919350505050565b6001600160a01b0381165f908152600a6020526040812054816130b482613af5565b50949350505050565b5f6130cd60065460786028613456565b90506130da83601061347f565b607883901b176130eb82601861347f565b60889190911b1760065550565b6040805160028082526060820183525f9260208301908036833701905050905030815f8151811061312b5761312b6143ae565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160018151811061317f5761317f6143ae565b6001600160a01b03928316602091820292909201015260405163791ac94760e01b81527f00000000000000000000000000000000000000000000000000000000000000009091169063791ac947906131e39085905f90869030904290600401614504565b5f604051808303815f87803b1580156131fa575f80fd5b505af115801561300d573d5f803e3d5ffd5b61321a6006545f6020613456565b600655565b6040516310c1b4d560e21b815263ffffffff841660048201525f906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811691634000aea0917f00000000000000000000000000000000000000000000000000000000000000009190821690634306d35490602401602060405180830381865afa1580156132b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132da9190614344565b6040805163ffffffff808b16602083015261ffff8a169282019290925290871660608201526080016040516020818303038152906040526040518463ffffffff1660e01b815260040161332f93929190614573565b6020604051808303815f875af115801561334b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061336f919061435b565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fc2a88c36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133f09190614344565b949350505050565b61341f60405180608001604052805f81526020015f81526020015f81526020015f81525090565b63ffffffff8216815260ff602083811c821690830152602883901c16604082015262ffffff60309290921c91909116606082015290565b5f80836001613466856002614682565b61347091906143d5565b901b1994909416949350505050565b6001811b8210610e6657604051638f44d83160e01b81526004810183905260248101829052604401610e53565b6001600160a01b0383166135105760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610e53565b6001600160a01b0382166135725760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610e53565b6001600160a01b0383165f90815260208190526040902054818110156135e95760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610e53565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3611437565b61366f60405180606001604052805f81526020015f81526020015f81525090565b60ff606083901c81168252606883901c8116602083015260709290921c909116604082015290565b5f6136a188613092565b90505f83156138fa5782156137aa578451158015906136c35750604085015115155b156137335761372c60648660400151896136dd919061432d565b6136e791906144a1565b86516064906136f6908b61432d565b61370091906144a1565b61370a908a6143d5565b61371491906143d5565b61371d8b61169e565b61372791906143c2565b613b36565b90506137ba565b84511580159061374557506040850151155b1561377157845161372c9060649061375d908a61432d565b61376791906144a1565b61371490896143d5565b84511580156137835750604085015115155b1561379d5761372c606486604001518961375d919061432d565b61372c8761371d8b61169e565b6137b78761371d8b61169e565b90505b6060880151805f8190036138195760a088901c62ffffff1691508190506137ef8b8b5f01518c602001518d6040015186612d2d565b5f828152600c6020526040902080546001600160a01b0319166001600160a01b038d161790556001015b82158061382557508383145b80156138315750808214155b15613849576138408882613bee565b505050506128e5565b838311156138f35762ffffff60b889901c165f6138708d61386a88886143d5565b84613c11565b90505f61387e858385613c96565b9050838514613897576138928b8583613d41565b6138a1565b6138a18b82613d7c565b7fd4a167f62427a87418c8179efb1099f2da50e01c5374433a1e21db418fd9e4458e6138cd89896143d5565b604080516001600160a01b03909316835260208301919091520160405180910390a15050505b50506139df565b866139048a61169e565b10156139115750506128e5565b6139288761391e8b61169e565b61372791906143d5565b9050818110156139df575f61393d82846143d5565b90505f8167ffffffffffffffff811115613959576139596140b1565b604051908082528060200260200182016040528015613982578160200160208202803683370190505b50905061398f8b83613d9f565b905061399a81613e94565b604080516001600160a01b038d168152602081018490527f0c129863ec4f7070868d0ab05157245e6264ef1004096ec9dd7fbbc67d575253910160405180910390a150505b505050505050505050565b5f8083613a005782602001518360400151613a08565b825160408401515b90925090505f6064613a1a848861432d565b613a2491906144a1565b90505f6064613a33848961432d565b613a3d91906144a1565b90505f81613a4b848a6143d5565b613a5591906143d5565b90508615613a6d57613a688a8a836134ac565b613ad8565b8115613acd57613a7e8a8a846134ac565b886001600160a01b031663fff6cae96040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613ab6575f80fd5b505af1158015613ac8573d5f803e3d5ffd5b505050505b613ad88a8a836134ac565b8215613ae957613ae98a30856134ac565b50505050505050505050565b5f805b600a821015613b31575f613b0d83601861432d565b91505082811c62ffffff81165f03613b255750915091565b82600101925050613af8565b915091565b5f681b1ae4d6e2ef500000821015613b4f57505f919050565b683635c9adc5dea00000821015613b6857506001919050565b685150ae84a8cdf00000821015613b8157506002919050565b686c6b935b8bbd400000821015613b9a57506003919050565b68878678326eac900000821015613bb357506004919050565b68bdbc41e0348b300000821015613bcc57506005919050565b69010f0cf064dd59200000821015613be657506007919050565b50600a919050565b613bfb8260a06018613456565b9150613c0881601861347f565b60a01b17600655565b6001600160a01b0383165f908152600a602052604081205481613c3382613af5565b9150508060d803613c48578492505050610f18565b5f5b85811015613c7357600180860195831b93909317920160d88214613c7357601882019150613c4a565b50506001600160a01b0385165f908152600a602052604090205550819392505050565b600a81045f818152600b6020526040812054909190825b85811015613d3657600a85045f60098711613cc85786613cdc565b81600a028781613cda57613cda61448d565b065b9050601881028015613cf557808a901b85179450613cfb565b89811b94505b8160091480613d0c57508884600101145b15613d22575f838152600b602052604090208590555b876001019750836001019350505050613cad565b509295945050505050565b613d4e8360a06030613456565b9250613d5b82601861347f565b60a082901b83179250613d6f81601861347f565b60b81b9190911760065550565b613d898260b86018613456565b9150613d9681601861347f565b60b81b17600655565b60605f613dab84613092565b6001600160a01b0385165f908152600a60205260408120549192508467ffffffffffffffff811115613ddf57613ddf6140b1565b604051908082528060200260200182016040528015613e08578160200160208202803683370190505b5090505f613e1784601861432d565b90505f5b86811015613e5b576018820391508184901c838281518110613e3f57613e3f6143ae565b62ffffff90921660209283029190910190910152600101613e1b565b50613e718382613e6c89601861432d565b613456565b6001600160a01b0388165f908152600a6020526040902055509250505092915050565b80515f80805b83811015613f83575f858281518110613eb557613eb56143ae565b602002602001015162ffffff1690505f600a8281613ed557613ed561448d565b049050825f03613ef0575f818152600b602052604090205493505b8215801590613eff5750808514155b15613f20575f858152600b6020526040808220959095558181529390932054925b5f60098311613f2f5782613f43565b81600a028381613f4157613f4161448d565b065b90505f816018029050613f5886826018613456565b9550878560010103613f75575f838152600b602052604090208690555b509094505050600101613e9a565b5050505050565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f60208284031215613fca575f80fd5b5035919050565b5f5b83811015613feb578181015183820152602001613fd3565b50505f910152565b5f815180845261400a816020860160208601613fd1565b601f01601f19169290920160200192915050565b602081525f610f186020830184613ff3565b6001600160a01b038116811461196f575f80fd5b5f8060408385031215614055575f80fd5b823561406081614030565b946020939093013593505050565b602080825282518282018190525f9190848201906040850190845b818110156140a557835183529284019291840191600101614089565b50909695505050505050565b634e487b7160e01b5f52604160045260245ffd5b5f80604083850312156140d6575f80fd5b8235915060208084013567ffffffffffffffff808211156140f5575f80fd5b818601915086601f830112614108575f80fd5b81358181111561411a5761411a6140b1565b8060051b604051601f19603f8301168101818110858211171561413f5761413f6140b1565b60405291825284820192508381018501918983111561415c575f80fd5b938501935b8285101561417a57843584529385019392850192614161565b8096505050505050509250929050565b5f805f6060848603121561419c575f80fd5b505081359360208301359350604090920135919050565b5f805f606084860312156141c5575f80fd5b83356141d081614030565b925060208401356141e081614030565b929592945050506040919091013590565b5f8060408385031215614202575f80fd5b50508035926020909101359150565b5f60208284031215614221575f80fd5b813565ffffffffffff81168114610f18575f80fd5b5f60208284031215614246575f80fd5b8135610f1881614030565b801515811461196f575f80fd5b5f805f60608486031215614270575f80fd5b833561427b81614030565b9250602084013561428b81614251565b9150604084013561429b81614251565b809150509250925092565b5f80604083850312156142b7575f80fd5b82356142c281614030565b915060208301356142d281614030565b809150509250929050565b602080825282518282018190525f9190848201906040850190845b818110156140a557835162ffffff16835292840192918401916001016142f8565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610c8f57610c8f614319565b5f60208284031215614354575f80fd5b5051919050565b5f6020828403121561436b575f80fd5b8151610f1881614251565b600181811c9082168061438a57607f821691505b6020821081036143a857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b80820180821115610c8f57610c8f614319565b81810381811115610c8f57610c8f614319565b6001600160a01b039687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b5f805f60608486031215614435575f80fd5b8351925060208401519150604084015190509250925092565b5f6020828403121561445e575f80fd5b8151610f1881614030565b6020808252600a908201526973616d652076616c756560b01b604082015260600190565b634e487b7160e01b5f52601260045260245ffd5b5f826144af576144af61448d565b500490565b5f826144c2576144c261448d565b500690565b5f82516144d8818460208701613fd1565b9190910192915050565b5f80604083850312156144f3575f80fd5b505080516020909101519092909150565b5f60a082018783526020878185015260a0604085015281875180845260c08601915082890193505f5b818110156145525784516001600160a01b03168352938301939183019160010161452d565b50506001600160a01b03969096166060850152505050608001529392505050565b60018060a01b0384168152826020820152606060408201525f6145996060830184613ff3565b95945050505050565b600181815b808511156145dc57815f19048211156145c2576145c2614319565b808516156145cf57918102915b93841c93908002906145a7565b509250929050565b5f826145f257506001610c8f565b816145fe57505f610c8f565b8160018114614614576002811461461e5761463a565b6001915050610c8f565b60ff84111561462f5761462f614319565b50506001821b610c8f565b5060208310610133831016604e8410600b841016171561465d575081810a610c8f565b61466783836145a2565b805f190482111561467a5761467a614319565b029392505050565b5f610f1883836145e456fea264697066735822122071da3b7386b293fee1e1929e49f67a4cef2c5b4570c355088fbfdf8ff32e2d0f64736f6c634300081500330000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca0000000000000000000000005a861794b927983406fce1d062e00b9368d97df6
Deployed Bytecode
0x608060405260043610610278575f3560e01c80638d5fcacb1161014a578063cae5f11e116100be578063e461a55e11610078578063e461a55e14610858578063e8891de814610884578063e9cc4edd146108a3578063ef4d5efa146108c2578063f2fde38b146108d6578063ffc9896b146108f5575f80fd5b8063cae5f11e1461077e578063d346b577146107b0578063d7e1a3d9146107ec578063dd62ed3e14610811578063ddf5451214610830578063de9ca28d14610844575f80fd5b8063b2a8116a1161010f578063b2a8116a146106c3578063b4664394146106e2578063beba2126146106f6578063c09d28561461070b578063c1f1b1b514610742578063c1f3c33f1461075f575f80fd5b80638d5fcacb146106125780638da5cb5b1461065457806395d89b4114610671578063a457c2d714610685578063a9059cbb146106a4575f80fd5b806332fe7b26116101ec5780635fd2f823116101a65780635fd2f8231461056e57806367a2b56a1461058257806370a08231146105a1578063715018a6146105c057806377841d59146105d457806382374c13146105f3575f80fd5b806332fe7b261461046657806339509351146104b15780633c3b2a73146104d0578063556d9228146104ef57806355a34e6f146105235780635ac1c61e14610536575f80fd5b80631fe543e31161023d5780631fe543e31461033c578063224290851461035b57806323b872dd1461037a57806325dee0c4146103995780632d10fa28146103b8578063313ce5671461044b575f80fd5b8063051515541461028357806306fdde03146102a4578063095ea7b3146102ce578063128047b5146102fd57806318160ddd1461031e575f80fd5b3661027f57005b5f80fd5b34801561028e575f80fd5b506102a261029d366004613fba565b610947565b005b3480156102af575f80fd5b506102b8610bec565b6040516102c5919061401e565b60405180910390f35b3480156102d9575f80fd5b506102ed6102e8366004614044565b610c7c565b60405190151581526020016102c5565b348015610308575f80fd5b50610311610c95565b6040516102c5919061406e565b348015610329575f80fd5b506002545b6040519081526020016102c5565b348015610347575f80fd5b506102a26103563660046140c5565b610ddf565b348015610366575f80fd5b506102a261037536600461418a565b610e6a565b348015610385575f80fd5b506102ed6103943660046141b3565b610efa565b3480156103a4575f80fd5b506102a26103b3366004613fba565b610f1f565b3480156103c3575f80fd5b506103cc610faa565b6040805186518152602080880151818301528783015182840152606080890151908301526080808901519083015260a09788015197820197909752855160c08201528686015160e0820152940151610100850152825161012085015293909101516101408301526101608201526101808101919091526101a0016102c5565b348015610456575f80fd5b50604051601281526020016102c5565b348015610471575f80fd5b506104997f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81565b6040516001600160a01b0390911681526020016102c5565b3480156104bc575f80fd5b506102ed6104cb366004614044565b611004565b3480156104db575f80fd5b506102a26104ea3660046141f1565b611025565b3480156104fa575f80fd5b50610499610509366004613fba565b5f908152600c60205260409020546001600160a01b031690565b6102a2610531366004614211565b61110f565b348015610541575f80fd5b5060075461055990600160e01b900463ffffffff1681565b60405163ffffffff90911681526020016102c5565b348015610579575f80fd5b506102a261143d565b34801561058d575f80fd5b506102a261059c366004614044565b61151d565b3480156105ac575f80fd5b5061032e6105bb366004614236565b61169e565b3480156105cb575f80fd5b506102a26116b8565b3480156105df575f80fd5b506102a26105ee36600461425e565b6116cb565b3480156105fe575f80fd5b50600f54610499906001600160a01b031681565b34801561061d575f80fd5b5061063161062c366004613fba565b611761565b6040805162ffffff90931683526001600160a01b039091166020830152016102c5565b34801561065f575f80fd5b506005546001600160a01b0316610499565b34801561067c575f80fd5b506102b8611775565b348015610690575f80fd5b506102ed61069f366004614044565b611784565b3480156106af575f80fd5b506102ed6106be366004614044565b611809565b3480156106ce575f80fd5b5061032e6106dd366004614236565b611816565b3480156106ed575f80fd5b506102a2611820565b348015610701575f80fd5b5061032e60085481565b348015610716575f80fd5b5060075461072a906001600160801b031681565b6040516001600160801b0390911681526020016102c5565b34801561074d575f80fd5b50600d546001600160a01b0316610499565b34801561076a575f80fd5b506102a2610779366004613fba565b611972565b348015610789575f80fd5b507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2610499565b3480156107bb575f80fd5b506007546107d590600160b01b900465ffffffffffff1681565b60405165ffffffffffff90911681526020016102c5565b3480156107f7575f80fd5b506007546107d590600160801b900465ffffffffffff1681565b34801561081c575f80fd5b5061032e61082b3660046142a6565b611a00565b34801561083b575f80fd5b506102a2611a2a565b34801561084f575f80fd5b506102a2611b02565b348015610863575f80fd5b50610877610872366004614236565b611bda565b6040516102c591906142dd565b34801561088f575f80fd5b506102a261089e366004613fba565b611c6c565b3480156108ae575f80fd5b506102a26108bd3660046141f1565b611cfa565b3480156108cd575f80fd5b5061032e611db9565b3480156108e1575f80fd5b506102a26108f0366004614236565b611fd7565b348015610900575f80fd5b5061091461090f366004614236565b61204d565b6040516102c591908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b61094f612095565b600d546001600160a01b0316610978576040516305835fed60e01b815260040160405180910390fd5b5f61098a8266038d7ea4c6800061432d565b90507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004015f604051808303818588803b1580156109e5575f80fd5b505af11580156109f7573d5f803e3d5ffd5b5050600d546040516370a0823160e01b81523060048201525f94506001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28116945063a9059cbb93509091169083906370a08231906024016020604051808303815f875af1158015610a71573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a959190614344565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af1158015610add573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b01919061435b565b905080610b215760405163062e4f6360e11b815260040160405180910390fd5b600d5f9054906101000a90046001600160a01b03166001600160a01b031663fff6cae96040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610b6d575f80fd5b505af1158015610b7f573d5f803e3d5ffd5b5050604080516001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2168152602081018690527f5c0eec4199f95cf196fdac30f5458f67ba720232c0fce87b1540c0c7dc0e773f93500190505b60405180910390a1505050565b606060038054610bfb90614376565b80601f0160208091040260200160405190810160405280929190818152602001828054610c2790614376565b8015610c725780601f10610c4957610100808354040283529160200191610c72565b820191905f5260205f20905b815481529060010190602001808311610c5557829003601f168201915b5050505050905090565b5f33610c898185856120ef565b60019150505b92915050565b60408051600780825261010082019092526060915f91906020820160e080368337019050509050681b1ae4d6e2ef500000815f81518110610cd857610cd86143ae565b602002602001018181525050683635c9adc5dea0000081600181518110610d0157610d016143ae565b602002602001018181525050685150ae84a8cdf0000081600281518110610d2a57610d2a6143ae565b602002602001018181525050686c6b935b8bbd40000081600381518110610d5357610d536143ae565b60200260200101818152505068878678326eac90000081600481518110610d7c57610d7c6143ae565b60200260200101818152505068bdbc41e0348b30000081600581518110610da557610da56143ae565b60200260200101818152505069010f0cf064dd5920000081600681518110610dcf57610dcf6143ae565b6020908102919091010152919050565b336001600160a01b037f0000000000000000000000005a861794b927983406fce1d062e00b9368d97df61614610e5c5760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792056524620563220777261707065722063616e2066756c66696c6c0060448201526064015b60405180910390fd5b610e668282612212565b5050565b610e72612095565b600a610e7e82856143c2565b1180610e935750600a610e9182846143c2565b115b15610eb157604051633634941560e21b815260040160405180910390fd5b610ebc838383612341565b60408051848152602081018490529081018290527fcf8a1e1d5f09cf3c97dbb653cd9a4d7aace9292fbc1bb8211febf2d400febbdd90606001610bdf565b5f33610f0785828561238e565b610f12858585612400565b60019150505b9392505050565b610f27612095565b600754600160e01b900463ffffffff16811015610f5757604051631c23763d60e01b815260040160405180910390fd5b600780546001600160e01b0316600160e01b63ffffffff8416021790556040518181527f0f7a60a7e1cf3f1b0b1540f0e964947327ad8b2bde2e2ac3e07d922b69e977d99060200160405180910390a150565b610fb2613f8a565b610fd360405180606001604052805f81526020015f81526020015f81525090565b604080518082019091525f80825260208201525f80610ff36006546128ee565b945094509450945094509091929394565b5f33610c898185856110168383611a00565b61102091906143c2565b6120ef565b3330148015906110405750600e546001600160a01b03163314155b801561105757506005546001600160a01b03163314155b1561107557604051636932705760e11b815260040160405180910390fd5b6005546001600160a01b0316330361110557600754600160b01b900465ffffffffffff1615806110b257506007546001600160801b03166298967f145b806110c657506007546001600160801b0316155b156110e4576040516351bf115f60e01b815260040160405180910390fd5b6007546006546001600160801b03909116925060b81c62ffffff165f190190505b610e6682826129c5565b611117612095565b600d546001600160a01b03161561114157604051630cac471160e41b815260040160405180910390fd5b61012c8165ffffffffffff161161116b57604051631c23763d60e01b815260040160405180910390fd5b611197307f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d5f196120ef565b7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663f305d719473060016111d33061169e565b6111dd91906143d5565b5f8030426040518863ffffffff1660e01b8152600401611202969594939291906143e8565b60606040518083038185885af115801561121e573d5f803e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906112439190614423565b5050505f7f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112a3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112c7919061444e565b60405163e6a4390560e01b81526001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2811660048301523060248301529192505f9183169063e6a4390590604401602060405180830381865afa158015611336573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135a919061444e565b905061136a815f60015f80612d2d565b600d80546001600160a01b0319166001600160a01b03831617905561139765ffffffffffff8416436143c2565b600760106101000a81548165ffffffffffff021916908365ffffffffffff1602179055505f604051806101a001604052804381526020014360326113db91906143c2565b81526020015f815260200160018152602001600381526020016001815260200160048152602001600481526020016001815260200161177081526020016127108152602001600181526020016001815250905061143781612d90565b50505050565b611445612095565b5f611451600654612e91565b90505f81604001515f03611466576001611468565b5f5b90508160400151810361148d5760405162461bcd60e51b8152600401610e5390614469565b6114ae825f0151836020015183856060015186608001518760a00151612ee5565b80156114ed57604051600181527f0f8293c744b66395bf9a745e7b4d95c3b84f65fd0f4cb60bad74975fa315eb1b906020015b60405180910390a15050565b6040515f81527f0f8293c744b66395bf9a745e7b4d95c3b84f65fd0f4cb60bad74975fa315eb1b906020016114e1565b611525612095565b6001600160a01b03821661154c57604051639ed698f560e01b815260040160405180910390fd5b5f815f036115c3576040516001600160a01b0384169047905f81818185875af1925050503d805f811461159a576040519150601f19603f3d011682016040523d82523d5f602084013e61159f565b606091505b505080915050806115c35760405163062e4f6360e11b815260040160405180910390fd5b600d546001600160a01b038085169116036116195760405162461bcd60e51b81526020600482015260166024820152752ab9b29030b2322a37a830b4b91034b739ba32b0b21760511b6044820152606401610e53565b5f61162b8366038d7ea4c6800061432d565b9050836001600160a01b0316816040515f6040518083038185875af1925050503d805f8114611675576040519150601f19603f3d011682016040523d82523d5f602084013e61167a565b606091505b505080925050816114375760405163062e4f6360e11b815260040160405180910390fd5b6001600160a01b03165f9081526020819052604090205490565b6116c0612095565b6116c95f612f63565b565b6116d3612095565b600d546001600160a01b038481169116148061172057507f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d6001600160a01b0316836001600160a01b0316145b8061173357506001600160a01b03831630145b1561175157604051636932705760e11b815260040160405180910390fd5b61175c838383612fb4565b505050565b5f8061176c83613015565b91509150915091565b606060048054610bfb90614376565b5f33816117918286611a00565b9050838110156117f15760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b6064820152608401610e53565b6117fe82868684036120ef565b506001949350505050565b5f33610c89818585612400565b5f610c8f82613092565b611828612095565b600f546001600160a01b031661183c575f80fd5b7f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b031663a9059cbb61187d6005546001600160a01b031690565b6040516370a0823160e01b81523060048201527f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca6001600160a01b0316906370a0823190602401602060405180830381865afa1580156118df573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119039190614344565b6040516001600160e01b031960e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303815f875af115801561194b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196f919061435b565b50565b61197a612095565b5f611986600654612e91565b6020810151909150808311156119af57604051633634941560e21b815260040160405180910390fd5b6119d0825f0151848460400151856060015186608001518760a00151612ee5565b6040518381527fb32eee1f3b022fecf91130907d354359df3234353a0ee169155ac37dbeed75c090602001610bdf565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b611a32612095565b5f611a3e600654612e91565b90505f81606001515f03611a53576001611a55565b5f5b905081606001518103611a7a5760405162461bcd60e51b8152600401610e5390614469565b611a9b825f0151836020015184604001518486608001518760a00151612ee5565b8015611ad257604051600181527fc97260ffb3df6b903cdfd59e3b5b21a896404903a8e8a83bf60ba3fca365fbe5906020016114e1565b6040515f81527fc97260ffb3df6b903cdfd59e3b5b21a896404903a8e8a83bf60ba3fca365fbe5906020016114e1565b611b0a612095565b5f611b16600654612e91565b90505f8160a001515f03611b2b576001611b2d565b5f5b90508160a001518103611b525760405162461bcd60e51b8152600401610e5390614469565b611b73825f0151836020015184604001518560600151866080015186612ee5565b8015611baa57604051600181527fa8392e314504d0b57633e056d62ab8ededff9020da370c77dd137a25324b5c18906020016114e1565b6040515f81527fa8392e314504d0b57633e056d62ab8ededff9020da370c77dd137a25324b5c18906020016114e1565b6001600160a01b0381165f908152600a602081815260408084205481518481526101608101909252606094909390928201610140803683370190505090505f5b600a811015611c64575f611c2f82601861432d565b90508084901c838381518110611c4757611c476143ae565b62ffffff9092166020928302919091019091015250600101611c1a565b509392505050565b611c74612095565b5f611c80600654612e91565b608081015190915080831115611ca957604051633634941560e21b815260040160405180910390fd5b611cca825f0151836020015184604001518560600151878760a00151612ee5565b6040518381527fb3bf54177f07aa628d24efcbd137a401112718a4d9c8c1a8538b24e21029422990602001610bdf565b611d02612095565b60065460408051808201909152607882901c61ffff16815260889190911c62ffffff1660208201525f611d36600654612e91565b805190915015611d70578151841080611d525750816020015183105b15611d7057604051631c23763d60e01b815260040160405180910390fd5b611d7a84846130bd565b60408051858152602081018590527faa6f6b0a509f2b07cf30d89dbd3bb410883aaa429ad4da41fdf36c02398cf1a0910160405180910390a150505050565b5f611dc2612095565b5f611dce600654612e91565b600654815191925060b81c62ffffff16901580611dfb5750600754600160b01b900465ffffffffffff1615155b80611e165750600754600160801b900465ffffffffffff1643105b80611e215750806001145b15611e3f57604051630cc4134b60e11b815260040160405180910390fd5b5f611e493061169e565b9050681b1ae4d6e2ef500000811115611eae57600d545f90606490611e76906001600160a01b031661169e565b611e8190601461432d565b611e8b91906144a1565b905080821115611e99578091505b611eac611ea76001846143d5565b6130f8565b505b478015611f19575f611ec86005546001600160a01b031690565b6001600160a01b0316476040515f6040518083038185875af1925050503d805f8114611f0f576040519150601f19603f3d011682016040523d82523d5f602084013e611f14565b606091505b505050505b6007805465ffffffffffff60b01b1916600160b01b4265ffffffffffff1602179055611f4361320c565b611f717f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d5f6001805f612d2d565b600754611f8e90600160e01b900463ffffffff166003600161321f565b600780546001600160801b0319166298967f17905560405190955085907f0c720560a539b13f97fb22b6c1ac4393045cedca3bb997fd2ea1f7a3dfb76a58905f90a25050505090565b611fdf612095565b6001600160a01b0381166120445760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610e53565b61196f81612f63565b61207460405180608001604052805f81526020015f81526020015f81526020015f81525090565b6001600160a01b0382165f90815260096020526040902054610c8f906133f8565b6005546001600160a01b031633146116c95760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610e53565b6001600160a01b0383166121515760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b6064820152608401610e53565b6001600160a01b0382166121b25760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b6064820152608401610e53565b6001600160a01b038381165f8181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6006545f9060b81c62ffffff16905080600190039050815f8151811061223a5761223a6143ae565b60200260200101516008819055505f8160085461225791906144b4565b600780546001600160801b0319166001600160801b0383169081179091556040519192509085907f54d97c1f7e5abad75bd421455cd4dd296852a52e1ea721f2cdb66d06fa2082a9905f90a3604080516001600160801b0383166024820152604480820185905282518083039091018152606490910182526020810180516001600160e01b0316633c3b2a7360e01b17905290515f9130916122f991906144c7565b5f604051808303815f865af19150503d805f8114612332576040519150601f19603f3d011682016040523d82523d5f602084013e612337565b606091505b5050505050505050565b5f61235160065460606018613456565b905061235e84600861347f565b606084901b1761236f83600861347f565b606883901b1761238082600861347f565b60709190911b176006555050565b5f6123998484611a00565b90505f19811461143757818110156123f35760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610e53565b61143784848484036120ef565b6006545f61240d82612e91565b6001600160a01b0386165f9081526009602052604081205491925090612432906133f8565b6001600160a01b0386165f9081526009602052604081205491925090612457906133f8565b90506001600160a01b0387163014806124735750604083015115155b8061248f575060208201511580159061248f5750604082015115155b806124ab57506020810151158015906124ab5750604081015115155b156124c0576124bb8787876134ac565b6128e5565b82515f036124e1576040516305835fed60e01b815260040160405180910390fd5b600d5460408051808201909152607886901c61ffff168152608886901c62ffffff1660208201525f916001600160a01b0316905f61251e8861364e565b325f908152600960205260408120549192509061253a906133f8565b90508b6001600160a01b0316846001600160a01b0316036126e35785604001515f036126da5743886020015111156126525787516125799060026143c2565b43101561258b57600a80835260408301525b82516125a090670de0b6b3a76400009061432d565b8a11156125c057604051632d2b153d60e01b815260040160405180910390fd5b670de0b6b3a764000083602001516125d8919061432d565b8a6125e28d61169e565b6125ec91906143c2565b111561260b5760405163cc91297760e01b815260040160405180910390fd5b608088015186514391011180612628575060808801518151439101115b156126465760405163dcafac0960e01b815260040160405180910390fd5b60078252600360408301525b43865260608601511561267b5761267b8b875f0151886020015189604001518a60600151612d2d565b61269d8b878c8c8660018e606001515f03612696575f613697565b6001613697565b326001600160a01b038c16148015906126b95750438860200151115b156126da576126da32875f0151886020015189604001518a60600151612d2d565b600194506127ca565b8a6001600160a01b0316846001600160a01b0316036127ca5760408701511580156127115750608088015115155b1561275157608088015187514391011180612733575060808801518151439101115b156127515760405163dcafac0960e01b815260040160405180910390fd5b61276b8c888c8c865f8e606001515f03612696575f613697565b5f6127753061169e565b9050681b1ae4d6e2ef5000008111156127c8575f60646127948e61169e565b61279f90600561432d565b6127a991906144a1565b90506127c68183116127c057611ea76001846143d5565b816130f8565b505b505b606088015115801590612824575060208601511580156127fb57508b6001600160a01b0316846001600160a01b0316145b806128245750602087015115801561282457508a6001600160a01b0316846001600160a01b0316145b1561283b576128368c8c8c88866139ea565b6128df565b8b6001600160a01b0316846001600160a01b03161415801561286f57508a6001600160a01b0316846001600160a01b031614155b156128d4578760a001515f03612898576040516308090ba360e41b815260040160405180910390fd5b60208601511580156128ab575086518651105b156128b557865186525b6128c48c888c8c865f80613697565b6128d48b878c8c8660015f613697565b6128df8c8c8c6134ac565b50505050505b50505050505050565b6128f6613f8a565b61291760405180606001604052805f81526020015f81526020015f81525090565b60408051808201825263ffffffff8581168552602086811c9091168186015260ff86841c811686850152604887901c8116606080880191909152605088901c82166080880152605888901c821660a0808901919091529088901c82168652606888901c821686840152607088901c9091169385019390935261ffff607887901c16825262ffffff608887901c8116918301919091529395929490939181901c82169260b89190911c90911690565b815f6129d082613015565b9150506001600160a01b038116612aab5782821015612a2b575f6129f483856143d5565b90505f5b81811015612a2857836001019350612a0f84613015565b9350506001600160a01b038316612a28576001016129f8565b50505b6001600160a01b038116158015612a4157508282145b15612a7d578391505f5b84811015612a7b575f1990920191612a6283613015565b9250506001600160a01b038216612a7b57600101612a4b565b505b6001600160a01b038116612a8f575f80fd5b600780546001600160801b0319166001600160801b0384161790555b600f80546001600160a01b0319166001600160a01b0383811691909117909155600d5460405163095ea7b360e01b81527f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d831660048201525f19602482015291169063095ea7b3906044016020604051808303815f875af1158015612b32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612b56919061435b565b50600d546040516370a0823160e01b815230600482018190525f926001600160a01b037f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d8116936302751cec939291909116906370a0823190602401602060405180830381865afa158015612bcd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bf19190614344565b5f8030426040518763ffffffff1660e01b8152600401612c16969594939291906143e8565b60408051808303815f875af1158015612c31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c5591906144e2565b9150505f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114612ca1576040519150601f19603f3d011682016040523d82523d5f602084013e612ca6565b606091505b5050905080612ce95760405162461bcd60e51b815260206004820152600f60248201526e4661696c656420746f2073656e642160881b6044820152606401610e53565b6040516001600160a01b03841681527f0992f42a6118239e571ca390863e9f148a939f9f0470578217d738d6d665116e9060200160405180910390a1505050505050565b612d3884602061347f565b83612d4484600861347f565b602084901b17612d5583600861347f565b602883901b17612d6682601861347f565b6001600160a01b039095165f90815260096020526040902060309190911b94909417909355505050565b604080516101a0810182526020808252808201526008918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101919091526010610120820152601861014082018190526101608201819052610180820152600d905f9081905f5b84811015612e8757612e428682600d8110612e1e57612e1e6143ae565b60200201518383600d8110612e3557612e356143ae565b602002015160ff1661347f565b838682600d8110612e5557612e556143ae565b6020020151901b831792508181600d8110612e7257612e726143ae565b602002015160ff169390930192600101612e01565b5050600655505050565b612e99613f8a565b63ffffffff8083168252602083811c9091169082015260ff604083811c821690830152604883901c81166060830152605083901c8116608083015260589290921c90911660a082015290565b5f612ef46006545f6060613456565b9050612f0187602061347f565b8617612f0e86602061347f565b602086901b17612f1f85600861347f565b604085901b17612f3084600861347f565b604884901b17612f4183600861347f565b605083901b17612f5282600861347f565b60589190911b176006555050505050565b600580546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0383165f90815260096020526040812054612fd5906133f8565b90505f83612fe3575f612fe6565b60015b90505f83612ff4575f612ff7565b60015b905061300d86845f015184848760600151612d2d565b505050505050565b5f8080613023600a856144a1565b90505f600985116130345784613049565b61303f82600a61432d565b61304990866144b4565b90505f61305782601861432d565b5f938452600b602090815260408086205490921c62ffffff81168652600c90915293205492966001600160a01b039093169550919350505050565b6001600160a01b0381165f908152600a6020526040812054816130b482613af5565b50949350505050565b5f6130cd60065460786028613456565b90506130da83601061347f565b607883901b176130eb82601861347f565b60889190911b1760065550565b6040805160028082526060820183525f9260208301908036833701905050905030815f8151811061312b5761312b6143ae565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28160018151811061317f5761317f6143ae565b6001600160a01b03928316602091820292909201015260405163791ac94760e01b81527f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d9091169063791ac947906131e39085905f90869030904290600401614504565b5f604051808303815f87803b1580156131fa575f80fd5b505af115801561300d573d5f803e3d5ffd5b61321a6006545f6020613456565b600655565b6040516310c1b4d560e21b815263ffffffff841660048201525f906001600160a01b037f000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca811691634000aea0917f0000000000000000000000005a861794b927983406fce1d062e00b9368d97df69190821690634306d35490602401602060405180830381865afa1580156132b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906132da9190614344565b6040805163ffffffff808b16602083015261ffff8a169282019290925290871660608201526080016040516020818303038152906040526040518463ffffffff1660e01b815260040161332f93929190614573565b6020604051808303815f875af115801561334b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061336f919061435b565b507f0000000000000000000000005a861794b927983406fce1d062e00b9368d97df66001600160a01b031663fc2a88c36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156133cc573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906133f09190614344565b949350505050565b61341f60405180608001604052805f81526020015f81526020015f81526020015f81525090565b63ffffffff8216815260ff602083811c821690830152602883901c16604082015262ffffff60309290921c91909116606082015290565b5f80836001613466856002614682565b61347091906143d5565b901b1994909416949350505050565b6001811b8210610e6657604051638f44d83160e01b81526004810183905260248101829052604401610e53565b6001600160a01b0383166135105760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b6064820152608401610e53565b6001600160a01b0382166135725760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b6064820152608401610e53565b6001600160a01b0383165f90815260208190526040902054818110156135e95760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b6064820152608401610e53565b6001600160a01b038481165f81815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3611437565b61366f60405180606001604052805f81526020015f81526020015f81525090565b60ff606083901c81168252606883901c8116602083015260709290921c909116604082015290565b5f6136a188613092565b90505f83156138fa5782156137aa578451158015906136c35750604085015115155b156137335761372c60648660400151896136dd919061432d565b6136e791906144a1565b86516064906136f6908b61432d565b61370091906144a1565b61370a908a6143d5565b61371491906143d5565b61371d8b61169e565b61372791906143c2565b613b36565b90506137ba565b84511580159061374557506040850151155b1561377157845161372c9060649061375d908a61432d565b61376791906144a1565b61371490896143d5565b84511580156137835750604085015115155b1561379d5761372c606486604001518961375d919061432d565b61372c8761371d8b61169e565b6137b78761371d8b61169e565b90505b6060880151805f8190036138195760a088901c62ffffff1691508190506137ef8b8b5f01518c602001518d6040015186612d2d565b5f828152600c6020526040902080546001600160a01b0319166001600160a01b038d161790556001015b82158061382557508383145b80156138315750808214155b15613849576138408882613bee565b505050506128e5565b838311156138f35762ffffff60b889901c165f6138708d61386a88886143d5565b84613c11565b90505f61387e858385613c96565b9050838514613897576138928b8583613d41565b6138a1565b6138a18b82613d7c565b7fd4a167f62427a87418c8179efb1099f2da50e01c5374433a1e21db418fd9e4458e6138cd89896143d5565b604080516001600160a01b03909316835260208301919091520160405180910390a15050505b50506139df565b866139048a61169e565b10156139115750506128e5565b6139288761391e8b61169e565b61372791906143d5565b9050818110156139df575f61393d82846143d5565b90505f8167ffffffffffffffff811115613959576139596140b1565b604051908082528060200260200182016040528015613982578160200160208202803683370190505b50905061398f8b83613d9f565b905061399a81613e94565b604080516001600160a01b038d168152602081018490527f0c129863ec4f7070868d0ab05157245e6264ef1004096ec9dd7fbbc67d575253910160405180910390a150505b505050505050505050565b5f8083613a005782602001518360400151613a08565b825160408401515b90925090505f6064613a1a848861432d565b613a2491906144a1565b90505f6064613a33848961432d565b613a3d91906144a1565b90505f81613a4b848a6143d5565b613a5591906143d5565b90508615613a6d57613a688a8a836134ac565b613ad8565b8115613acd57613a7e8a8a846134ac565b886001600160a01b031663fff6cae96040518163ffffffff1660e01b81526004015f604051808303815f87803b158015613ab6575f80fd5b505af1158015613ac8573d5f803e3d5ffd5b505050505b613ad88a8a836134ac565b8215613ae957613ae98a30856134ac565b50505050505050505050565b5f805b600a821015613b31575f613b0d83601861432d565b91505082811c62ffffff81165f03613b255750915091565b82600101925050613af8565b915091565b5f681b1ae4d6e2ef500000821015613b4f57505f919050565b683635c9adc5dea00000821015613b6857506001919050565b685150ae84a8cdf00000821015613b8157506002919050565b686c6b935b8bbd400000821015613b9a57506003919050565b68878678326eac900000821015613bb357506004919050565b68bdbc41e0348b300000821015613bcc57506005919050565b69010f0cf064dd59200000821015613be657506007919050565b50600a919050565b613bfb8260a06018613456565b9150613c0881601861347f565b60a01b17600655565b6001600160a01b0383165f908152600a602052604081205481613c3382613af5565b9150508060d803613c48578492505050610f18565b5f5b85811015613c7357600180860195831b93909317920160d88214613c7357601882019150613c4a565b50506001600160a01b0385165f908152600a602052604090205550819392505050565b600a81045f818152600b6020526040812054909190825b85811015613d3657600a85045f60098711613cc85786613cdc565b81600a028781613cda57613cda61448d565b065b9050601881028015613cf557808a901b85179450613cfb565b89811b94505b8160091480613d0c57508884600101145b15613d22575f838152600b602052604090208590555b876001019750836001019350505050613cad565b509295945050505050565b613d4e8360a06030613456565b9250613d5b82601861347f565b60a082901b83179250613d6f81601861347f565b60b81b9190911760065550565b613d898260b86018613456565b9150613d9681601861347f565b60b81b17600655565b60605f613dab84613092565b6001600160a01b0385165f908152600a60205260408120549192508467ffffffffffffffff811115613ddf57613ddf6140b1565b604051908082528060200260200182016040528015613e08578160200160208202803683370190505b5090505f613e1784601861432d565b90505f5b86811015613e5b576018820391508184901c838281518110613e3f57613e3f6143ae565b62ffffff90921660209283029190910190910152600101613e1b565b50613e718382613e6c89601861432d565b613456565b6001600160a01b0388165f908152600a6020526040902055509250505092915050565b80515f80805b83811015613f83575f858281518110613eb557613eb56143ae565b602002602001015162ffffff1690505f600a8281613ed557613ed561448d565b049050825f03613ef0575f818152600b602052604090205493505b8215801590613eff5750808514155b15613f20575f858152600b6020526040808220959095558181529390932054925b5f60098311613f2f5782613f43565b81600a028381613f4157613f4161448d565b065b90505f816018029050613f5886826018613456565b9550878560010103613f75575f838152600b602052604090208690555b509094505050600101613e9a565b5050505050565b6040518060c001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81525090565b5f60208284031215613fca575f80fd5b5035919050565b5f5b83811015613feb578181015183820152602001613fd3565b50505f910152565b5f815180845261400a816020860160208601613fd1565b601f01601f19169290920160200192915050565b602081525f610f186020830184613ff3565b6001600160a01b038116811461196f575f80fd5b5f8060408385031215614055575f80fd5b823561406081614030565b946020939093013593505050565b602080825282518282018190525f9190848201906040850190845b818110156140a557835183529284019291840191600101614089565b50909695505050505050565b634e487b7160e01b5f52604160045260245ffd5b5f80604083850312156140d6575f80fd5b8235915060208084013567ffffffffffffffff808211156140f5575f80fd5b818601915086601f830112614108575f80fd5b81358181111561411a5761411a6140b1565b8060051b604051601f19603f8301168101818110858211171561413f5761413f6140b1565b60405291825284820192508381018501918983111561415c575f80fd5b938501935b8285101561417a57843584529385019392850192614161565b8096505050505050509250929050565b5f805f6060848603121561419c575f80fd5b505081359360208301359350604090920135919050565b5f805f606084860312156141c5575f80fd5b83356141d081614030565b925060208401356141e081614030565b929592945050506040919091013590565b5f8060408385031215614202575f80fd5b50508035926020909101359150565b5f60208284031215614221575f80fd5b813565ffffffffffff81168114610f18575f80fd5b5f60208284031215614246575f80fd5b8135610f1881614030565b801515811461196f575f80fd5b5f805f60608486031215614270575f80fd5b833561427b81614030565b9250602084013561428b81614251565b9150604084013561429b81614251565b809150509250925092565b5f80604083850312156142b7575f80fd5b82356142c281614030565b915060208301356142d281614030565b809150509250929050565b602080825282518282018190525f9190848201906040850190845b818110156140a557835162ffffff16835292840192918401916001016142f8565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610c8f57610c8f614319565b5f60208284031215614354575f80fd5b5051919050565b5f6020828403121561436b575f80fd5b8151610f1881614251565b600181811c9082168061438a57607f821691505b6020821081036143a857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffd5b80820180821115610c8f57610c8f614319565b81810381811115610c8f57610c8f614319565b6001600160a01b039687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b5f805f60608486031215614435575f80fd5b8351925060208401519150604084015190509250925092565b5f6020828403121561445e575f80fd5b8151610f1881614030565b6020808252600a908201526973616d652076616c756560b01b604082015260600190565b634e487b7160e01b5f52601260045260245ffd5b5f826144af576144af61448d565b500490565b5f826144c2576144c261448d565b500690565b5f82516144d8818460208701613fd1565b9190910192915050565b5f80604083850312156144f3575f80fd5b505080516020909101519092909150565b5f60a082018783526020878185015260a0604085015281875180845260c08601915082890193505f5b818110156145525784516001600160a01b03168352938301939183019160010161452d565b50506001600160a01b03969096166060850152505050608001529392505050565b60018060a01b0384168152826020820152606060408201525f6145996060830184613ff3565b95945050505050565b600181815b808511156145dc57815f19048211156145c2576145c2614319565b808516156145cf57918102915b93841c93908002906145a7565b509250929050565b5f826145f257506001610c8f565b816145fe57505f610c8f565b8160018114614614576002811461461e5761463a565b6001915050610c8f565b60ff84111561462f5761462f614319565b50506001821b610c8f565b5060208310610133831016604e8410600b841016171561465d575081810a610c8f565b61466783836145a2565b805f190482111561467a5761467a614319565b029392505050565b5f610f1883836145e456fea264697066735822122071da3b7386b293fee1e1929e49f67a4cef2c5b4570c355088fbfdf8ff32e2d0f64736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca0000000000000000000000005a861794b927983406fce1d062e00b9368d97df6
-----Decoded View---------------
Arg [0] : router_ (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [1] : linkAddress (address): 0x514910771AF9Ca656af840dff83E8264EcF986CA
Arg [2] : wrapperAddress (address): 0x5A861794B927983406fCE1D062e00b9368d97Df6
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [1] : 000000000000000000000000514910771af9ca656af840dff83e8264ecf986ca
Arg [2] : 0000000000000000000000005a861794b927983406fce1d062e00b9368d97df6
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.