Token migration announcement. War Riders Gun token contract has migrated to a new address.
ERC-721
Old Contract
Overview
Max Total Supply
4,903 WRG
Holders
155
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
4 WRGLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
GunToken
Compiler Version
v0.5.11+commit.c082d0b4
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2019-10-18 */ pragma solidity ^0.5.5; library strings { struct slice { uint _len; uint _ptr; } function memcpy(uint dest, uint src, uint len) private pure { // Copy word-length chunks while possible for(; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes uint mask = 256 ** (32 - len) - 1; assembly { let srcpart := and(mload(src), not(mask)) let destpart := and(mload(dest), mask) mstore(dest, or(destpart, srcpart)) } } /* * @dev Returns a slice containing the entire string. * @param self The string to make a slice from. * @return A newly allocated slice containing the entire string. */ function toSlice(string memory self) internal pure returns (slice memory) { uint ptr; assembly { ptr := add(self, 0x20) } return slice(bytes(self).length, ptr); } /* * @dev Returns the length of a null-terminated bytes32 string. * @param self The value to find the length of. * @return The length of the string, from 0 to 32. */ function len(bytes32 self) internal pure returns (uint) { uint ret; if (self == 0) return 0; if (uint(self) & 0xffffffffffffffffffffffffffffffff == 0) { ret += 16; self = bytes32(uint(self) / 0x100000000000000000000000000000000); } if (uint(self) & 0xffffffffffffffff == 0) { ret += 8; self = bytes32(uint(self) / 0x10000000000000000); } if (uint(self) & 0xffffffff == 0) { ret += 4; self = bytes32(uint(self) / 0x100000000); } if (uint(self) & 0xffff == 0) { ret += 2; self = bytes32(uint(self) / 0x10000); } if (uint(self) & 0xff == 0) { ret += 1; } return 32 - ret; } /* * @dev Returns a slice containing the entire bytes32, interpreted as a * null-terminated utf-8 string. * @param self The bytes32 value to convert to a slice. * @return A new slice containing the value of the input argument up to the * first null. */ function toSliceB32(bytes32 self) internal pure returns (slice memory ret) { // Allocate space for `self` in memory, copy it there, and point ret at it assembly { let ptr := mload(0x40) mstore(0x40, add(ptr, 0x20)) mstore(ptr, self) mstore(add(ret, 0x20), ptr) } ret._len = len(self); } /* * @dev Returns a new slice containing the same data as the current slice. * @param self The slice to copy. * @return A new slice containing the same data as `self`. */ function copy(slice memory self) internal pure returns (slice memory) { return slice(self._len, self._ptr); } /* * @dev Copies a slice to a new string. * @param self The slice to copy. * @return A newly allocated string containing the slice's text. */ function toString(slice memory self) internal pure returns (string memory) { string memory ret = new string(self._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); return ret; } /* * @dev Returns the length in runes of the slice. Note that this operation * takes time proportional to the length of the slice; avoid using it * in loops, and call `slice.empty()` if you only need to know whether * the slice is empty or not. * @param self The slice to operate on. * @return The length of the slice in runes. */ function len(slice memory self) internal pure returns (uint l) { // Starting at ptr-31 means the LSB will be the byte we care about uint ptr = self._ptr - 31; uint end = ptr + self._len; for (l = 0; ptr < end; l++) { uint8 b; assembly { b := and(mload(ptr), 0xFF) } if (b < 0x80) { ptr += 1; } else if(b < 0xE0) { ptr += 2; } else if(b < 0xF0) { ptr += 3; } else if(b < 0xF8) { ptr += 4; } else if(b < 0xFC) { ptr += 5; } else { ptr += 6; } } } /* * @dev Returns true if the slice is empty (has a length of 0). * @param self The slice to operate on. * @return True if the slice is empty, False otherwise. */ function empty(slice memory self) internal pure returns (bool) { return self._len == 0; } /* * @dev Returns a positive number if `other` comes lexicographically after * `self`, a negative number if it comes before, or zero if the * contents of the two slices are equal. Comparison is done per-rune, * on unicode codepoints. * @param self The first slice to compare. * @param other The second slice to compare. * @return The result of the comparison. */ function compare(slice memory self, slice memory other) internal pure returns (int) { uint shortest = self._len; if (other._len < self._len) shortest = other._len; uint selfptr = self._ptr; uint otherptr = other._ptr; for (uint idx = 0; idx < shortest; idx += 32) { uint a; uint b; assembly { a := mload(selfptr) b := mload(otherptr) } if (a != b) { // Mask out irrelevant bytes and check again uint256 mask = uint256(-1); // 0xffff... if(shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } uint256 diff = (a & mask) - (b & mask); if (diff != 0) return int(diff); } selfptr += 32; otherptr += 32; } return int(self._len) - int(other._len); } /* * @dev Returns true if the two slices contain the same text. * @param self The first slice to compare. * @param self The second slice to compare. * @return True if the slices are equal, false otherwise. */ function equals(slice memory self, slice memory other) internal pure returns (bool) { return compare(self, other) == 0; } /* * @dev Extracts the first rune in the slice into `rune`, advancing the * slice to point to the next rune and returning `self`. * @param self The slice to operate on. * @param rune The slice that will contain the first rune. * @return `rune`. */ function nextRune(slice memory self, slice memory rune) internal pure returns (slice memory) { rune._ptr = self._ptr; if (self._len == 0) { rune._len = 0; return rune; } uint l; uint b; // Load the first byte of the rune into the LSBs of b assembly { b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) } if (b < 0x80) { l = 1; } else if(b < 0xE0) { l = 2; } else if(b < 0xF0) { l = 3; } else { l = 4; } // Check for truncated codepoints if (l > self._len) { rune._len = self._len; self._ptr += self._len; self._len = 0; return rune; } self._ptr += l; self._len -= l; rune._len = l; return rune; } /* * @dev Returns the first rune in the slice, advancing the slice to point * to the next rune. * @param self The slice to operate on. * @return A slice containing only the first rune from `self`. */ function nextRune(slice memory self) internal pure returns (slice memory ret) { nextRune(self, ret); } /* * @dev Returns the number of the first codepoint in the slice. * @param self The slice to operate on. * @return The number of the first codepoint in the slice. */ function ord(slice memory self) internal pure returns (uint ret) { if (self._len == 0) { return 0; } uint word; uint length; uint divisor = 2 ** 248; // Load the rune into the MSBs of b assembly { word:= mload(mload(add(self, 32))) } uint b = word / divisor; if (b < 0x80) { ret = b; length = 1; } else if(b < 0xE0) { ret = b & 0x1F; length = 2; } else if(b < 0xF0) { ret = b & 0x0F; length = 3; } else { ret = b & 0x07; length = 4; } // Check for truncated codepoints if (length > self._len) { return 0; } for (uint i = 1; i < length; i++) { divisor = divisor / 256; b = (word / divisor) & 0xFF; if (b & 0xC0 != 0x80) { // Invalid UTF-8 sequence return 0; } ret = (ret * 64) | (b & 0x3F); } return ret; } /* * @dev Returns the keccak-256 hash of the slice. * @param self The slice to hash. * @return The hash of the slice. */ function keccak(slice memory self) internal pure returns (bytes32 ret) { assembly { ret := keccak256(mload(add(self, 32)), mload(self)) } } /* * @dev Returns true if `self` starts with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function startsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } if (self._ptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` starts with `needle`, `needle` is removed from the * beginning of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function beyond(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } bool equal = true; if (self._ptr != needle._ptr) { assembly { let length := mload(needle) let selfptr := mload(add(self, 0x20)) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; self._ptr += needle._len; } return self; } /* * @dev Returns true if the slice ends with `needle`. * @param self The slice to operate on. * @param needle The slice to search for. * @return True if the slice starts with the provided text, false otherwise. */ function endsWith(slice memory self, slice memory needle) internal pure returns (bool) { if (self._len < needle._len) { return false; } uint selfptr = self._ptr + self._len - needle._len; if (selfptr == needle._ptr) { return true; } bool equal; assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } return equal; } /* * @dev If `self` ends with `needle`, `needle` is removed from the * end of `self`. Otherwise, `self` is unmodified. * @param self The slice to operate on. * @param needle The slice to search for. * @return `self` */ function until(slice memory self, slice memory needle) internal pure returns (slice memory) { if (self._len < needle._len) { return self; } uint selfptr = self._ptr + self._len - needle._len; bool equal = true; if (selfptr != needle._ptr) { assembly { let length := mload(needle) let needleptr := mload(add(needle, 0x20)) equal := eq(keccak256(selfptr, length), keccak256(needleptr, length)) } } if (equal) { self._len -= needle._len; } return self; } // Returns the memory address of the first byte of the first occurrence of // `needle` in `self`, or the first byte after `self` if not found. function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr = selfptr; uint idx; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } uint end = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr >= end) return selfptr + selflen; ptr++; assembly { ptrdata := and(mload(ptr), mask) } } return ptr; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; } } } return selfptr + selflen; } // Returns the memory address of the first byte after the last occurrence of // `needle` in `self`, or the address of `self` if not found. function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) { uint ptr; if (needlelen <= selflen) { if (needlelen <= 32) { bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1)); bytes32 needledata; assembly { needledata := and(mload(needleptr), mask) } ptr = selfptr + selflen - needlelen; bytes32 ptrdata; assembly { ptrdata := and(mload(ptr), mask) } while (ptrdata != needledata) { if (ptr <= selfptr) return selfptr; ptr--; assembly { ptrdata := and(mload(ptr), mask) } } return ptr + needlelen; } else { // For long needles, use hashing bytes32 hash; assembly { hash := keccak256(needleptr, needlelen) } ptr = selfptr + (selflen - needlelen); while (ptr >= selfptr) { bytes32 testHash; assembly { testHash := keccak256(ptr, needlelen) } if (hash == testHash) return ptr + needlelen; ptr -= 1; } } } return selfptr; } /* * @dev Modifies `self` to contain everything from the first occurrence of * `needle` to the end of the slice. `self` is set to the empty slice * if `needle` is not found. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function find(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); self._len -= ptr - self._ptr; self._ptr = ptr; return self; } /* * @dev Modifies `self` to contain the part of the string from the start of * `self` to the end of the first occurrence of `needle`. If `needle` * is not found, `self` is set to the empty slice. * @param self The slice to search and modify. * @param needle The text to search for. * @return `self`. */ function rfind(slice memory self, slice memory needle) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); self._len = ptr - self._ptr; return self; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and `token` to everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function split(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = self._ptr; token._len = ptr - self._ptr; if (ptr == self._ptr + self._len) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; self._ptr = ptr + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and returning everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` up to the first occurrence of `delim`. */ function split(slice memory self, slice memory needle) internal pure returns (slice memory token) { split(self, needle, token); } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and `token` to everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function rsplit(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) { uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = ptr; token._len = self._len - (ptr - self._ptr); if (ptr == self._ptr) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything before the last * occurrence of `needle`, and returning everything after it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` after the last occurrence of `delim`. */ function rsplit(slice memory self, slice memory needle) internal pure returns (slice memory token) { rsplit(self, needle, token); } /* * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return The number of occurrences of `needle` found in `self`. */ function count(slice memory self, slice memory needle) internal pure returns (uint cnt) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len; while (ptr <= self._ptr + self._len) { cnt++; ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len; } } /* * @dev Returns True if `self` contains `needle`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return True if `needle` is found in `self`, false otherwise. */ function contains(slice memory self, slice memory needle) internal pure returns (bool) { return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr; } /* * @dev Returns a newly allocated string containing the concatenation of * `self` and `other`. * @param self The first slice to concatenate. * @param other The second slice to concatenate. * @return The concatenation of the two strings. */ function concat(slice memory self, slice memory other) internal pure returns (string memory) { string memory ret = new string(self._len + other._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); memcpy(retptr + self._len, other._ptr, other._len); return ret; } /* * @dev Joins an array of slices, using `self` as a delimiter, returning a * newly allocated string. * @param self The delimiter to use. * @param parts A list of slices to join. * @return A newly allocated string containing all the slices in `parts`, * joined with `self`. */ function join(slice memory self, slice[] memory parts) internal pure returns (string memory) { if (parts.length == 0) return ""; uint length = self._len * (parts.length - 1); for(uint i = 0; i < parts.length; i++) length += parts[i]._len; string memory ret = new string(length); uint retptr; assembly { retptr := add(ret, 32) } for(uint i = 0; i < parts.length; i++) { memcpy(retptr, parts[i]._ptr, parts[i]._len); retptr += parts[i]._len; if (i < parts.length - 1) { memcpy(retptr, self._ptr, self._len); retptr += self._len; } } return ret; } } /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } /** * @dev Required interface of an ERC721 compliant contract. */ contract IERC721 is IERC165 { event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of NFTs in `owner`'s account. */ function balanceOf(address owner) public view returns (uint256 balance); /** * @dev Returns the owner of the NFT specified by `tokenId`. */ function ownerOf(uint256 tokenId) public view returns (address owner); /** * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to * another (`to`). * * * * Requirements: * - `from`, `to` cannot be zero. * - `tokenId` must be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this * NFT by either {approve} or {setApprovalForAll}. */ function safeTransferFrom(address from, address to, uint256 tokenId) public; /** * @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to * another (`to`). * * Requirements: * - If the caller is not `from`, it must be approved to move this NFT by * either {approve} or {setApprovalForAll}. */ function transferFrom(address from, address to, uint256 tokenId) public; function approve(address to, uint256 tokenId) public; function getApproved(uint256 tokenId) public view returns (address operator); function setApprovalForAll(address operator, bool _approved) public; function isApprovedForAll(address owner, address operator) public view returns (bool); function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public; } /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract IERC721Metadata is IERC721 { function name() external view returns (string memory); function symbol() external view returns (string memory); function tokenURI(uint256 tokenId) external view returns (string memory); } /* * @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 GSN 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. */ contract Context { // Empty internal constructor, to prevent people from mistakenly deploying // an instance of this contract, which should be used via inheritance. constructor () internal { } // solhint-disable-previous-line no-empty-blocks function _msgSender() internal view returns (address payable) { return msg.sender; } function _msgData() internal view returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract IERC721Enumerable is IERC721 { function totalSupply() public view returns (uint256); function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId); function tokenByIndex(uint256 index) public view returns (uint256); } /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ contract IERC721Receiver { /** * @notice Handle the receipt of an NFT * @dev The ERC721 smart contract calls this function on the recipient * after a {IERC721-safeTransferFrom}. This function MUST return the function selector, * otherwise the caller will revert the transaction. The selector to be * returned can be obtained as `this.onERC721Received.selector`. This * function MAY throw to revert and reject the transfer. * Note: the ERC721 contract address is always the message sender. * @param operator The address which called `safeTransferFrom` function * @param from The address which previously owned the token * @param tokenId The NFT identifier which is being transferred * @param data Additional data with no specified format * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4); } /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * NOTE: This is a feature of the next version of OpenZeppelin Contracts. * @dev Get it via `npm install @openzeppelin/contracts@next`. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * NOTE: This is a feature of the next version of OpenZeppelin Contracts. * @dev Get it via `npm install @openzeppelin/contracts@next`. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * NOTE: This is a feature of the next version of OpenZeppelin Contracts. * @dev Get it via `npm install @openzeppelin/contracts@next`. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * This test is non-exhaustive, and there may be false-negatives: during the * execution of a contract's constructor, its address will be reported as * not containing a contract. * * IMPORTANT: It is unsafe to assume that an address for which this * function returns false is an externally-owned account (EOA) and not a * contract. */ function isContract(address account) internal view returns (bool) { // This method relies in extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != 0x0 && codehash != accountHash); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * NOTE: This is a feature of the next version of OpenZeppelin Contracts. * @dev Get it via `npm install @openzeppelin/contracts@next`. */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } } /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath} * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never * directly accessed. */ library Counters { using SafeMath for uint256; struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { // The {SafeMath} overflow check can be skipped here, see the comment at the top counter._value += 1; } function decrement(Counter storage counter) internal { counter._value = counter._value.sub(1); } } /** * @dev Implementation of the {IERC165} interface. * * Contracts may inherit from this and call {_registerInterface} to declare * their support of an interface. */ contract ERC165 is IERC165 { /* * bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7 */ bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7; /** * @dev Mapping of interface ids to whether or not it's supported. */ mapping(bytes4 => bool) private _supportedInterfaces; constructor () internal { // Derived contracts need only register support for their own interfaces, // we register support for ERC165 itself here _registerInterface(_INTERFACE_ID_ERC165); } /** * @dev See {IERC165-supportsInterface}. * * Time complexity O(1), guaranteed to always use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev Registers the contract as an implementer of the interface defined by * `interfaceId`. Support of the actual ERC165 interface is automatic and * registering its interface id is not required. * * See {IERC165-supportsInterface}. * * Requirements: * * - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`). */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff, "ERC165: invalid interface id"); _supportedInterfaces[interfaceId] = true; } } /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://eips.ethereum.org/EIPS/eip-721 */ contract ERC721 is Context, ERC165, IERC721 { using SafeMath for uint256; using Address for address; using Counters for Counters.Counter; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from token ID to owner mapping (uint256 => address) private _tokenOwner; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to number of owned token mapping (address => Counters.Counter) private _ownedTokensCount; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; /* * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde * * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ * 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd */ bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; constructor () public { // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721); } /** * @dev Gets the balance of the specified address. * @param owner address to query the balance of * @return uint256 representing the amount owned by the passed address */ function balanceOf(address owner) public view returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _ownedTokensCount[owner].current(); } /** * @dev Gets the owner of the specified token ID. * @param tokenId uint256 ID of the token to query the owner of * @return address currently marked as the owner of the given token ID */ function ownerOf(uint256 tokenId) public view returns (address) { address owner = _tokenOwner[tokenId]; require(owner != address(0), "ERC721: owner query for nonexistent token"); return owner; } /** * @dev Approves another address to transfer the given token ID * The zero address indicates there is no approved address. * There can only be one approved address per token at a given time. * Can only be called by the token owner or an approved operator. * @param to address to be approved for the given token ID * @param tokenId uint256 ID of the token to be approved */ function approve(address to, uint256 tokenId) public { address owner = ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev Gets the approved address for a token ID, or zero if no address set * Reverts if the token ID does not exist. * @param tokenId uint256 ID of the token to query the approval of * @return address currently approved for the given token ID */ function getApproved(uint256 tokenId) public view returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev Sets or unsets the approval of a given operator * An operator is allowed to transfer all tokens of the sender on their behalf. * @param to operator address to set the approval * @param approved representing the status of the approval to be set */ function setApprovalForAll(address to, bool approved) public { require(to != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][to] = approved; emit ApprovalForAll(_msgSender(), to, approved); } /** * @dev Tells whether an operator is approved by a given owner. * @param owner owner address which you want to query the approval of * @param operator operator address which you want to query the approval of * @return bool whether the given operator is approved by the given owner */ function isApprovedForAll(address owner, address operator) public view returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Transfers the ownership of a given token ID to another address. * Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * Requires the msg.sender to be the owner, approved, or operator. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function transferFrom(address from, address to, uint256 tokenId) public { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transferFrom(from, to, tokenId); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received}, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function safeTransferFrom(address from, address to, uint256 tokenId) public { safeTransferFrom(from, to, tokenId, ""); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received}, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the _msgSender() to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransferFrom(from, to, tokenId, _data); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ function _safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) internal { _transferFrom(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether the specified token exists. * @param tokenId uint256 ID of the token to query the existence of * @return bool whether the token exists */ function _exists(uint256 tokenId) internal view returns (bool) { address owner = _tokenOwner[tokenId]; return owner != address(0); } /** * @dev Returns whether the given spender can transfer a given token ID. * @param spender address of the spender to query * @param tokenId uint256 ID of the token to be transferred * @return bool whether the msg.sender is approved for the given token ID, * is an operator of the owner, or is the owner of the token */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Internal function to safely mint a new token. * Reverts if the given token ID already exists. * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * @param to The address that will own the minted token * @param tokenId uint256 ID of the token to be minted */ function _safeMint(address to, uint256 tokenId) internal { _safeMint(to, tokenId, ""); } /** * @dev Internal function to safely mint a new token. * Reverts if the given token ID already exists. * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * @param to The address that will own the minted token * @param tokenId uint256 ID of the token to be minted * @param _data bytes data to send along with a safe transfer check */ function _safeMint(address to, uint256 tokenId, bytes memory _data) internal { _mint(to, tokenId); require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Internal function to mint a new token. * Reverts if the given token ID already exists. * @param to The address that will own the minted token * @param tokenId uint256 ID of the token to be minted */ function _mint(address to, uint256 tokenId) internal { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _tokenOwner[tokenId] = to; _ownedTokensCount[to].increment(); emit Transfer(address(0), to, tokenId); } /** * @dev Internal function to burn a specific token. * Reverts if the token does not exist. * Deprecated, use {_burn} instead. * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own"); _clearApproval(tokenId); _ownedTokensCount[owner].decrement(); _tokenOwner[tokenId] = address(0); emit Transfer(owner, address(0), tokenId); } /** * @dev Internal function to burn a specific token. * Reverts if the token does not exist. * @param tokenId uint256 ID of the token being burned */ function _burn(uint256 tokenId) internal { _burn(ownerOf(tokenId), tokenId); } /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function _transferFrom(address from, address to, uint256 tokenId) internal { require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); require(to != address(0), "ERC721: transfer to the zero address"); _clearApproval(tokenId); _ownedTokensCount[from].decrement(); _ownedTokensCount[to].increment(); _tokenOwner[tokenId] = to; emit Transfer(from, to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * This function is deprecated. * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) internal returns (bool) { if (!to.isContract()) { return true; } bytes4 retval = IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data); return (retval == _ERC721_RECEIVED); } /** * @dev Private function to clear current approval of a given token ID. * @param tokenId uint256 ID of the token to be transferred */ function _clearApproval(uint256 tokenId) private { if (_tokenApprovals[tokenId] != address(0)) { _tokenApprovals[tokenId] = address(0); } } } /** * @title ERC-721 Non-Fungible Token with optional enumeration extension logic * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract ERC721Enumerable is Context, ERC165, ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => uint256[]) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /* * bytes4(keccak256('totalSupply()')) == 0x18160ddd * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 * * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 */ bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; /** * @dev Constructor function. */ constructor () public { // register the supported interface to conform to ERC721Enumerable via ERC165 _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); } /** * @dev Gets the token ID at a given index of the tokens list of the requested owner. * @param owner address owning the tokens list to be accessed * @param index uint256 representing the index to be accessed of the requested tokens list * @return uint256 token ID at the given index of the tokens list owned by the requested address */ function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev Gets the total amount of tokens stored by the contract. * @return uint256 representing the total amount of tokens */ function totalSupply() public view returns (uint256) { return _allTokens.length; } /** * @dev Gets the token ID at a given index of all the tokens in this contract * Reverts if the index is greater or equal to the total number of tokens. * @param index uint256 representing the index to be accessed of the tokens list * @return uint256 token ID at the given index of the tokens list */ function tokenByIndex(uint256 index) public view returns (uint256) { require(index < totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to transferFrom, this imposes no restrictions on msg.sender. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function _transferFrom(address from, address to, uint256 tokenId) internal { super._transferFrom(from, to, tokenId); _removeTokenFromOwnerEnumeration(from, tokenId); _addTokenToOwnerEnumeration(to, tokenId); } /** * @dev Internal function to mint a new token. * Reverts if the given token ID already exists. * @param to address the beneficiary that will own the minted token * @param tokenId uint256 ID of the token to be minted */ function _mint(address to, uint256 tokenId) internal { super._mint(to, tokenId); _addTokenToOwnerEnumeration(to, tokenId); _addTokenToAllTokensEnumeration(tokenId); } /** * @dev Internal function to burn a specific token. * Reverts if the token does not exist. * Deprecated, use {ERC721-_burn} instead. * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); _removeTokenFromOwnerEnumeration(owner, tokenId); // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund _ownedTokensIndex[tokenId] = 0; _removeTokenFromAllTokensEnumeration(tokenId); } /** * @dev Gets the list of token IDs of the requested owner. * @param owner address owning the tokens * @return uint256[] List of token IDs owned by the requested address */ function _tokensOfOwner(address owner) internal view returns (uint256[] storage) { return _ownedTokens[owner]; } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { _ownedTokensIndex[tokenId] = _ownedTokens[to].length; _ownedTokens[to].push(tokenId); } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array _ownedTokens[from].length--; // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by // lastTokenId, or just over the end of the array if the token was the last one). } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length.sub(1); uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array _allTokens.length--; _allTokensIndex[tokenId] = 0; } } /** * @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. * * 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. */ 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 () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner(), "Ownable: caller is not the owner"); _; } /** * @dev Returns true if the caller is the current owner. */ function isOwner() public view returns (bool) { return _msgSender() == _owner; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = 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 onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } /** * @title ERC721 Non-Fungible Token Standard basic implementation * Modified to remove the mint function and to replace it * with the _addTokenTo function. * This function is very similar to the _mint function, but it * does not emit a Transfer event * @dev see https://eips.ethereum.org/EIPS/eip-721 */ contract NoMintERC721 is Context, ERC165, IERC721 { using SafeMath for uint256; using Address for address; using Counters for Counters.Counter; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from token ID to owner mapping (uint256 => address) private _tokenOwner; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to number of owned token mapping (address => Counters.Counter) private _ownedTokensCount; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; /* * bytes4(keccak256('balanceOf(address)')) == 0x70a08231 * bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e * bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3 * bytes4(keccak256('getApproved(uint256)')) == 0x081812fc * bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465 * bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5 * bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde * * => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^ * 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd */ bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd; constructor () public { // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721); } /** * @dev Gets the balance of the specified address. * @param owner address to query the balance of * @return uint256 representing the amount owned by the passed address */ function balanceOf(address owner) public view returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return _ownedTokensCount[owner].current(); } /** * @dev Gets the owner of the specified token ID. * @param tokenId uint256 ID of the token to query the owner of * @return address currently marked as the owner of the given token ID */ function ownerOf(uint256 tokenId) public view returns (address) { address owner = _tokenOwner[tokenId]; require(owner != address(0), "ERC721: owner query for nonexistent token"); return owner; } /** * @dev Approves another address to transfer the given token ID * The zero address indicates there is no approved address. * There can only be one approved address per token at a given time. * Can only be called by the token owner or an approved operator. * @param to address to be approved for the given token ID * @param tokenId uint256 ID of the token to be approved */ function approve(address to, uint256 tokenId) public { address owner = ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not owner nor approved for all" ); _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev Gets the approved address for a token ID, or zero if no address set * Reverts if the token ID does not exist. * @param tokenId uint256 ID of the token to query the approval of * @return address currently approved for the given token ID */ function getApproved(uint256 tokenId) public view returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev Sets or unsets the approval of a given operator * An operator is allowed to transfer all tokens of the sender on their behalf. * @param to operator address to set the approval * @param approved representing the status of the approval to be set */ function setApprovalForAll(address to, bool approved) public { require(to != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][to] = approved; emit ApprovalForAll(_msgSender(), to, approved); } /** * @dev Tells whether an operator is approved by a given owner. * @param owner owner address which you want to query the approval of * @param operator operator address which you want to query the approval of * @return bool whether the given operator is approved by the given owner */ function isApprovedForAll(address owner, address operator) public view returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Transfers the ownership of a given token ID to another address. * Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * Requires the msg.sender to be the owner, approved, or operator. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function transferFrom(address from, address to, uint256 tokenId) public { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _transferFrom(from, to, tokenId); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received}, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function safeTransferFrom(address from, address to, uint256 tokenId) public { safeTransferFrom(from, to, tokenId, ""); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement {IERC721Receiver-onERC721Received}, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the _msgSender() to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved"); _safeTransferFrom(from, to, tokenId, _data); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg.sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ function _safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) internal { _transferFrom(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns whether the specified token exists. * @param tokenId uint256 ID of the token to query the existence of * @return bool whether the token exists */ function _exists(uint256 tokenId) internal view returns (bool) { address owner = _tokenOwner[tokenId]; return owner != address(0); } /** * @dev Returns whether the given spender can transfer a given token ID. * @param spender address of the spender to query * @param tokenId uint256 ID of the token to be transferred * @return bool whether the msg.sender is approved for the given token ID, * is an operator of the owner, or is the owner of the token */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender)); } /** * @dev Internal function to mint a new token. * Reverts if the given token ID already exists. * @param to The address that will own the minted token * @param tokenId uint256 ID of the token to be minted */ function _addTokenTo(address to, uint256 tokenId) internal { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _tokenOwner[tokenId] = to; _ownedTokensCount[to].increment(); } /** * @dev Internal function to burn a specific token. * Reverts if the token does not exist. * Deprecated, use {_burn} instead. * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own"); _clearApproval(tokenId); _ownedTokensCount[owner].decrement(); _tokenOwner[tokenId] = address(0); emit Transfer(owner, address(0), tokenId); } /** * @dev Internal function to burn a specific token. * Reverts if the token does not exist. * @param tokenId uint256 ID of the token being burned */ function _burn(uint256 tokenId) internal { _burn(ownerOf(tokenId), tokenId); } /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function _transferFrom(address from, address to, uint256 tokenId) internal { require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own"); require(to != address(0), "ERC721: transfer to the zero address"); _clearApproval(tokenId); _ownedTokensCount[from].decrement(); _ownedTokensCount[to].increment(); _tokenOwner[tokenId] = to; emit Transfer(from, to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * This function is deprecated. * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data) internal returns (bool) { if (!to.isContract()) { return true; } bytes4 retval = IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data); return (retval == _ERC721_RECEIVED); } /** * @dev Private function to clear current approval of a given token ID. * @param tokenId uint256 ID of the token to be transferred */ function _clearApproval(uint256 tokenId) private { if (_tokenApprovals[tokenId] != address(0)) { _tokenApprovals[tokenId] = address(0); } } } /** * @title ERC-721 Non-Fungible Token with optional enumeration extension logic * Modified to work with the NoMintERC721 contract * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract NoMintERC721Enumerable is Context, ERC165, NoMintERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => uint256[]) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /* * bytes4(keccak256('totalSupply()')) == 0x18160ddd * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59 * bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7 * * => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63 */ bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63; /** * @dev Constructor function. */ constructor () public { // register the supported interface to conform to ERC721Enumerable via ERC165 _registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE); } /** * @dev Gets the token ID at a given index of the tokens list of the requested owner. * @param owner address owning the tokens list to be accessed * @param index uint256 representing the index to be accessed of the requested tokens list * @return uint256 token ID at the given index of the tokens list owned by the requested address */ function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev Gets the total amount of tokens stored by the contract. * @return uint256 representing the total amount of tokens */ function totalSupply() public view returns (uint256) { return _allTokens.length; } /** * @dev Gets the token ID at a given index of all the tokens in this contract * Reverts if the index is greater or equal to the total number of tokens. * @param index uint256 representing the index to be accessed of the tokens list * @return uint256 token ID at the given index of the tokens list */ function tokenByIndex(uint256 index) public view returns (uint256) { require(index < totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev Internal function to transfer ownership of a given token ID to another address. * As opposed to transferFrom, this imposes no restrictions on msg.sender. * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function _transferFrom(address from, address to, uint256 tokenId) internal { super._transferFrom(from, to, tokenId); _removeTokenFromOwnerEnumeration(from, tokenId); _addTokenToOwnerEnumeration(to, tokenId); } /** * @dev Internal function to mint a new token. * Reverts if the given token ID already exists. * @param to address the beneficiary that will own the minted token * @param tokenId uint256 ID of the token to be minted */ function _addTokenTo(address to, uint256 tokenId) internal { super._addTokenTo(to, tokenId); _addTokenToOwnerEnumeration(to, tokenId); _addTokenToAllTokensEnumeration(tokenId); } /** * @dev Internal function to burn a specific token. * Reverts if the token does not exist. * Deprecated, use {ERC721-_burn} instead. * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned */ function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); _removeTokenFromOwnerEnumeration(owner, tokenId); // Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund _ownedTokensIndex[tokenId] = 0; _removeTokenFromAllTokensEnumeration(tokenId); } /** * @dev Gets the list of token IDs of the requested owner. * @param owner address owning the tokens * @return uint256[] List of token IDs owned by the requested address */ function _tokensOfOwner(address owner) internal view returns (uint256[] storage) { return _ownedTokens[owner]; } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { _ownedTokensIndex[tokenId] = _ownedTokens[to].length; _ownedTokens[to].push(tokenId); } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array _ownedTokens[from].length--; // Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by // lastTokenId, or just over the end of the array if the token was the last one). } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length.sub(1); uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array _allTokens.length--; _allTokensIndex[tokenId] = 0; } } /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * Modified to change * function tokenURI(uint256 tokenId) external view returns (string memory); * to * function tokenURI(uint256 tokenId) public view returns (string memory); * @dev See https://eips.ethereum.org/EIPS/eip-721 */ contract OveridableERC721Metadata is Context, ERC165, NoMintERC721, IERC721Metadata { // Token name string private _name; // Token symbol string private _symbol; // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; /* * bytes4(keccak256('name()')) == 0x06fdde03 * bytes4(keccak256('symbol()')) == 0x95d89b41 * bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd * * => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f */ bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f; /** * @dev Constructor function */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_INTERFACE_ID_ERC721_METADATA); } /** * @dev Gets the token name. * @return string representing the token name */ function name() external view returns (string memory) { return _name; } /** * @dev Gets the token symbol. * @return string representing the token symbol */ function symbol() external view returns (string memory) { return _symbol; } /** * @dev Returns an URI for a given token ID. * Throws if the token ID does not exist. May return an empty string. * @param tokenId uint256 ID of the token to query */ function tokenURI(uint256 tokenId) public view returns (string memory) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); return _tokenURIs[tokenId]; } /** * @dev Internal function to set the token URI for a given token. * Reverts if the token ID does not exist. * @param tokenId uint256 ID of the token to set its URI * @param uri string URI to assign */ function _setTokenURI(uint256 tokenId, string memory uri) internal { require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token"); _tokenURIs[tokenId] = uri; } /** * @dev Internal function to burn a specific token. * Reverts if the token does not exist. * Deprecated, use _burn(uint256) instead. * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned by the msg.sender */ function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); // Clear metadata (if any) if (bytes(_tokenURIs[tokenId]).length != 0) { delete _tokenURIs[tokenId]; } } } /** * ERC-721 implementation that allows * tokens (of the same category) to be minted in batches. Each batch * contains enough data to generate all * token ids inside the batch, and to * generate the tokenURI in the batch */ contract GunToken is NoMintERC721, NoMintERC721Enumerable, OveridableERC721Metadata, Ownable { using strings for *; address internal factory; address internal oldToken; uint256 internal migrateCursor = 0; uint16 public constant maxAllocation = 4000; uint256 public lastAllocation = 0; event BatchTransfer(address indexed from, address indexed to, uint256 indexed batchIndex); struct Batch { address owner; uint16 size; uint8 category; uint256 startId; uint256 startTokenId; } Batch[] public allBatches; mapping(address => uint256) unactivatedBalance; mapping(uint256 => bool) isActivated; //Used for enumeration mapping(address => Batch[]) public batchesOwned; //Batch index to owner batch index mapping(uint256 => uint256) public ownedBatchIndex; mapping(uint8 => uint256) internal totalGunsMintedByCategory; uint256 internal _totalSupply; modifier onlyFactory { require(msg.sender == factory, "Not authorized"); _; } constructor(address factoryAddress, address oldGunToken) public OveridableERC721Metadata("War Riders Gun", "WRG") { factory = factoryAddress; oldToken = oldGunToken; } function categoryTypeToId(uint8 category, uint256 categoryId) public view returns (uint256) { for (uint i = 0; i < allBatches.length; i++) { Batch memory a = allBatches[i]; if (a.category != category) continue; uint256 endId = a.startId + a.size; if (categoryId >= a.startId && categoryId < endId) { uint256 dif = categoryId - a.startId; return a.startTokenId + dif; } } revert(); } /** * @dev Gets the token ID at a given index of the tokens list of the requested owner. * @param owner address owning the tokens list to be accessed * @param index uint256 representing the index to be accessed of the requested tokens list * @return uint256 token ID at the given index of the tokens list owned by the requested address */ function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) { return tokenOfOwner(owner)[index]; } function getBatchCount(address owner) public view returns(uint256) { return batchesOwned[owner].length; } function getTokensInBatch(address owner, uint256 index) public view returns (uint256[] memory) { Batch memory a = batchesOwned[owner][index]; uint256[] memory result = new uint256[](a.size); uint256 pos = 0; uint end = a.startTokenId + a.size; for (uint i = a.startTokenId; i < end; i++) { if (isActivated[i] && super.ownerOf(i) != owner) { continue; } result[pos] = i; pos++; } require(pos > 0); uint256 subAmount = a.size - pos; assembly { mstore(result, sub(mload(result), subAmount)) } return result; } function tokenByIndex(uint256 index) public view returns (uint256) { return allTokens()[index]; } function allTokens() public view returns (uint256[] memory) { uint256[] memory result = new uint256[](totalSupply()); uint pos = 0; for (uint i = 0; i < allBatches.length; i++) { Batch memory a = allBatches[i]; uint end = a.startTokenId + a.size; for (uint j = a.startTokenId; j < end; j++) { result[pos] = j; pos++; } } return result; } function tokenOfOwner(address owner) public view returns (uint256[] memory) { uint256[] memory result = new uint256[](balanceOf(owner)); uint pos = 0; for (uint i = 0; i < batchesOwned[owner].length; i++) { Batch memory a = batchesOwned[owner][i]; uint end = a.startTokenId + a.size; for (uint j = a.startTokenId; j < end; j++) { if (isActivated[j] && super.ownerOf(j) != owner) { continue; } result[pos] = j; pos++; } } uint256[] memory fallbackOwned = _tokensOfOwner(owner); for (uint i = 0; i < fallbackOwned.length; i++) { result[pos] = fallbackOwned[i]; pos++; } return result; } function balanceOf(address owner) public view returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); return super.balanceOf(owner) + unactivatedBalance[owner]; } function ownerOf(uint256 tokenId) public view returns (address) { require(exists(tokenId), "Token doesn't exist!"); if (isActivated[tokenId]) { return super.ownerOf(tokenId); } uint256 index = getBatchIndex(tokenId); require(index < allBatches.length, "Token batch doesn't exist"); Batch memory a = allBatches[index]; require(tokenId < a.startTokenId + a.size); return a.owner; } function exists(uint256 _tokenId) public view returns (bool) { if (isActivated[_tokenId]) { return super._exists(_tokenId); } else { uint256 index = getBatchIndex(_tokenId); if (index < allBatches.length) { Batch memory a = allBatches[index]; uint end = a.startTokenId + a.size; return _tokenId < end; } return false; } } function totalSupply() public view returns (uint256) { return _totalSupply; } function claimAllocation(address to, uint16 size, uint8 category) public onlyFactory returns (uint) { require(size < maxAllocation, "Size must be smaller than maxAllocation"); allBatches.push(Batch({ owner: to, size: size, category: category, startId: totalGunsMintedByCategory[category], startTokenId: lastAllocation })); uint end = lastAllocation + size; for (uint i = lastAllocation; i < end; i++) { emit Transfer(address(0), to, i); } lastAllocation += maxAllocation; unactivatedBalance[to] += size; totalGunsMintedByCategory[category] += size; _addBatchToOwner(to, allBatches[allBatches.length - 1]); _totalSupply += size; return lastAllocation; } function migrate(uint256 count) public onlyOwner returns (uint256) { GunToken oldGuns = GunToken(oldToken); for (uint256 i = 0; i < count; i++) { uint256 index = migrateCursor + i; (address to, uint16 size, uint8 category, uint256 startId, uint256 startTokenId) = oldGuns.allBatches(index); allBatches.push(Batch({ owner: to, size: size, category: category, startId: startId, startTokenId: startTokenId })); uint end = lastAllocation + size; uint256 ubalance = size; for (uint z = lastAllocation; z < end; z++) { address owner = oldGuns.ownerOf(z); if (owner != to) { isActivated[z] = true; addTokenTo(owner, z); ubalance--; } else { emit Transfer(address(0), to, z); } } lastAllocation += maxAllocation; unactivatedBalance[to] += ubalance; totalGunsMintedByCategory[category] += size; _addBatchToOwner(to, allBatches[allBatches.length - 1]); _totalSupply += size; } migrateCursor += count; return lastAllocation; } function transferFrom(address from, address to, uint256 tokenId) public { if (!isActivated[tokenId]) { activate(tokenId); } super.transferFrom(from, to, tokenId); } function activate(uint256 tokenId) public { require(!isActivated[tokenId], "Token already activated"); uint256 index = getBatchIndex(tokenId); require(index < allBatches.length, "Token batch doesn't exist"); Batch memory a = allBatches[index]; require(tokenId < a.startTokenId + a.size); isActivated[tokenId] = true; addTokenTo(a.owner, tokenId); unactivatedBalance[a.owner]--; } function getBatchIndex(uint256 tokenId) public pure returns (uint256) { uint256 index = (tokenId / maxAllocation); return index; } function categoryForToken(uint256 tokenId) public view returns (uint8) { uint256 index = getBatchIndex(tokenId); require(index < allBatches.length, "Token batch doesn't exist"); Batch memory a = allBatches[index]; return a.category; } function categoryIdForToken(uint256 tokenId) public view returns (uint256) { uint256 index = getBatchIndex(tokenId); require(index < allBatches.length, "Token batch doesn't exist"); Batch memory a = allBatches[index]; uint256 categoryId = (tokenId % maxAllocation) + a.startId; return categoryId; } function uintToString(uint v) internal pure returns (string memory) { if (v == 0) { return "0"; } uint j = v; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len - 1; while (v != 0) { bstr[k--] = byte(uint8(48 + v % 10)); v /= 10; } return string(bstr); } function tokenURI(uint256 tokenId) public view returns (string memory) { require(exists(tokenId), "Token doesn't exist!"); if (isActivated[tokenId]) { return super.tokenURI(tokenId); } else { //Predict the token URI uint8 category = categoryForToken(tokenId); uint256 _categoryId = categoryIdForToken(tokenId); string memory id = uintToString(category).toSlice().concat("/".toSlice()).toSlice().concat(uintToString(_categoryId).toSlice().concat(".json".toSlice()).toSlice()); string memory _base = "https://vault.warriders.com/guns/"; //Final URL: https://vault.warriders.com/guns/<category>/<category_id>.json string memory _metadata = _base.toSlice().concat(id.toSlice()); return _metadata; } } function addTokenTo(address _to, uint256 _tokenId) internal { //Predict the token URI uint8 category = categoryForToken(_tokenId); uint256 _categoryId = categoryIdForToken(_tokenId); string memory id = uintToString(category).toSlice().concat("/".toSlice()).toSlice().concat(uintToString(_categoryId).toSlice().concat(".json".toSlice()).toSlice()); string memory _base = "https://vault.warriders.com/guns/"; //Final URL: https://vault.warriders.com/guns/<category>/<category_id>.json string memory _metadata = _base.toSlice().concat(id.toSlice()); super._addTokenTo(_to, _tokenId); super._setTokenURI(_tokenId, _metadata); } function ceil(uint a, uint m) internal pure returns (uint ) { return ((a + m - 1) / m) * m; } function _removeBatchFromOwner(address from, Batch memory batch) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 globalIndex = getBatchIndex(batch.startTokenId); uint256 lastBatchIndex = batchesOwned[from].length.sub(1); uint256 batchIndex = ownedBatchIndex[globalIndex]; // When the token to delete is the last token, the swap operation is unnecessary if (batchIndex != lastBatchIndex) { Batch memory lastBatch = batchesOwned[from][lastBatchIndex]; uint256 lastGlobalIndex = getBatchIndex(lastBatch.startTokenId); batchesOwned[from][batchIndex] = lastBatch; // Move the last batch to the slot of the to-delete batch ownedBatchIndex[lastGlobalIndex] = batchIndex; // Update the moved batch's index } // This also deletes the contents at the last position of the array batchesOwned[from].length--; // Note that ownedBatchIndex[batch] hasn't been cleared: it still points to the old slot (now occupied by // lastBatch, or just over the end of the array if the batch was the last one). } function _addBatchToOwner(address to, Batch memory batch) private { uint256 globalIndex = getBatchIndex(batch.startTokenId); ownedBatchIndex[globalIndex] = batchesOwned[to].length; batchesOwned[to].push(batch); } function batchTransfer(uint256 batchIndex, address to) public { Batch storage a = allBatches[batchIndex]; address previousOwner = a.owner; require(a.owner == msg.sender); _removeBatchFromOwner(previousOwner, a); a.owner = to; _addBatchToOwner(to, a); emit BatchTransfer(previousOwner, to, batchIndex); //Now to need to emit a bunch of transfer events uint end = a.startTokenId + a.size; uint256 unActivated = 0; for (uint i = a.startTokenId; i < end; i++) { if (isActivated[i]) { if (ownerOf(i) != previousOwner) continue; //The previous owner didn't own this token, don't emit an event } else { unActivated++; } emit Transfer(previousOwner, to, i); } unactivatedBalance[to] += unActivated; unactivatedBalance[previousOwner] -= unActivated; } } contract ApproveAndCallFallBack { function receiveApproval(address from, uint256 tokens, address token, bytes memory data) public payable returns (bool); } /** * @title ERC20Basic * @dev Simpler version of ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/179 */ contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } contract ERC20 is ERC20Basic { function allowance(address owner, address spender) public view returns (uint256); function transferFrom(address from, address to, uint256 value) public returns (bool); function approve(address spender, uint256 value) public returns (bool); event Approval( address indexed owner, address indexed spender, uint256 value ); } contract BurnableToken is ERC20 { event Burn(address indexed burner, uint256 value); function burn(uint256 _value) public; } contract StandardBurnableToken is BurnableToken { function burnFrom(address _from, uint256 _value) public; } interface BZNFeed { /** * Returns the converted BZN value */ function convert(uint256 usd) external view returns (uint256); } contract SimpleBZNFeed is BZNFeed, Ownable { uint256 private conversion; function updateConversion(uint256 conversionRate) public onlyOwner { conversion = conversionRate; } function convert(uint256 usd) external view returns (uint256) { return usd * conversion; } } interface IDSValue { function peek() external view returns (bytes32, bool); function read() external view returns (bytes32); function poke(bytes32 wut) external; function void() external; } library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes_slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes_slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes_slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes_slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes_slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes_slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint _start, uint _length ) internal pure returns (bytes memory) { require(_bytes.length >= (_start + _length)); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint _start) internal pure returns (address) { require(_bytes.length >= (_start + 20)); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint _start) internal pure returns (uint8) { require(_bytes.length >= (_start + 1)); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint _start) internal pure returns (uint16) { require(_bytes.length >= (_start + 2)); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint _start) internal pure returns (uint32) { require(_bytes.length >= (_start + 4)); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint _start) internal pure returns (uint64) { require(_bytes.length >= (_start + 8)); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint _start) internal pure returns (uint96) { require(_bytes.length >= (_start + 12)); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint _start) internal pure returns (uint128) { require(_bytes.length >= (_start + 16)); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint(bytes memory _bytes, uint _start) internal pure returns (uint256) { require(_bytes.length >= (_start + 32)); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint _start) internal pure returns (bytes32) { require(_bytes.length >= (_start + 32)); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes_slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes_slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } } contract GunPreOrder is Ownable, ApproveAndCallFallBack { using BytesLib for bytes; using SafeMath for uint256; //Event for when a bulk buy order has been placed event consumerBulkBuy(uint8 category, uint256 quanity, address reserver); //Event for when a gun has been bought event GunsBought(uint256 gunId, address owner, uint8 category); //Event for when ether is taken out of this contract event Withdrawal(uint256 amount); //Default referal commision percent uint256 public constant COMMISSION_PERCENT = 5; //Whether category is open mapping(uint8 => bool) public categoryExists; mapping(uint8 => bool) public categoryOpen; mapping(uint8 => bool) public categoryKilled; //The additional referal commision percent for any given referal address (default is 0) mapping(address => uint256) internal commissionRate; //How many guns in a given category an address has reserved mapping(uint8 => mapping(address => uint256)) public categoryReserveAmount; //Opensea buy address address internal constant OPENSEA = 0x5b3256965e7C3cF26E11FCAf296DfC8807C01073; //The percent increase and percent base for a given category mapping(uint8 => uint256) public categoryPercentIncrease; mapping(uint8 => uint256) public categoryPercentBase; //Price of a givevn category in USD WEI mapping(uint8 => uint256) public categoryPrice; //The percent of ether required for buying in BZN mapping(uint8 => uint256) public requiredEtherPercent; mapping(uint8 => uint256) public requiredEtherPercentBase; bool public allowCreateCategory = true; //The gun token contract GunToken public token; //The gun factory contract GunFactory internal factory; //The BZN contract StandardBurnableToken internal bzn; //The Maker ETH/USD price feed IDSValue public ethFeed; BZNFeed public bznFeed; //The gamepool address address internal gamePool; //Require the skinned/regular shop to be opened modifier ensureShopOpen(uint8 category) { require(categoryExists[category], "Category doesn't exist!"); require(categoryOpen[category], "Category is not open!"); _; } //Allow a function to accept ETH payment modifier payInETH(address referal, uint8 category, address new_owner, uint16 quanity) { uint256 usdPrice; uint256 totalPrice; (usdPrice, totalPrice) = priceFor(category, quanity); require(usdPrice > 0, "Price not yet set"); categoryPrice[category] = usdPrice; //Save last price uint256 price = convert(totalPrice, false); require(msg.value >= price, "Not enough Ether sent!"); _; if (msg.value > price) { uint256 change = msg.value - price; msg.sender.transfer(change); } if (referal != address(0)) { require(referal != msg.sender, "The referal cannot be the sender"); require(referal != tx.origin, "The referal cannot be the tranaction origin"); require(referal != new_owner, "The referal cannot be the new owner"); //The commissionRate map adds any partner bonuses, or 0 if a normal user referral uint256 totalCommision = COMMISSION_PERCENT + commissionRate[referal]; uint256 commision = (price * totalCommision) / 100; address payable _referal = address(uint160(referal)); _referal.transfer(commision); } } //Allow function to accept BZN payment modifier payInBZN(address referal, uint8 category, address payable new_owner, uint16 quanity) { uint256[] memory prices = new uint256[](4); //Hack to work around local var limit (usdPrice, bznPrice, commision, totalPrice) (prices[0], prices[3]) = priceFor(category, quanity); require(prices[0] > 0, "Price not yet set"); categoryPrice[category] = prices[0]; prices[1] = convert(prices[3], true); //Convert the totalPrice to BZN //The commissionRate map adds any partner bonuses, or 0 if a normal user referral if (referal != address(0)) { prices[2] = (prices[1] * (COMMISSION_PERCENT + commissionRate[referal])) / 100; } uint256 requiredEther = (convert(prices[3], false) * requiredEtherPercent[category]) / requiredEtherPercentBase[category]; require(msg.value >= requiredEther, "Buying with BZN requires some Ether!"); bzn.burnFrom(new_owner, (((prices[1] - prices[2]) * 30) / 100)); bzn.transferFrom(new_owner, gamePool, prices[1] - prices[2] - (((prices[1] - prices[2]) * 30) / 100)); _; if (msg.value > requiredEther) { new_owner.transfer(msg.value - requiredEther); } if (referal != address(0)) { require(referal != msg.sender, "The referal cannot be the sender"); require(referal != tx.origin, "The referal cannot be the tranaction origin"); require(referal != new_owner, "The referal cannot be the new owner"); bzn.transferFrom(new_owner, referal, prices[2]); prices[2] = (requiredEther * (COMMISSION_PERCENT + commissionRate[referal])) / 100; address payable _referal = address(uint160(referal)); _referal.transfer(prices[2]); } } //Constructor constructor( address tokenAddress, address tokenFactory, address gp, address isd, address bzn_address ) public { token = GunToken(tokenAddress); factory = GunFactory(tokenFactory); ethFeed = IDSValue(isd); bzn = StandardBurnableToken(bzn_address); gamePool = gp; //Set percent increases categoryPercentIncrease[1] = 100035; categoryPercentBase[1] = 100000; categoryPercentIncrease[2] = 100025; categoryPercentBase[2] = 100000; categoryPercentIncrease[3] = 100015; categoryPercentBase[3] = 100000; commissionRate[OPENSEA] = 10; } function createCategory(uint8 category) public onlyOwner { require(allowCreateCategory); categoryExists[category] = true; } function disableCreateCategories() public onlyOwner { allowCreateCategory = false; } //Set the referal commision rate for an address function setCommission(address referral, uint256 percent) public onlyOwner { require(percent > COMMISSION_PERCENT); require(percent < 95); percent = percent - COMMISSION_PERCENT; commissionRate[referral] = percent; } //Set the price increase/base for skinned or regular guns function setPercentIncrease(uint256 increase, uint256 base, uint8 category) public onlyOwner { require(increase > base); categoryPercentIncrease[category] = increase; categoryPercentBase[category] = base; } function setEtherPercent(uint256 percent, uint256 base, uint8 category) public onlyOwner { requiredEtherPercent[category] = percent; requiredEtherPercentBase[category] = base; } function killCategory(uint8 category) public onlyOwner { require(!categoryKilled[category]); categoryOpen[category] = false; categoryKilled[category] = true; } //Open/Close the skinned or regular guns shop function setShopState(uint8 category, bool open) public onlyOwner { require(category == 1 || category == 2 || category == 3); require(!categoryKilled[category]); require(categoryExists[category]); categoryOpen[category] = open; } /** * Set the price for any given category in USD. */ function setPrice(uint8 category, uint256 price, bool inWei) public onlyOwner { uint256 multiply = 1e18; if (inWei) { multiply = 1; } categoryPrice[category] = price * multiply; } /** Withdraw the amount from the contract's balance. Only the contract owner can execute this function */ function withdraw(uint256 amount) public onlyOwner { uint256 balance = address(this).balance; require(amount <= balance, "Requested to much"); address payable _owner = address(uint160(owner())); _owner.transfer(amount); emit Withdrawal(amount); } function setBZNFeedContract(address new_bzn_feed) public onlyOwner { bznFeed = BZNFeed(new_bzn_feed); } //Buy many skinned or regular guns with BZN. This will reserve the amount of guns and allows the new_owner to invoke claimGuns for free function buyWithBZN(address referal, uint8 category, address payable new_owner, uint16 quanity) ensureShopOpen(category) payInBZN(referal, category, new_owner, quanity) public payable returns (bool) { factory.mintFor(new_owner, quanity, category); return true; } //Buy many skinned or regular guns with ETH. This will reserve the amount of guns and allows the new_owner to invoke claimGuns for free function buyWithEther(address referal, uint8 category, address new_owner, uint16 quanity) ensureShopOpen(category) payInETH(referal, category, new_owner, quanity) public payable returns (bool) { factory.mintFor(new_owner, quanity, category); return true; } function convert(uint256 usdValue, bool isBZN) public view returns (uint256) { if (isBZN) { return bznFeed.convert(usdValue); } else { bool temp; bytes32 aaa; (aaa, temp) = ethFeed.peek(); uint256 priceForEtherInUsdWei = uint256(aaa); return usdValue / (priceForEtherInUsdWei / 1e18); } } /** Get the price for skinned or regular guns in USD (wei) */ function priceFor(uint8 category, uint16 quanity) public view returns (uint256, uint256) { require(quanity > 0); uint256 percent = categoryPercentIncrease[category]; uint256 base = categoryPercentBase[category]; uint256 currentPrice = categoryPrice[category]; uint256 nextPrice = currentPrice; uint256 totalPrice = 0; //We can't use exponents because we'll overflow quickly //Only for loop :( for (uint i = 0; i < quanity; i++) { nextPrice = (currentPrice * percent) / base; currentPrice = nextPrice; totalPrice += nextPrice; } //Return the next price, as this is the true price return (nextPrice, totalPrice); } //Determine if a tokenId exists (has been sold) function sold(uint256 _tokenId) public view returns (bool) { return token.exists(_tokenId); } function receiveApproval(address from, uint256 tokenAmount, address tokenContract, bytes memory data) public payable returns (bool) { address referal; uint8 category; uint16 quanity; (referal, category, quanity) = abi.decode(data, (address, uint8, uint16)); require(quanity >= 1); address payable _from = address(uint160(from)); buyWithBZN(referal, category, _from, quanity); return true; } } contract GunFactory is Ownable { using strings for *; uint8 public constant PREMIUM_CATEGORY = 1; uint8 public constant MIDGRADE_CATEGORY = 2; uint8 public constant REGULAR_CATEGORY = 3; uint256 public constant ONE_MONTH = 2628000; uint256 public mintedGuns = 0; address preOrderAddress; GunToken token; mapping(uint8 => uint256) internal gunsMintedByCategory; mapping(uint8 => uint256) internal totalGunsMintedByCategory; mapping(uint8 => uint256) internal firstMonthLimit; mapping(uint8 => uint256) internal secondMonthLimit; mapping(uint8 => uint256) internal thirdMonthLimit; uint256 internal startTime; mapping(uint8 => uint256) internal currentMonthEnd; uint256 internal monthOneEnd; uint256 internal monthTwoEnd; modifier onlyPreOrder { require(msg.sender == preOrderAddress, "Not authorized"); _; } modifier isInitialized { require(preOrderAddress != address(0), "No linked preorder"); require(address(token) != address(0), "No linked token"); _; } constructor() public { firstMonthLimit[PREMIUM_CATEGORY] = 5000; firstMonthLimit[MIDGRADE_CATEGORY] = 20000; firstMonthLimit[REGULAR_CATEGORY] = 30000; secondMonthLimit[PREMIUM_CATEGORY] = 2500; secondMonthLimit[MIDGRADE_CATEGORY] = 10000; secondMonthLimit[REGULAR_CATEGORY] = 15000; thirdMonthLimit[PREMIUM_CATEGORY] = 600; thirdMonthLimit[MIDGRADE_CATEGORY] = 3000; thirdMonthLimit[REGULAR_CATEGORY] = 6000; startTime = block.timestamp; monthOneEnd = startTime + ONE_MONTH; monthTwoEnd = startTime + ONE_MONTH + ONE_MONTH; currentMonthEnd[PREMIUM_CATEGORY] = monthOneEnd; currentMonthEnd[MIDGRADE_CATEGORY] = monthOneEnd; currentMonthEnd[REGULAR_CATEGORY] = monthOneEnd; } function uintToString(uint v) internal pure returns (string memory) { if (v == 0) { return "0"; } uint j = v; uint len; while (j != 0) { len++; j /= 10; } bytes memory bstr = new bytes(len); uint k = len - 1; while (v != 0) { bstr[k--] = byte(uint8(48 + v % 10)); v /= 10; } return string(bstr); } function mintFor(address newOwner, uint16 size, uint8 category) public onlyPreOrder isInitialized returns (uint256) { GunPreOrder preOrder = GunPreOrder(preOrderAddress); require(preOrder.categoryExists(category), "Invalid category"); require(!hasReachedLimit(category), "The monthly limit has been reached"); token.claimAllocation(newOwner, size, category); mintedGuns++; gunsMintedByCategory[category] = gunsMintedByCategory[category] + 1; totalGunsMintedByCategory[category] = totalGunsMintedByCategory[category] + 1; } function hasReachedLimit(uint8 category) internal returns (bool) { uint256 currentTime = block.timestamp; uint256 limit = currentLimit(category); uint256 monthEnd = currentMonthEnd[category]; //If the current block time is greater than or equal to the end of the month if (currentTime >= monthEnd) { //It's a new month, reset all limits //gunsMintedByCategory[PREMIUM_CATEGORY] = 0; //gunsMintedByCategory[MIDGRADE_CATEGORY] = 0; //gunsMintedByCategory[REGULAR_CATEGORY] = 0; gunsMintedByCategory[category] = 0; //Set next month end to be equal one month in advance //do this while the current time is greater than the next month end while (currentTime >= monthEnd) { monthEnd = monthEnd + ONE_MONTH; } //Finally, update the limit limit = currentLimit(category); currentMonthEnd[category] = monthEnd; } //Check if the limit has been reached return gunsMintedByCategory[category] >= limit; } function reachedLimit(uint8 category) public view returns (bool) { uint256 limit = currentLimit(category); return gunsMintedByCategory[category] >= limit; } function currentLimit(uint8 category) public view returns (uint256) { uint256 currentTime = block.timestamp; uint256 limit; if (currentTime < monthOneEnd) { limit = firstMonthLimit[category]; } else if (currentTime < monthTwoEnd) { limit = secondMonthLimit[category]; } else { limit = thirdMonthLimit[category]; } return limit; } function setCategoryLimit(uint8 category, uint256 firstLimit, uint256 secondLimit, uint256 thirdLimit) public onlyOwner { require(firstMonthLimit[category] == 0); require(secondMonthLimit[category] == 0); require(thirdMonthLimit[category] == 0); firstMonthLimit[category] = firstLimit; secondMonthLimit[category] = secondLimit; thirdMonthLimit[category] = thirdLimit; } /** Attach the preOrder that will be receiving tokens being marked for sale by the sellCar function */ function attachPreOrder(address dst) public onlyOwner { //Enforce that address is indeed a preorder GunPreOrder preOrder = GunPreOrder(dst); preOrderAddress = address(preOrder); } /** Attach the token being used for things */ function attachToken(address dst) public onlyOwner { require(address(token) == address(0)); require(dst != address(0)); //Enforce that address is indeed a preorder GunToken ct = GunToken(dst); token = ct; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownedBatchIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"uint256","name":"categoryId","type":"uint256"}],"name":"categoryTypeToId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"batchesOwned","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint16","name":"size","type":"uint16"},{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"startTokenId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"tokenOfOwner","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"categoryIdForToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getBatchIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"migrate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint16","name":"size","type":"uint16"},{"internalType":"uint8","name":"category","type":"uint8"}],"name":"claimAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allTokens","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"categoryForToken","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxAllocation","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"batchIndex","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"batchTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"activate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allBatches","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint16","name":"size","type":"uint16"},{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"uint256","name":"startId","type":"uint256"},{"internalType":"uint256","name":"startTokenId","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getTokensInBatch","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastAllocation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getBatchCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"factoryAddress","type":"address"},{"internalType":"address","name":"oldGunToken","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"batchIndex","type":"uint256"}],"name":"BatchTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"}]
Contract Creation Code
60806040526000600f5560006010553480156200001b57600080fd5b506040516200629a3803806200629a833981810160405260408110156200004157600080fd5b8101908080519060200190929190805190602001909291905050506040518060400160405280600e81526020017f576172205269646572732047756e0000000000000000000000000000000000008152506040518060400160405280600381526020017f5752470000000000000000000000000000000000000000000000000000000000815250620000e06301ffc9a760e01b6200029760201b60201c565b620000f86380ac58cd60e01b6200029760201b60201c565b6200011063780e9d6360e01b6200029760201b60201c565b816009908051906020019062000128929190620003a8565b5080600a908051906020019062000141929190620003a8565b506200015a635b5e139f60e01b6200029760201b60201c565b505060006200016e620003a060201b60201c565b905080600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35081600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505062000457565b63ffffffff60e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141562000334576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4552433136353a20696e76616c696420696e746572666163652069640000000081525060200191505060405180910390fd5b6001600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600033905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003eb57805160ff19168380011785556200041c565b828001600101855582156200041c579182015b828111156200041b578251825591602001919060010190620003fe565b5b5090506200042b91906200042f565b5090565b6200045491905b808211156200045057600081600090555060010162000436565b5090565b90565b615e3380620004676000396000f3fe608060405234801561001057600080fd5b50600436106102315760003560e01c80636ff97f1d11610130578063a51d6be0116100b8578063d3204c0c1161007c578063d3204c0c14610e75578063e985e9c514610f18578063e9a04ce014610f94578063f2fde38b14610fb2578063f8d39a3614610ff657610231565b8063a51d6be014610bb5578063b260c42a14610c03578063b88d4fde14610c31578063bfe6d41714610d36578063c87b56dd14610dce57610231565b80638f32d59b116100ff5780638f32d59b14610a52578063956accf914610a7457806395d89b4114610abc5780639b3ba79f14610b3f578063a22cb46514610b6557610231565b80636ff97f1d1461094757806370a08231146109a6578063715018a6146109fe5780638da5cb5b14610a0857610231565b8063294cdf0d116101be578063454b060811610182578063454b06081461079c5780634f558e79146107de5780634f6ccce714610824578063519861a7146108665780636352211e146108d957610231565b8063294cdf0d146105af5780632a9d74bb146106485780632f745c591461068a57806342842e0e146106ec57806344ec3c071461075a57610231565b806308fff1461161020557806308fff146146103ce578063095ea7b31461041d578063141321621461046b57806318160ddd1461052357806323b872dd1461054157610231565b80622b557d1461023657806301ffc9a71461027857806306fdde03146102dd578063081812fc14610360575b600080fd5b6102626004803603602081101561024c57600080fd5b810190808035906020019092919050505061104e565b6040518082815260200191505060405180910390f35b6102c36004803603602081101561028e57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050611066565b604051808215151515815260200191505060405180910390f35b6102e56110cd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561032557808201518184015260208101905061030a565b50505050905090810190601f1680156103525780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61038c6004803603602081101561037657600080fd5b810190808035906020019092919050505061116f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610407600480360360408110156103e457600080fd5b81019080803560ff1690602001909291908035906020019092919050505061120a565b6040518082815260200191505060405180910390f35b6104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611371565b005b6104b76004803603604081101561048157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611558565b604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018561ffff1661ffff1681526020018460ff1660ff1681526020018381526020018281526020019550505050505060405180910390f35b61052b6115e3565b6040518082815260200191505060405180910390f35b6105ad6004803603606081101561055757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506115ed565b005b6105f1600480360360208110156105c557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061162c565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610634578082015181840152602081019050610619565b505050509050019250505060405180910390f35b6106746004803603602081101561065e57600080fd5b810190808035906020019092919050505061195a565b6040518082815260200191505060405180910390f35b6106d6600480360360408110156106a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611ade565b6040518082815260200191505060405180910390f35b6107586004803603606081101561070257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611b04565b005b6107866004803603602081101561077057600080fd5b8101908080359060200190929190505050611b24565b6040518082815260200191505060405180910390f35b6107c8600480360360208110156107b257600080fd5b8101908080359060200190929190505050611b42565b6040518082815260200191505060405180910390f35b61080a600480360360208110156107f457600080fd5b810190808035906020019092919050505061211f565b604051808215151515815260200191505060405180910390f35b6108506004803603602081101561083a57600080fd5b8101908080359060200190929190505050612273565b6040518082815260200191505060405180910390f35b6108c36004803603606081101561087c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff169060200190929190803560ff169060200190929190505050612297565b6040518082815260200191505060405180910390f35b610905600480360360208110156108ef57600080fd5b8101908080359060200190929190505050612704565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61094f61293e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610992578082015181840152602081019050610977565b505050509050019250505060405180910390f35b6109e8600480360360208110156109bc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612ad5565b6040518082815260200191505060405180910390f35b610a06612bad565b005b610a10612ce8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a5a612d12565b604051808215151515815260200191505060405180910390f35b610aa060048036036020811015610a8a57600080fd5b8101908080359060200190929190505050612d71565b604051808260ff1660ff16815260200191505060405180910390f35b610ac4612ede565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610b04578082015181840152602081019050610ae9565b50505050905090810190601f168015610b315780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610b47612f80565b604051808261ffff1661ffff16815260200191505060405180910390f35b610bb360048036036040811015610b7b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050612f86565b005b610c0160048036036040811015610bcb57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061313e565b005b610c2f60048036036020811015610c1957600080fd5b81019080803590602001909291905050506135b0565b005b610d3460048036036080811015610c4757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610cae57600080fd5b820183602082011115610cc057600080fd5b80359060200191846001830284011164010000000083111715610ce257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061384f565b005b610d6260048036036020811015610d4c57600080fd5b81019080803590602001909291905050506138c7565b604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018561ffff1661ffff1681526020018460ff1660ff1681526020018381526020018281526020019550505050505060405180910390f35b610dfa60048036036020811015610de457600080fd5b8101908080359060200190929190505050613945565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610e3a578082015181840152602081019050610e1f565b50505050905090810190601f168015610e675780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610ec160048036036040811015610e8b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b4c565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610f04578082015181840152602081019050610ee9565b505050509050019250505060405180910390f35b610f7a60048036036040811015610f2e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613d93565b604051808215151515815260200191505060405180910390f35b610f9c613e27565b6040518082815260200191505060405180910390f35b610ff460048036036020811015610fc857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613e2d565b005b6110386004803603602081101561100c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613eb3565b6040518082815260200191505060405180910390f35b60156020528060005260406000206000915090505481565b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b606060098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156111655780601f1061113a57610100808354040283529160200191611165565b820191906000526020600020905b81548152906001019060200180831161114857829003601f168201915b5050505050905090565b600061117a82613eff565b6111cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615cfd602c913960400191505060405180910390fd5b6002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600080600090505b60118054905081101561136557611227615999565b6011828154811061123457fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090508460ff16816040015160ff161461130d5750611358565b6000816020015161ffff1682606001510190508160600151851015801561133357508085105b156113555760008260600151860390508083608001510194505050505061136b565b50505b8080600101915050611212565b50600080fd5b92915050565b600061137c82612704565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611403576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615dad6021913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16611422613f71565b73ffffffffffffffffffffffffffffffffffffffff16148061145157506114508161144b613f71565b613d93565b5b6114a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180615c726038913960400191505060405180910390fd5b826002600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b6014602052816000526040600020818154811061157157fe5b9060005260206000209060030201600091509150508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16908060000160169054906101000a900460ff16908060010154908060020154905085565b6000601754905090565b6013600082815260200190815260200160002060009054906101000a900460ff1661161c5761161b816135b0565b5b611627838383613f79565b505050565b60608061163883612ad5565b6040519080825280602002602001820160405280156116665781602001602082028038833980820191505090505b509050600080905060008090505b601460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490508110156118a1576116c6615999565b601460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811061171057fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090506000816020015161ffff1682608001510190506000826080015190505b81811015611891576013600082815260200190815260200160002060009054906101000a900460ff16801561185857508773ffffffffffffffffffffffffffffffffffffffff1661183f82613fef565b73ffffffffffffffffffffffffffffffffffffffff1614155b1561186257611884565b8086868151811061186f57fe5b60200260200101818152505084806001019550505b80806001019150506117ef565b5050508080600101915050611674565b5060606118ad856140b7565b8054806020026020016040519081016040528092919081815260200182805480156118f757602002820191906000526020600020905b8154815260200190600101908083116118e3575b5050505050905060008090505b815181101561194e5781818151811061191957fe5b602002602001015184848151811061192d57fe5b60200260200101818152505082806001019350508080600101915050611904565b50829350505050919050565b60008061196683611b24565b905060118054905081106119e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e20626174636820646f65736e27742065786973740000000000000081525060200191505060405180910390fd5b6119ea615999565b601182815481106119f757fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050905060008160600151610fa061ffff168681611acf57fe5b06019050809350505050919050565b6000611ae98361162c565b8281518110611af457fe5b6020026020010151905092915050565b611b1f8383836040518060200160405280600081525061384f565b505050565b600080610fa061ffff168381611b3657fe5b04905080915050919050565b6000611b4c612d12565b611bbe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008090505b8381101561210357600081600f5401905060008060008060008773ffffffffffffffffffffffffffffffffffffffff1663bfe6d417876040518263ffffffff1660e01b81526004018082815260200191505060a06040518083038186803b158015611c5557600080fd5b505afa158015611c69573d6000803e3d6000fd5b505050506040513d60a0811015611c7f57600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291905050509450945094509450945060116040518060a001604052808773ffffffffffffffffffffffffffffffffffffffff1681526020018661ffff1681526020018560ff168152602001848152602001838152509080600181540180825580915050906001820390600052602060002090600302016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548160ff021916908360ff160217905550606082015181600101556080820151816002015550505060008461ffff1660105401905060008561ffff169050600060105490505b82811015611f6d5760008b73ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015611e4e57600080fd5b505afa158015611e62573d6000803e3d6000fd5b505050506040513d6020811015611e7857600080fd5b810190808051906020019092919050505090508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611f025760016013600084815260200190815260200160002060006101000a81548160ff021916908315150217905550611ef481836140ff565b828060019003935050611f5f565b818973ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b508080600101915050611df3565b50610fa061ffff1660106000828254019250508190555080601260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508561ffff16601660008760ff1660ff168152602001908152602001600020600082825401925050819055506120da8760116001601180549050038154811061201557fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050614262565b8561ffff1660176000828254019250508190555050505050505050508080600101915050611beb565b5082600f60008282540192505081905550601054915050919050565b60006013600083815260200190815260200160002060009054906101000a900460ff16156121575761215082613eff565b905061226e565b600061216283611b24565b905060118054905081101561226857612179615999565b6011828154811061218657fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090506000816020015161ffff168260800151019050808510935050505061226e565b60009150505b919050565b600061227d61293e565b828151811061228857fe5b60200260200101519050919050565b6000600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461235c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4e6f7420617574686f72697a656400000000000000000000000000000000000081525060200191505060405180910390fd5b610fa061ffff168361ffff16106123be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180615b826027913960400191505060405180910390fd5b60116040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018561ffff1681526020018460ff168152602001601660008660ff1660ff1681526020019081526020016000205481526020016010548152509080600181540180825580915050906001820390600052602060002090600302016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548160ff021916908360ff160217905550606082015181600101556080820151816002015550505060008361ffff16601054019050600060105490505b8181101561257257808673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a48080600101915050612501565b50610fa061ffff166010600082825401925050819055508361ffff16601260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508361ffff16601660008560ff1660ff168152602001908152602001600020600082825401925050819055506126e38560116001601180549050038154811061261e57fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050614262565b8361ffff166017600082825401925050819055506010549150509392505050565b600061270f8261211f565b612781576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e20646f65736e27742065786973742100000000000000000000000081525060200191505060405180910390fd5b6013600083815260200190815260200160002060009054906101000a900460ff16156127b7576127b082613fef565b9050612939565b60006127c283611b24565b9050601180549050811061283e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e20626174636820646f65736e27742065786973740000000000000081525060200191505060405180910390fd5b612846615999565b6011828154811061285357fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff168152602001600182015481526020016002820154815250509050806020015161ffff16816080015101841061292f57600080fd5b8060000151925050505b919050565b6060806129496115e3565b6040519080825280602002602001820160405280156129775781602001602082028038833980820191505090505b509050600080905060008090505b601180549050811015612acc5761299a615999565b601182815481106129a757fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090506000816020015161ffff1682608001510190506000826080015190505b81811015612abc5780868681518110612a9b57fe5b60200260200101818152505084806001019550508080600101915050612a86565b5050508080600101915050612985565b50819250505090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615caa602a913960400191505060405180910390fd5b601260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612ba5836143df565b019050919050565b612bb5612d12565b612c27576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d55613f71565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600080612d7d83611b24565b90506011805490508110612df9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e20626174636820646f65736e27742065786973740000000000000081525060200191505060405180910390fd5b612e01615999565b60118281548110612e0e57fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff168152602001600182015481526020016002820154815250509050806040015192505050919050565b6060600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612f765780601f10612f4b57610100808354040283529160200191612f76565b820191906000526020600020905b815481529060010190602001808311612f5957829003601f168201915b5050505050905090565b610fa081565b612f8e613f71565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561302f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4552433732313a20617070726f766520746f2063616c6c65720000000000000081525060200191505060405180910390fd5b806004600061303c613f71565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166130e9613f71565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051808215151515815260200191505060405180910390a35050565b60006011838154811061314d57fe5b9060005260206000209060030201905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146131e257600080fd5b61329e81836040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff168152602001600182015481526020016002820154815250506144b4565b828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061339d83836040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050614262565b838373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fc42fa155158786a1dd6ccc3a785f35845467353c3cc700e0e31a79f90e22227d60405160405180910390a460008260000160149054906101000a900461ffff1661ffff16836002015401905060008090506000846002015490505b8281101561350d576013600082815260200190815260200160002060009054906101000a900460ff161561349b578373ffffffffffffffffffffffffffffffffffffffff1661347682612704565b73ffffffffffffffffffffffffffffffffffffffff161461349657613500565b6134a4565b81806001019250505b808673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b8080600101915050613428565b5080601260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555080601260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550505050505050565b6013600082815260200190815260200160002060009054906101000a900460ff1615613644576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f546f6b656e20616c72656164792061637469766174656400000000000000000081525060200191505060405180910390fd5b600061364f82611b24565b905060118054905081106136cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e20626174636820646f65736e27742065786973740000000000000081525060200191505060405180910390fd5b6136d3615999565b601182815481106136e057fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff168152602001600182015481526020016002820154815250509050806020015161ffff1681608001510183106137bc57600080fd5b60016013600085815260200190815260200160002060006101000a81548160ff0219169083151502179055506137f68160000151846140ff565b60126000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600190039190505550505050565b61386061385a613f71565b836147d3565b6138b5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180615dce6031913960400191505060405180910390fd5b6138c1848484846148c7565b50505050565b601181815481106138d457fe5b90600052602060002090600302016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16908060000160169054906101000a900460ff16908060010154908060020154905085565b60606139508261211f565b6139c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e20646f65736e27742065786973742100000000000000000000000081525060200191505060405180910390fd5b6013600083815260200190815260200160002060009054906101000a900460ff16156139f8576139f182614939565b9050613b47565b6000613a0383612d71565b90506000613a108461195a565b90506060613af8613a7f613a7a613a5b6040518060400160405280600581526020017f2e6a736f6e000000000000000000000000000000000000000000000000000000815250614a4c565b613a6c613a6787614a7a565b614a4c565b614ba790919063ffffffff16565b614a4c565b613aea613ae5613ac36040518060400160405280600181526020017f2f00000000000000000000000000000000000000000000000000000000000000815250614a4c565b613ad7613ad28960ff16614a7a565b614a4c565b614ba790919063ffffffff16565b614a4c565b614ba790919063ffffffff16565b90506060604051806060016040528060218152602001615c016021913990506060613b3c613b2584614a4c565b613b2e84614a4c565b614ba790919063ffffffff16565b905080955050505050505b919050565b6060613b56615999565b601460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613ba057fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090506060816020015161ffff16604051908082528060200260200182016040528015613c9b5781602001602082028038833980820191505090505b50905060008090506000836020015161ffff1684608001510190506000846080015190505b81811015613d62576013600082815260200190815260200160002060009054906101000a900460ff168015613d2957508773ffffffffffffffffffffffffffffffffffffffff16613d1082613fef565b73ffffffffffffffffffffffffffffffffffffffff1614155b15613d3357613d55565b80848481518110613d4057fe5b60200260200101818152505082806001019350505b8080600101915050613cc0565b5060008211613d7057600080fd5b600082856020015161ffff16039050808451038452839550505050505092915050565b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60105481565b613e35612d12565b613ea7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b613eb081614c29565b50565b6000601460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b6000806001600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b600033905090565b613f8a613f84613f71565b826147d3565b613fdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180615dce6031913960400191505060405180910390fd5b613fea838383614d6f565b505050565b6000806001600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156140ae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615cd46029913960400191505060405180910390fd5b80915050919050565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050919050565b600061410a82612d71565b905060006141178361195a565b905060606141ff6141866141816141626040518060400160405280600581526020017f2e6a736f6e000000000000000000000000000000000000000000000000000000815250614a4c565b61417361416e87614a7a565b614a4c565b614ba790919063ffffffff16565b614a4c565b6141f16141ec6141ca6040518060400160405280600181526020017f2f00000000000000000000000000000000000000000000000000000000000000815250614a4c565b6141de6141d98960ff16614a7a565b614a4c565b614ba790919063ffffffff16565b614a4c565b614ba790919063ffffffff16565b90506060604051806060016040528060218152602001615c01602191399050606061424361422c84614a4c565b61423584614a4c565b614ba790919063ffffffff16565b905061424f8787614d93565b6142598682614db4565b50505050505050565b60006142718260800151611b24565b9050601460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506015600083815260200190815260200160002081905550601460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020829080600181540180825580915050906001820390600052602060002090600302016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548160ff021916908360ff1602179055506060820151816001015560808201518160020155505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415614466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615caa602a913960400191505060405180910390fd5b6144ad600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020614e3e565b9050919050565b60006144c38260800151611b24565b9050600061451d6001601460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050614e4c90919063ffffffff16565b905060006015600084815260200190815260200160002054905081811461477957614546615999565b601460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811061459057fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050905060006146618260800151611b24565b905081601460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481106146ae57fe5b906000526020600020906003020160008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548160ff021916908360ff160217905550606082015181600101556080820151816002015590505082601560008381526020019081526020016000208190555050505b601460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054809190600190036147cb91906159e5565b505050505050565b60006147de82613eff565b614833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615c46602c913960400191505060405180910390fd5b600061483e83612704565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806148ad57508373ffffffffffffffffffffffffffffffffffffffff166148958461116f565b73ffffffffffffffffffffffffffffffffffffffff16145b806148be57506148bd8185613d93565b5b91505092915050565b6148d2848484614d6f565b6148de84848484614e96565b614933576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180615ba96032913960400191505060405180910390fd5b50505050565b606061494482613eff565b614999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615d7e602f913960400191505060405180910390fd5b600b60008381526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015614a405780601f10614a1557610100808354040283529160200191614a40565b820191906000526020600020905b815481529060010190602001808311614a2357829003601f168201915b50505050509050919050565b614a54615a17565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606000821415614ac2576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050614ba2565b600082905060005b60008214614aec578080600101915050600a8281614ae457fe5b049150614aca565b6060816040519080825280601f01601f191660200182016040528015614b215781602001600182028038833980820191505090505b50905060006001830390505b60008614614b9a57600a8681614b3f57fe5b0660300160f81b82828060019003935081518110614b5957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8681614b9257fe5b049550614b2d565b819450505050505b919050565b60608082600001518460000151016040519080825280601f01601f191660200182016040528015614be75781602001600182028038833980820191505090505b5090506000602082019050614c058186602001518760000151615086565b614c1e8560000151820185602001518660000151615086565b819250505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615bdb6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b614d7a8383836150cf565b614d84838261532a565b614d8e82826154c8565b505050565b614d9d828261558f565b614da782826154c8565b614db08161574b565b5050565b614dbd82613eff565b614e12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615d29602c913960400191505060405180910390fd5b80600b60008481526020019081526020016000209080519060200190614e39929190615a31565b505050565b600081600001549050919050565b6000614e8e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615797565b905092915050565b6000614eb78473ffffffffffffffffffffffffffffffffffffffff16615857565b614ec4576001905061507e565b60008473ffffffffffffffffffffffffffffffffffffffff1663150b7a02614eea613f71565b8887876040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614fa6578082015181840152602081019050614f8b565b50505050905090810190601f168015614fd35780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614ff557600080fd5b505af1158015615009573d6000803e3d6000fd5b505050506040513d602081101561501f57600080fd5b8101908080519060200190929190505050905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150505b949350505050565b5b602081106150aa5781518352602083019250602082019150602081039050615087565b60006001826020036101000a0390508019835116818551168181178652505050505050565b8273ffffffffffffffffffffffffffffffffffffffff166150ef82612704565b73ffffffffffffffffffffffffffffffffffffffff161461515b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615d556029913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156151e1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615c226024913960400191505060405180910390fd5b6151ea816158a2565b615231600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615960565b615278600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615983565b816001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60006153826001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050614e4c90919063ffffffff16565b905060006006600084815260200190815260200160002054905081811461546f576000600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481106153ef57fe5b9060005260206000200154905080600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811061544757fe5b9060005260206000200181905550816006600083815260200190815260200160002081905550505b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054809190600190036154c19190615ab1565b5050505050565b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506006600083815260200190815260200160002081905550600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190915055505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415615632576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4552433732313a206d696e7420746f20746865207a65726f206164647265737381525060200191505060405180910390fd5b61563b81613eff565b156156ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000081525060200191505060405180910390fd5b816001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550615747600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615983565b5050565b6007805490506008600083815260200190815260200160002081905550600781908060018154018082558091505090600182039060005260206000200160009091929091909150555050565b6000838311158290615844576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156158095780820151818401526020810190506157ee565b50505050905090810190601f1680156158365780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f91506000801b82141580156158995750808214155b92505050919050565b600073ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461595d5760006002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b61597860018260000154614e4c90919063ffffffff16565b816000018190555050565b6001816000016000828254019250508190555050565b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600061ffff168152602001600060ff16815260200160008152602001600081525090565b815481835581811115615a1257600302816003028360005260206000209182019101615a119190615add565b5b505050565b604051806040016040528060008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615a7257805160ff1916838001178555615aa0565b82800160010185558215615aa0579182015b82811115615a9f578251825591602001919060010190615a84565b5b509050615aad9190615b5c565b5090565b815481835581811115615ad857818360005260206000209182019101615ad79190615b5c565b5b505050565b615b5991905b80821115615b5557600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549061ffff02191690556000820160166101000a81549060ff02191690556001820160009055600282016000905550600301615ae3565b5090565b90565b615b7e91905b80821115615b7a576000816000905550600101615b62565b5090565b9056fe53697a65206d75737420626520736d616c6c6572207468616e206d6178416c6c6f636174696f6e4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737368747470733a2f2f7661756c742e7761727269646572732e636f6d2f67756e732f4552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732314d657461646174613a2055524920736574206f66206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a265627a7a72315820876931c215f7956d3a852fd29294df62b37bd1b5c267f0ba3dfa8814f2f4f2e064736f6c634300050b003200000000000000000000000062d981aea59c6c768dff55ffb7f745cb79eeaa3600000000000000000000000018f64687e77c012d062bce0396fbbf7f21e11b77
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102315760003560e01c80636ff97f1d11610130578063a51d6be0116100b8578063d3204c0c1161007c578063d3204c0c14610e75578063e985e9c514610f18578063e9a04ce014610f94578063f2fde38b14610fb2578063f8d39a3614610ff657610231565b8063a51d6be014610bb5578063b260c42a14610c03578063b88d4fde14610c31578063bfe6d41714610d36578063c87b56dd14610dce57610231565b80638f32d59b116100ff5780638f32d59b14610a52578063956accf914610a7457806395d89b4114610abc5780639b3ba79f14610b3f578063a22cb46514610b6557610231565b80636ff97f1d1461094757806370a08231146109a6578063715018a6146109fe5780638da5cb5b14610a0857610231565b8063294cdf0d116101be578063454b060811610182578063454b06081461079c5780634f558e79146107de5780634f6ccce714610824578063519861a7146108665780636352211e146108d957610231565b8063294cdf0d146105af5780632a9d74bb146106485780632f745c591461068a57806342842e0e146106ec57806344ec3c071461075a57610231565b806308fff1461161020557806308fff146146103ce578063095ea7b31461041d578063141321621461046b57806318160ddd1461052357806323b872dd1461054157610231565b80622b557d1461023657806301ffc9a71461027857806306fdde03146102dd578063081812fc14610360575b600080fd5b6102626004803603602081101561024c57600080fd5b810190808035906020019092919050505061104e565b6040518082815260200191505060405180910390f35b6102c36004803603602081101561028e57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050611066565b604051808215151515815260200191505060405180910390f35b6102e56110cd565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561032557808201518184015260208101905061030a565b50505050905090810190601f1680156103525780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61038c6004803603602081101561037657600080fd5b810190808035906020019092919050505061116f565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610407600480360360408110156103e457600080fd5b81019080803560ff1690602001909291908035906020019092919050505061120a565b6040518082815260200191505060405180910390f35b6104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611371565b005b6104b76004803603604081101561048157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611558565b604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018561ffff1661ffff1681526020018460ff1660ff1681526020018381526020018281526020019550505050505060405180910390f35b61052b6115e3565b6040518082815260200191505060405180910390f35b6105ad6004803603606081101561055757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506115ed565b005b6105f1600480360360208110156105c557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061162c565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610634578082015181840152602081019050610619565b505050509050019250505060405180910390f35b6106746004803603602081101561065e57600080fd5b810190808035906020019092919050505061195a565b6040518082815260200191505060405180910390f35b6106d6600480360360408110156106a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611ade565b6040518082815260200191505060405180910390f35b6107586004803603606081101561070257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611b04565b005b6107866004803603602081101561077057600080fd5b8101908080359060200190929190505050611b24565b6040518082815260200191505060405180910390f35b6107c8600480360360208110156107b257600080fd5b8101908080359060200190929190505050611b42565b6040518082815260200191505060405180910390f35b61080a600480360360208110156107f457600080fd5b810190808035906020019092919050505061211f565b604051808215151515815260200191505060405180910390f35b6108506004803603602081101561083a57600080fd5b8101908080359060200190929190505050612273565b6040518082815260200191505060405180910390f35b6108c36004803603606081101561087c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff169060200190929190803560ff169060200190929190505050612297565b6040518082815260200191505060405180910390f35b610905600480360360208110156108ef57600080fd5b8101908080359060200190929190505050612704565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61094f61293e565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610992578082015181840152602081019050610977565b505050509050019250505060405180910390f35b6109e8600480360360208110156109bc57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612ad5565b6040518082815260200191505060405180910390f35b610a06612bad565b005b610a10612ce8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610a5a612d12565b604051808215151515815260200191505060405180910390f35b610aa060048036036020811015610a8a57600080fd5b8101908080359060200190929190505050612d71565b604051808260ff1660ff16815260200191505060405180910390f35b610ac4612ede565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610b04578082015181840152602081019050610ae9565b50505050905090810190601f168015610b315780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610b47612f80565b604051808261ffff1661ffff16815260200191505060405180910390f35b610bb360048036036040811015610b7b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050612f86565b005b610c0160048036036040811015610bcb57600080fd5b8101908080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061313e565b005b610c2f60048036036020811015610c1957600080fd5b81019080803590602001909291905050506135b0565b005b610d3460048036036080811015610c4757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610cae57600080fd5b820183602082011115610cc057600080fd5b80359060200191846001830284011164010000000083111715610ce257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061384f565b005b610d6260048036036020811015610d4c57600080fd5b81019080803590602001909291905050506138c7565b604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018561ffff1661ffff1681526020018460ff1660ff1681526020018381526020018281526020019550505050505060405180910390f35b610dfa60048036036020811015610de457600080fd5b8101908080359060200190929190505050613945565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610e3a578082015181840152602081019050610e1f565b50505050905090810190601f168015610e675780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610ec160048036036040811015610e8b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050613b4c565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610f04578082015181840152602081019050610ee9565b505050509050019250505060405180910390f35b610f7a60048036036040811015610f2e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613d93565b604051808215151515815260200191505060405180910390f35b610f9c613e27565b6040518082815260200191505060405180910390f35b610ff460048036036020811015610fc857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613e2d565b005b6110386004803603602081101561100c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050613eb3565b6040518082815260200191505060405180910390f35b60156020528060005260406000206000915090505481565b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b606060098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156111655780601f1061113a57610100808354040283529160200191611165565b820191906000526020600020905b81548152906001019060200180831161114857829003601f168201915b5050505050905090565b600061117a82613eff565b6111cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615cfd602c913960400191505060405180910390fd5b6002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600080600090505b60118054905081101561136557611227615999565b6011828154811061123457fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090508460ff16816040015160ff161461130d5750611358565b6000816020015161ffff1682606001510190508160600151851015801561133357508085105b156113555760008260600151860390508083608001510194505050505061136b565b50505b8080600101915050611212565b50600080fd5b92915050565b600061137c82612704565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611403576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180615dad6021913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16611422613f71565b73ffffffffffffffffffffffffffffffffffffffff16148061145157506114508161144b613f71565b613d93565b5b6114a6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180615c726038913960400191505060405180910390fd5b826002600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550818373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a4505050565b6014602052816000526040600020818154811061157157fe5b9060005260206000209060030201600091509150508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16908060000160169054906101000a900460ff16908060010154908060020154905085565b6000601754905090565b6013600082815260200190815260200160002060009054906101000a900460ff1661161c5761161b816135b0565b5b611627838383613f79565b505050565b60608061163883612ad5565b6040519080825280602002602001820160405280156116665781602001602082028038833980820191505090505b509050600080905060008090505b601460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490508110156118a1576116c6615999565b601460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020828154811061171057fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090506000816020015161ffff1682608001510190506000826080015190505b81811015611891576013600082815260200190815260200160002060009054906101000a900460ff16801561185857508773ffffffffffffffffffffffffffffffffffffffff1661183f82613fef565b73ffffffffffffffffffffffffffffffffffffffff1614155b1561186257611884565b8086868151811061186f57fe5b60200260200101818152505084806001019550505b80806001019150506117ef565b5050508080600101915050611674565b5060606118ad856140b7565b8054806020026020016040519081016040528092919081815260200182805480156118f757602002820191906000526020600020905b8154815260200190600101908083116118e3575b5050505050905060008090505b815181101561194e5781818151811061191957fe5b602002602001015184848151811061192d57fe5b60200260200101818152505082806001019350508080600101915050611904565b50829350505050919050565b60008061196683611b24565b905060118054905081106119e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e20626174636820646f65736e27742065786973740000000000000081525060200191505060405180910390fd5b6119ea615999565b601182815481106119f757fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050905060008160600151610fa061ffff168681611acf57fe5b06019050809350505050919050565b6000611ae98361162c565b8281518110611af457fe5b6020026020010151905092915050565b611b1f8383836040518060200160405280600081525061384f565b505050565b600080610fa061ffff168381611b3657fe5b04905080915050919050565b6000611b4c612d12565b611bbe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008090505b8381101561210357600081600f5401905060008060008060008773ffffffffffffffffffffffffffffffffffffffff1663bfe6d417876040518263ffffffff1660e01b81526004018082815260200191505060a06040518083038186803b158015611c5557600080fd5b505afa158015611c69573d6000803e3d6000fd5b505050506040513d60a0811015611c7f57600080fd5b8101908080519060200190929190805190602001909291908051906020019092919080519060200190929190805190602001909291905050509450945094509450945060116040518060a001604052808773ffffffffffffffffffffffffffffffffffffffff1681526020018661ffff1681526020018560ff168152602001848152602001838152509080600181540180825580915050906001820390600052602060002090600302016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548160ff021916908360ff160217905550606082015181600101556080820151816002015550505060008461ffff1660105401905060008561ffff169050600060105490505b82811015611f6d5760008b73ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015611e4e57600080fd5b505afa158015611e62573d6000803e3d6000fd5b505050506040513d6020811015611e7857600080fd5b810190808051906020019092919050505090508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611f025760016013600084815260200190815260200160002060006101000a81548160ff021916908315150217905550611ef481836140ff565b828060019003935050611f5f565b818973ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b508080600101915050611df3565b50610fa061ffff1660106000828254019250508190555080601260008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508561ffff16601660008760ff1660ff168152602001908152602001600020600082825401925050819055506120da8760116001601180549050038154811061201557fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050614262565b8561ffff1660176000828254019250508190555050505050505050508080600101915050611beb565b5082600f60008282540192505081905550601054915050919050565b60006013600083815260200190815260200160002060009054906101000a900460ff16156121575761215082613eff565b905061226e565b600061216283611b24565b905060118054905081101561226857612179615999565b6011828154811061218657fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090506000816020015161ffff168260800151019050808510935050505061226e565b60009150505b919050565b600061227d61293e565b828151811061228857fe5b60200260200101519050919050565b6000600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461235c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600e8152602001807f4e6f7420617574686f72697a656400000000000000000000000000000000000081525060200191505060405180910390fd5b610fa061ffff168361ffff16106123be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526027815260200180615b826027913960400191505060405180910390fd5b60116040518060a001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018561ffff1681526020018460ff168152602001601660008660ff1660ff1681526020019081526020016000205481526020016010548152509080600181540180825580915050906001820390600052602060002090600302016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548160ff021916908360ff160217905550606082015181600101556080820151816002015550505060008361ffff16601054019050600060105490505b8181101561257257808673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a48080600101915050612501565b50610fa061ffff166010600082825401925050819055508361ffff16601260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508361ffff16601660008560ff1660ff168152602001908152602001600020600082825401925050819055506126e38560116001601180549050038154811061261e57fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050614262565b8361ffff166017600082825401925050819055506010549150509392505050565b600061270f8261211f565b612781576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e20646f65736e27742065786973742100000000000000000000000081525060200191505060405180910390fd5b6013600083815260200190815260200160002060009054906101000a900460ff16156127b7576127b082613fef565b9050612939565b60006127c283611b24565b9050601180549050811061283e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e20626174636820646f65736e27742065786973740000000000000081525060200191505060405180910390fd5b612846615999565b6011828154811061285357fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff168152602001600182015481526020016002820154815250509050806020015161ffff16816080015101841061292f57600080fd5b8060000151925050505b919050565b6060806129496115e3565b6040519080825280602002602001820160405280156129775781602001602082028038833980820191505090505b509050600080905060008090505b601180549050811015612acc5761299a615999565b601182815481106129a757fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090506000816020015161ffff1682608001510190506000826080015190505b81811015612abc5780868681518110612a9b57fe5b60200260200101818152505084806001019550508080600101915050612a86565b5050508080600101915050612985565b50819250505090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612b5c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615caa602a913960400191505060405180910390fd5b601260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054612ba5836143df565b019050919050565b612bb5612d12565b612c27576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d55613f71565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b600080612d7d83611b24565b90506011805490508110612df9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e20626174636820646f65736e27742065786973740000000000000081525060200191505060405180910390fd5b612e01615999565b60118281548110612e0e57fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff168152602001600182015481526020016002820154815250509050806040015192505050919050565b6060600a8054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015612f765780601f10612f4b57610100808354040283529160200191612f76565b820191906000526020600020905b815481529060010190602001808311612f5957829003601f168201915b5050505050905090565b610fa081565b612f8e613f71565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141561302f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4552433732313a20617070726f766520746f2063616c6c65720000000000000081525060200191505060405180910390fd5b806004600061303c613f71565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff166130e9613f71565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051808215151515815260200191505060405180910390a35050565b60006011838154811061314d57fe5b9060005260206000209060030201905060008160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690503373ffffffffffffffffffffffffffffffffffffffff168260000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146131e257600080fd5b61329e81836040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff168152602001600182015481526020016002820154815250506144b4565b828260000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061339d83836040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050614262565b838373ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fc42fa155158786a1dd6ccc3a785f35845467353c3cc700e0e31a79f90e22227d60405160405180910390a460008260000160149054906101000a900461ffff1661ffff16836002015401905060008090506000846002015490505b8281101561350d576013600082815260200190815260200160002060009054906101000a900460ff161561349b578373ffffffffffffffffffffffffffffffffffffffff1661347682612704565b73ffffffffffffffffffffffffffffffffffffffff161461349657613500565b6134a4565b81806001019250505b808673ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45b8080600101915050613428565b5080601260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555080601260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540392505081905550505050505050565b6013600082815260200190815260200160002060009054906101000a900460ff1615613644576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f546f6b656e20616c72656164792061637469766174656400000000000000000081525060200191505060405180910390fd5b600061364f82611b24565b905060118054905081106136cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f546f6b656e20626174636820646f65736e27742065786973740000000000000081525060200191505060405180910390fd5b6136d3615999565b601182815481106136e057fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff168152602001600182015481526020016002820154815250509050806020015161ffff1681608001510183106137bc57600080fd5b60016013600085815260200190815260200160002060006101000a81548160ff0219169083151502179055506137f68160000151846140ff565b60126000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000815480929190600190039190505550505050565b61386061385a613f71565b836147d3565b6138b5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180615dce6031913960400191505060405180910390fd5b6138c1848484846148c7565b50505050565b601181815481106138d457fe5b90600052602060002090600302016000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900461ffff16908060000160169054906101000a900460ff16908060010154908060020154905085565b60606139508261211f565b6139c2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e20646f65736e27742065786973742100000000000000000000000081525060200191505060405180910390fd5b6013600083815260200190815260200160002060009054906101000a900460ff16156139f8576139f182614939565b9050613b47565b6000613a0383612d71565b90506000613a108461195a565b90506060613af8613a7f613a7a613a5b6040518060400160405280600581526020017f2e6a736f6e000000000000000000000000000000000000000000000000000000815250614a4c565b613a6c613a6787614a7a565b614a4c565b614ba790919063ffffffff16565b614a4c565b613aea613ae5613ac36040518060400160405280600181526020017f2f00000000000000000000000000000000000000000000000000000000000000815250614a4c565b613ad7613ad28960ff16614a7a565b614a4c565b614ba790919063ffffffff16565b614a4c565b614ba790919063ffffffff16565b90506060604051806060016040528060218152602001615c016021913990506060613b3c613b2584614a4c565b613b2e84614a4c565b614ba790919063ffffffff16565b905080955050505050505b919050565b6060613b56615999565b601460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208381548110613ba057fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff1681526020016001820154815260200160028201548152505090506060816020015161ffff16604051908082528060200260200182016040528015613c9b5781602001602082028038833980820191505090505b50905060008090506000836020015161ffff1684608001510190506000846080015190505b81811015613d62576013600082815260200190815260200160002060009054906101000a900460ff168015613d2957508773ffffffffffffffffffffffffffffffffffffffff16613d1082613fef565b73ffffffffffffffffffffffffffffffffffffffff1614155b15613d3357613d55565b80848481518110613d4057fe5b60200260200101818152505082806001019350505b8080600101915050613cc0565b5060008211613d7057600080fd5b600082856020015161ffff16039050808451038452839550505050505092915050565b6000600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60105481565b613e35612d12565b613ea7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b613eb081614c29565b50565b6000601460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490509050919050565b6000806001600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415915050919050565b600033905090565b613f8a613f84613f71565b826147d3565b613fdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526031815260200180615dce6031913960400191505060405180910390fd5b613fea838383614d6f565b505050565b6000806001600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156140ae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615cd46029913960400191505060405180910390fd5b80915050919050565b6000600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050919050565b600061410a82612d71565b905060006141178361195a565b905060606141ff6141866141816141626040518060400160405280600581526020017f2e6a736f6e000000000000000000000000000000000000000000000000000000815250614a4c565b61417361416e87614a7a565b614a4c565b614ba790919063ffffffff16565b614a4c565b6141f16141ec6141ca6040518060400160405280600181526020017f2f00000000000000000000000000000000000000000000000000000000000000815250614a4c565b6141de6141d98960ff16614a7a565b614a4c565b614ba790919063ffffffff16565b614a4c565b614ba790919063ffffffff16565b90506060604051806060016040528060218152602001615c01602191399050606061424361422c84614a4c565b61423584614a4c565b614ba790919063ffffffff16565b905061424f8787614d93565b6142598682614db4565b50505050505050565b60006142718260800151611b24565b9050601460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506015600083815260200190815260200160002081905550601460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020829080600181540180825580915050906001820390600052602060002090600302016000909192909190915060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548160ff021916908360ff1602179055506060820151816001015560808201518160020155505050505050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415614466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180615caa602a913960400191505060405180910390fd5b6144ad600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020614e3e565b9050919050565b60006144c38260800151611b24565b9050600061451d6001601460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050614e4c90919063ffffffff16565b905060006015600084815260200190815260200160002054905081811461477957614546615999565b601460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811061459057fe5b90600052602060002090600302016040518060a00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900461ffff1661ffff1661ffff1681526020016000820160169054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282015481525050905060006146618260800151611b24565b905081601460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002084815481106146ae57fe5b906000526020600020906003020160008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548161ffff021916908361ffff16021790555060408201518160000160166101000a81548160ff021916908360ff160217905550606082015181600101556080820151816002015590505082601560008381526020019081526020016000208190555050505b601460008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054809190600190036147cb91906159e5565b505050505050565b60006147de82613eff565b614833576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615c46602c913960400191505060405180910390fd5b600061483e83612704565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614806148ad57508373ffffffffffffffffffffffffffffffffffffffff166148958461116f565b73ffffffffffffffffffffffffffffffffffffffff16145b806148be57506148bd8185613d93565b5b91505092915050565b6148d2848484614d6f565b6148de84848484614e96565b614933576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180615ba96032913960400191505060405180910390fd5b50505050565b606061494482613eff565b614999576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f815260200180615d7e602f913960400191505060405180910390fd5b600b60008381526020019081526020016000208054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015614a405780601f10614a1557610100808354040283529160200191614a40565b820191906000526020600020905b815481529060010190602001808311614a2357829003601f168201915b50505050509050919050565b614a54615a17565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606000821415614ac2576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050614ba2565b600082905060005b60008214614aec578080600101915050600a8281614ae457fe5b049150614aca565b6060816040519080825280601f01601f191660200182016040528015614b215781602001600182028038833980820191505090505b50905060006001830390505b60008614614b9a57600a8681614b3f57fe5b0660300160f81b82828060019003935081518110614b5957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8681614b9257fe5b049550614b2d565b819450505050505b919050565b60608082600001518460000151016040519080825280601f01601f191660200182016040528015614be75781602001600182028038833980820191505090505b5090506000602082019050614c058186602001518760000151615086565b614c1e8560000151820185602001518660000151615086565b819250505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415614caf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180615bdb6026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b614d7a8383836150cf565b614d84838261532a565b614d8e82826154c8565b505050565b614d9d828261558f565b614da782826154c8565b614db08161574b565b5050565b614dbd82613eff565b614e12576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180615d29602c913960400191505060405180910390fd5b80600b60008481526020019081526020016000209080519060200190614e39929190615a31565b505050565b600081600001549050919050565b6000614e8e83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615797565b905092915050565b6000614eb78473ffffffffffffffffffffffffffffffffffffffff16615857565b614ec4576001905061507e565b60008473ffffffffffffffffffffffffffffffffffffffff1663150b7a02614eea613f71565b8887876040518563ffffffff1660e01b8152600401808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b83811015614fa6578082015181840152602081019050614f8b565b50505050905090810190601f168015614fd35780820380516001836020036101000a031916815260200191505b5095505050505050602060405180830381600087803b158015614ff557600080fd5b505af1158015615009573d6000803e3d6000fd5b505050506040513d602081101561501f57600080fd5b8101908080519060200190929190505050905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150505b949350505050565b5b602081106150aa5781518352602083019250602082019150602081039050615087565b60006001826020036101000a0390508019835116818551168181178652505050505050565b8273ffffffffffffffffffffffffffffffffffffffff166150ef82612704565b73ffffffffffffffffffffffffffffffffffffffff161461515b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180615d556029913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156151e1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180615c226024913960400191505060405180910390fd5b6151ea816158a2565b615231600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615960565b615278600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615983565b816001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b60006153826001600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002080549050614e4c90919063ffffffff16565b905060006006600084815260200190815260200160002054905081811461546f576000600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002083815481106153ef57fe5b9060005260206000200154905080600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020838154811061544757fe5b9060005260206000200181905550816006600083815260200190815260200160002081905550505b600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208054809190600190036154c19190615ab1565b5050505050565b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020805490506006600083815260200190815260200160002081905550600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190806001815401808255809150509060018203906000526020600020016000909192909190915055505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415615632576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4552433732313a206d696e7420746f20746865207a65726f206164647265737381525060200191505060405180910390fd5b61563b81613eff565b156156ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000081525060200191505060405180910390fd5b816001600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550615747600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020615983565b5050565b6007805490506008600083815260200190815260200160002081905550600781908060018154018082558091505090600182039060005260206000200160009091929091909150555050565b6000838311158290615844576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156158095780820151818401526020810190506157ee565b50505050905090810190601f1680156158365780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f91506000801b82141580156158995750808214155b92505050919050565b600073ffffffffffffffffffffffffffffffffffffffff166002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461595d5760006002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b50565b61597860018260000154614e4c90919063ffffffff16565b816000018190555050565b6001816000016000828254019250508190555050565b6040518060a00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600061ffff168152602001600060ff16815260200160008152602001600081525090565b815481835581811115615a1257600302816003028360005260206000209182019101615a119190615add565b5b505050565b604051806040016040528060008152602001600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615a7257805160ff1916838001178555615aa0565b82800160010185558215615aa0579182015b82811115615a9f578251825591602001919060010190615a84565b5b509050615aad9190615b5c565b5090565b815481835581811115615ad857818360005260206000209182019101615ad79190615b5c565b5b505050565b615b5991905b80821115615b5557600080820160006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556000820160146101000a81549061ffff02191690556000820160166101000a81549060ff02191690556001820160009055600282016000905550600301615ae3565b5090565b90565b615b7e91905b80821115615b7a576000816000905550600101615b62565b5090565b9056fe53697a65206d75737420626520736d616c6c6572207468616e206d6178416c6c6f636174696f6e4552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737368747470733a2f2f7661756c742e7761727269646572732e636f6d2f67756e732f4552433732313a207472616e7366657220746f20746865207a65726f20616464726573734552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732314d657461646174613a2055524920736574206f66206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a265627a7a72315820876931c215f7956d3a852fd29294df62b37bd1b5c267f0ba3dfa8814f2f4f2e064736f6c634300050b0032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000062d981aea59c6c768dff55ffb7f745cb79eeaa3600000000000000000000000018f64687e77c012d062bce0396fbbf7f21e11b77
-----Decoded View---------------
Arg [0] : factoryAddress (address): 0x62d981aea59C6c768dfF55ffB7F745cb79eEAA36
Arg [1] : oldGunToken (address): 0x18F64687E77C012D062BCe0396FBbF7f21e11B77
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000062d981aea59c6c768dff55ffb7f745cb79eeaa36
Arg [1] : 00000000000000000000000018f64687e77c012d062bce0396fbbf7f21e11b77
Deployed Bytecode Sourcemap
92844:15086:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;92844:15086:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93701:50;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;93701:50:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;39860:135;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;39860:135:0;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;90908:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;90908:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71236:204;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;71236:204:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;94179:572;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;94179:572:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;70518:425;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;70518:425:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;93607:47;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;93607:47:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98924:91;;;:::i;:::-;;;;;;;;;;;;;;;;;;;101461:209;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;101461:209:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;96795:876;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;96795:876:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;96795:876:0;;;;;;;;;;;;;;;;;102632:378;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;102632:378:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;95137:141;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;95137:141:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;73873:134;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;73873:134:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;102150:163;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;102150:163:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;99942:1507;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;99942:1507:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;98425:487;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;98425:487:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;96167:111;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;96167:111:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;99027:903;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;99027:903:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;97923:490;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;97923:490:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;96290:493;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;96290:493:0;;;;;;;;;;;;;;;;;97683:227;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;97683:227:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;66172:140;;;:::i;:::-;;65361:79;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;65727:94;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;102325:295;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;102325:295:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;91108:89;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;91108:89:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93086:43;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;71741:254;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;71741:254:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;106867:1060;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;106867:1060:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;101682:456;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;101682:456:0;;;;;;;;;;;;;;;;;:::i;:::-;;74744:272;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;74744:272:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;74744:272:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;74744:272:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;74744:272:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;93:3;85:6;81:16;74:27;137:4;133:9;126:4;121:3;117:14;113:30;106:37;;169:3;161:6;157:16;147:26;;74744:272:0;;;;;;;;;;;;;;;:::i;:::-;;93445:25;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;93445:25:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103510:896;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;103510:896:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;103510:896:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95421:734;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;95421:734:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;95421:734:0;;;;;;;;;;;;;;;;;72325:147;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;72325:147:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;93136:33;;;:::i;:::-;;;;;;;;;;;;;;;;;;;66467:109;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;66467:109:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;95290:119;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;95290:119:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;93701:50;;;;;;;;;;;;;;;;;:::o;39860:135::-;39930:4;39954:20;:33;39975:11;39954:33;;;;;;;;;;;;;;;;;;;;;;;;;;;39947:40;;39860:135;;;:::o;90908:85::-;90947:13;90980:5;90973:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;90908:85;:::o;71236:204::-;71295:7;71323:16;71331:7;71323;:16::i;:::-;71315:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71408:15;:24;71424:7;71408:24;;;;;;;;;;;;;;;;;;;;;71401:31;;71236:204;;;:::o;94179:572::-;94262:7;94287:6;94296:1;94287:10;;94282:433;94303:10;:17;;;;94299:1;:21;94282:433;;;94342:14;;:::i;:::-;94359:10;94370:1;94359:13;;;;;;;;;;;;;;;;;;94342:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94405:8;94391:22;;:1;:10;;;:22;;;94387:53;;94432:8;;;94387:53;94469:13;94497:1;:6;;;94485:18;;:1;:9;;;:18;94469:34;;94536:1;:9;;;94522:10;:23;;:45;;;;;94562:5;94549:10;:18;94522:45;94518:186;;;94588:11;94615:1;:9;;;94602:10;:22;94588:36;;94685:3;94668:1;:14;;;:20;94661:27;;;;;;;;94518:186;94282:433;;;94322:3;;;;;;;94282:433;;;;94735:8;;;94179:572;;;;;:::o;70518:425::-;70582:13;70598:16;70606:7;70598;:16::i;:::-;70582:32;;70639:5;70633:11;;:2;:11;;;;70625:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70719:5;70703:21;;:12;:10;:12::i;:::-;:21;;;:62;;;;70728:37;70745:5;70752:12;:10;:12::i;:::-;70728:16;:37::i;:::-;70703:62;70695:154;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70889:2;70862:15;:24;70878:7;70862:24;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;70927:7;70923:2;70907:28;;70916:5;70907:28;;;;;;;;;;;;70518:425;;;:::o;93607:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;98924:91::-;98968:7;98995:12;;98988:19;;98924:91;:::o;101461:209::-;101549:11;:20;101561:7;101549:20;;;;;;;;;;;;;;;;;;;;;101544:71;;101586:17;101595:7;101586:8;:17::i;:::-;101544:71;101625:37;101644:4;101650:2;101654:7;101625:18;:37::i;:::-;101461:209;;;:::o;96795:876::-;96853:16;96882:23;96922:16;96932:5;96922:9;:16::i;:::-;96908:31;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;148:4;140:6;136:17;126:27;;0:157;96908:31:0;;;;96882:57;;96960:8;96971:1;96960:12;;96988:6;96997:1;96988:10;;96983:437;97004:12;:19;97017:5;97004:19;;;;;;;;;;;;;;;:26;;;;97000:1;:30;96983:437;;;97052:14;;:::i;:::-;97069:12;:19;97082:5;97069:19;;;;;;;;;;;;;;;97089:1;97069:22;;;;;;;;;;;;;;;;;;97052:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97106:8;97134:1;:6;;;97117:23;;:1;:14;;;:23;97106:34;;97160:6;97169:1;:14;;;97160:23;;97155:254;97189:3;97185:1;:7;97155:254;;;97222:11;:14;97234:1;97222:14;;;;;;;;;;;;;;;;;;;;;:43;;;;;97260:5;97240:25;;:16;97254:1;97240:13;:16::i;:::-;:25;;;;97222:43;97218:100;;;97290:8;;97218:100;97368:1;97354:6;97361:3;97354:11;;;;;;;;;;;;;:15;;;;;97388:5;;;;;;;97155:254;97194:3;;;;;;;97155:254;;;;96983:437;;97032:3;;;;;;;96983:437;;;;97440:30;97473:21;97488:5;97473:14;:21::i;:::-;97440:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97510:6;97519:1;97510:10;;97505:125;97526:13;:20;97522:1;:24;97505:125;;;97582:13;97596:1;97582:16;;;;;;;;;;;;;;97568:6;97575:3;97568:11;;;;;;;;;;;;;:30;;;;;97613:5;;;;;;;97548:3;;;;;;;97505:125;;;;97657:6;97650:13;;;;;96795:876;;;:::o;102632:378::-;102698:7;102718:13;102734:22;102748:7;102734:13;:22::i;:::-;102718:38;;102783:10;:17;;;;102775:5;:25;102767:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102851:14;;:::i;:::-;102868:10;102879:5;102868:17;;;;;;;;;;;;;;;;;;102851:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102906:18;102955:1;:9;;;93125:4;102928:23;;:7;:23;;;;;;102927:37;102906:58;;102992:10;102985:17;;;;;102632:378;;;:::o;95137:141::-;95217:7;95244:19;95257:5;95244:12;:19::i;:::-;95264:5;95244:26;;;;;;;;;;;;;;95237:33;;95137:141;;;;:::o;73873:134::-;73960:39;73977:4;73983:2;73987:7;73960:39;;;;;;;;;;;;:16;:39::i;:::-;73873:134;;;:::o;102150:163::-;102211:7;102231:13;93125:4;102248:23;;:7;:23;;;;;;102231:41;;102300:5;102293:12;;;102150:163;;;:::o;99942:1507::-;100000:7;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100020:16;100048:8;;;;;;;;;;;100020:37;;100083:9;100095:1;100083:13;;100078:1279;100102:5;100098:1;:9;100078:1279;;;100129:13;100161:1;100145:13;;:17;100129:33;;100192:10;100204:11;100217:14;100233:15;100250:20;100274:7;:18;;;100293:5;100274:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;100274:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;100274:25:0;;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;100274:25:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100191:108;;;;;;;;;;100314:10;100330:196;;;;;;;;100362:2;100330:196;;;;;;100389:4;100330:196;;;;;;100422:8;100330:196;;;;;;100458:7;100330:196;;;;100498:12;100330:196;;;100314:213;;39:1:-1;33:3;27:10;23:18;57:10;52:3;45:23;79:10;72:17;;0:93;100314:213:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;100556:8;100584:4;100567:21;;:14;;:21;100556:32;;100603:16;100622:4;100603:23;;;;100646:6;100655:14;;100646:23;;100641:405;100675:3;100671:1;:7;100641:405;;;100704:13;100720:7;:15;;;100736:1;100720:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;100720:18:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;100720:18:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;100720:18:0;;;;;;;;;;;;;;;;100704:34;;100770:2;100761:11;;:5;:11;;;100757:238;;100814:4;100797:11;:14;100809:1;100797:14;;;;;;;;;;;;:21;;;;;;;;;;;;;;;;;;100841:20;100852:5;100859:1;100841:10;:20::i;:::-;100884:10;;;;;;;;100757:238;;;100973:1;100969:2;100948:27;;100965:1;100948:27;;;;;;;;;;;;100757:238;100641:405;100680:3;;;;;;;100641:405;;;;93125:4;101074:31;;:14;;:31;;;;;;;;;;;101146:8;101120:18;:22;101139:2;101120:22;;;;;;;;;;;;;;;;:34;;;;;;;;;;;101208:4;101169:43;;:25;:35;101195:8;101169:35;;;;;;;;;;;;;;;;:43;;;;;;;;;;;101241:55;101258:2;101262:10;101293:1;101273:10;:17;;;;:21;101262:33;;;;;;;;;;;;;;;;;;101241:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:16;:55::i;:::-;101341:4;101325:20;;:12;;:20;;;;;;;;;;;100078:1279;;;;;;;;100109:3;;;;;;;100078:1279;;;;101394:5;101377:13;;:22;;;;;;;;;;;101427:14;;101420:21;;;99942:1507;;;:::o;98425:487::-;98480:4;98501:11;:21;98513:8;98501:21;;;;;;;;;;;;;;;;;;;;;98497:408;;;98546:23;98560:8;98546:13;:23::i;:::-;98539:30;;;;98497:408;98602:13;98618:23;98632:8;98618:13;:23::i;:::-;98602:39;;98668:10;:17;;;;98660:5;:25;98656:211;;;98706:14;;:::i;:::-;98723:10;98734:5;98723:17;;;;;;;;;;;;;;;;;;98706:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98759:8;98787:1;:6;;;98770:23;;:1;:14;;;:23;98759:34;;98848:3;98837:8;:14;98830:21;;;;;;;98656:211;98888:5;98881:12;;;98425:487;;;;:::o;96167:111::-;96225:7;96252:11;:9;:11::i;:::-;96264:5;96252:18;;;;;;;;;;;;;;96245:25;;96167:111;;;:::o;99027:903::-;99121:4;93923:7;;;;;;;;;;;93909:21;;:10;:21;;;93901:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;93125:4;99146:20;;:4;:20;;;99138:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99231:10;99247:202;;;;;;;;99275:2;99247:202;;;;;;99298:4;99247:202;;;;;;99327:8;99247:202;;;;;;99359:25;:35;99385:8;99359:35;;;;;;;;;;;;;;;;99247:202;;;;99423:14;;99247:202;;;99231:219;;39:1:-1;33:3;27:10;23:18;57:10;52:3;45:23;79:10;72:17;;0:93;99231:219:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;99471:8;99499:4;99482:21;;:14;;:21;99471:32;;99519:6;99528:14;;99519:23;;99514:103;99548:3;99544:1;:7;99514:103;;;99603:1;99599:2;99578:27;;99595:1;99578:27;;;;;;;;;;;;99553:3;;;;;;;99514:103;;;;93125:4;99637:31;;:14;;:31;;;;;;;;;;;99715:4;99689:30;;:18;:22;99708:2;99689:22;;;;;;;;;;;;;;;;:30;;;;;;;;;;;99769:4;99730:43;;:25;:35;99756:8;99730:35;;;;;;;;;;;;;;;;:43;;;;;;;;;;;99794:55;99811:2;99815:10;99846:1;99826:10;:17;;;;:21;99815:33;;;;;;;;;;;;;;;;;;99794:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:16;:55::i;:::-;99886:4;99870:20;;:12;;:20;;;;;;;;;;;99908:14;;99901:21;;;99027:903;;;;;:::o;97923:490::-;97978:7;98007:15;98014:7;98007:6;:15::i;:::-;97999:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98074:11;:20;98086:7;98074:20;;;;;;;;;;;;;;;;;;;;;98070:84;;;98119:22;98133:7;98119:13;:22::i;:::-;98112:29;;;;98070:84;98165:13;98181:22;98195:7;98181:13;:22::i;:::-;98165:38;;98231:10;:17;;;;98223:5;:25;98215:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98290:14;;:::i;:::-;98307:10;98318:5;98307:17;;;;;;;;;;;;;;;;;;98290:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;98371:1;:6;;;98354:23;;:1;:14;;;:23;98344:7;:33;98336:42;;;;;;98397:1;:7;;;98390:14;;;;97923:490;;;;:::o;96290:493::-;96332:16;96361:23;96401:13;:11;:13::i;:::-;96387:28;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;148:4;140:6;136:17;126:27;;0:157;96387:28:0;;;;96361:54;;96436:8;96447:1;96436:12;;96464:6;96473:1;96464:10;;96459:283;96480:10;:17;;;;96476:1;:21;96459:283;;;96519:14;;:::i;:::-;96536:10;96547:1;96536:13;;;;;;;;;;;;;;;;;;96519:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;96564:8;96592:1;:6;;;96575:23;;:1;:14;;;:23;96564:34;;96618:6;96627:1;:14;;;96618:23;;96613:118;96647:3;96643:1;:7;96613:118;;;96690:1;96676:6;96683:3;96676:11;;;;;;;;;;;;;:15;;;;;96710:5;;;;;;;96652:3;;;;;;;96613:118;;;;96459:283;;96499:3;;;;;;;96459:283;;;;96769:6;96762:13;;;;96290:493;:::o;97683:227::-;97738:7;97783:1;97766:19;;:5;:19;;;;97758:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;97877:18;:25;97896:5;97877:25;;;;;;;;;;;;;;;;97852:22;97868:5;97852:15;:22::i;:::-;:50;97845:57;;97683:227;;;:::o;66172:140::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66271:1;66234:40;;66255:6;;;;;;;;;;;66234:40;;;;;;;;;;;;66302:1;66285:6;;:19;;;;;;;;;;;;;;;;;;66172:140::o;65361:79::-;65399:7;65426:6;;;;;;;;;;;65419:13;;65361:79;:::o;65727:94::-;65767:4;65807:6;;;;;;;;;;;65791:22;;:12;:10;:12::i;:::-;:22;;;65784:29;;65727:94;:::o;102325:295::-;102389:5;102407:13;102423:22;102437:7;102423:13;:22::i;:::-;102407:38;;102472:10;:17;;;;102464:5;:25;102456:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102540:14;;:::i;:::-;102557:10;102568:5;102557:17;;;;;;;;;;;;;;;;;;102540:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102602:1;:10;;;102595:17;;;;102325:295;;;:::o;91108:89::-;91149:13;91182:7;91175:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91108:89;:::o;93086:43::-;93125:4;93086:43;:::o;71741:254::-;71827:12;:10;:12::i;:::-;71821:18;;:2;:18;;;;71813:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;71921:8;71882:18;:32;71901:12;:10;:12::i;:::-;71882:32;;;;;;;;;;;;;;;:36;71915:2;71882:36;;;;;;;;;;;;;;;;:47;;;;;;;;;;;;;;;;;;71974:2;71945:42;;71960:12;:10;:12::i;:::-;71945:42;;;71978:8;71945:42;;;;;;;;;;;;;;;;;;;;;;71741:254;;:::o;106867:1060::-;106940:15;106958:10;106969;106958:22;;;;;;;;;;;;;;;;;;106940:40;;107001:21;107025:1;:7;;;;;;;;;;;;107001:31;;107072:10;107061:21;;:1;:7;;;;;;;;;;;;:21;;;107053:30;;;;;;107104:39;107126:13;107141:1;107104:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:21;:39::i;:::-;107174:2;107164:1;:7;;;:12;;;;;;;;;;;;;;;;;;107197:23;107214:2;107218:1;107197:23;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:16;:23::i;:::-;107279:10;107275:2;107246:44;;107260:13;107246:44;;;;;;;;;;;;107369:8;107397:1;:6;;;;;;;;;;;;107380:23;;:1;:14;;;:23;107369:34;;107414:19;107436:1;107414:23;;107453:6;107462:1;:14;;;107453:23;;107448:355;107482:3;107478:1;:7;107448:355;;;107511:11;:14;107523:1;107511:14;;;;;;;;;;;;;;;;;;;;;107507:235;;;107564:13;107550:27;;:10;107558:1;107550:7;:10::i;:::-;:27;;;107546:62;;107600:8;;107546:62;107507:235;;;107713:13;;;;;;;107507:235;107789:1;107785:2;107761:30;;107770:13;107761:30;;;;;;;;;;;;107448:355;107487:3;;;;;;;107448:355;;;;107849:11;107823:18;:22;107842:2;107823:22;;;;;;;;;;;;;;;;:37;;;;;;;;;;;107908:11;107871:18;:33;107890:13;107871:33;;;;;;;;;;;;;;;;:48;;;;;;;;;;;106867:1060;;;;;;:::o;101682:456::-;101744:11;:20;101756:7;101744:20;;;;;;;;;;;;;;;;;;;;;101743:21;101735:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101803:13;101819:22;101833:7;101819:13;:22::i;:::-;101803:38;;101868:10;:17;;;;101860:5;:25;101852:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101926:14;;:::i;:::-;101943:10;101954:5;101943:17;;;;;;;;;;;;;;;;;;101926:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;102006:1;:6;;;101989:23;;:1;:14;;;:23;101979:7;:33;101971:42;;;;;;102047:4;102024:11;:20;102036:7;102024:20;;;;;;;;;;;;:27;;;;;;;;;;;;;;;;;;102062:28;102073:1;:7;;;102082;102062:10;:28::i;:::-;102101:18;:27;102120:1;:7;;;102101:27;;;;;;;;;;;;;;;;:29;;;;;;;;;;;;;;101682:456;;;:::o;74744:272::-;74859:41;74878:12;:10;:12::i;:::-;74892:7;74859:18;:41::i;:::-;74851:103;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;74965:43;74983:4;74989:2;74993:7;75002:5;74965:17;:43::i;:::-;74744:272;;;;:::o;93445:25::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;103510:896::-;103566:13;103600:15;103607:7;103600:6;:15::i;:::-;103592:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;103655:11;:20;103667:7;103655:20;;;;;;;;;;;;;;;;;;;;;103651:748;;;103699:23;103714:7;103699:14;:23::i;:::-;103692:30;;;;103651:748;103792:14;103809:25;103826:7;103809:16;:25::i;:::-;103792:42;;103849:19;103871:27;103890:7;103871:18;:27::i;:::-;103849:49;;103927:16;103946:144;104018:71;:61;104061:17;:15;;;;;;;;;;;;;;;;;;:17::i;:::-;104018:35;:25;104031:11;104018:12;:25::i;:::-;:33;:35::i;:::-;:42;;:61;;;;:::i;:::-;:69;:71::i;:::-;103946:64;:54;103986:13;:11;;;;;;;;;;;;;;;;;;:13::i;:::-;103946:32;:22;103959:8;103946:22;;:12;:22::i;:::-;:30;:32::i;:::-;:39;;:54;;;;:::i;:::-;:62;:64::i;:::-;:71;;:144;;;;:::i;:::-;103927:163;;104105:19;:57;;;;;;;;;;;;;;;;;;;104280:23;104306:36;104329:12;:2;:10;:12::i;:::-;104306:15;:5;:13;:15::i;:::-;:22;;:36;;;;:::i;:::-;104280:62;;104378:9;104371:16;;;;;;;103510:896;;;;:::o;95421:734::-;95498:16;95527:14;;:::i;:::-;95544:12;:19;95557:5;95544:19;;;;;;;;;;;;;;;95564:5;95544:26;;;;;;;;;;;;;;;;;;95527:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;95581:23;95621:1;:6;;;95607:21;;;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;148:4;140:6;136:17;126:27;;0:157;95607:21:0;;;;95581:47;;95649:11;95663:1;95649:15;;95675:8;95703:1;:6;;;95686:23;;:1;:14;;;:23;95675:34;;95725:6;95734:1;:14;;;95725:23;;95720:226;95754:3;95750:1;:7;95720:226;;;95783:11;:14;95795:1;95783:14;;;;;;;;;;;;;;;;;;;;;:43;;;;;95821:5;95801:25;;:16;95815:1;95801:13;:16::i;:::-;:25;;;;95783:43;95779:92;;;95847:8;;95779:92;95913:1;95899:6;95906:3;95899:11;;;;;;;;;;;;;:15;;;;;95929:5;;;;;;;95720:226;95759:3;;;;;;;95720:226;;;;95980:1;95974:3;:7;95966:16;;;;;;96003:17;96032:3;96023:1;:6;;;:12;;;96003:32;;96101:9;96092:6;96086:13;96082:29;96074:6;96067:45;96141:6;96134:13;;;;;;;95421:734;;;;:::o;72325:147::-;72405:4;72429:18;:25;72448:5;72429:25;;;;;;;;;;;;;;;:35;72455:8;72429:35;;;;;;;;;;;;;;;;;;;;;;;;;72422:42;;72325:147;;;;:::o;93136:33::-;;;;:::o;66467:109::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66540:28;66559:8;66540:18;:28::i;:::-;66467:109;:::o;95290:119::-;95348:7;95375:12;:19;95388:5;95375:19;;;;;;;;;;;;;;;:26;;;;95368:33;;95290:119;;;:::o;76209:155::-;76266:4;76283:13;76299:11;:20;76311:7;76299:20;;;;;;;;;;;;;;;;;;;;;76283:36;;76354:1;76337:19;;:5;:19;;;;76330:26;;;76209:155;;;:::o;27961:98::-;28006:15;28041:10;28034:17;;27961:98;:::o;72919:292::-;73063:41;73082:12;:10;:12::i;:::-;73096:7;73063:18;:41::i;:::-;73055:103;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;73171:32;73185:4;73191:2;73195:7;73171:13;:32::i;:::-;72919:292;;;:::o;69859:228::-;69914:7;69934:13;69950:11;:20;69962:7;69950:20;;;;;;;;;;;;;;;;;;;;;69934:36;;70006:1;69989:19;;:5;:19;;;;69981:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;70074:5;70067:12;;;69859:228;;;:::o;85400:126::-;85462:17;85499:12;:19;85512:5;85499:19;;;;;;;;;;;;;;;85492:26;;85400:126;;;:::o;104418:747::-;104522:14;104539:26;104556:8;104539:16;:26::i;:::-;104522:43;;104576:19;104598:28;104617:8;104598:18;:28::i;:::-;104576:50;;104651:16;104670:144;104742:71;:61;104785:17;:15;;;;;;;;;;;;;;;;;;:17::i;:::-;104742:35;:25;104755:11;104742:12;:25::i;:::-;:33;:35::i;:::-;:42;;:61;;;;:::i;:::-;:69;:71::i;:::-;104670:64;:54;104710:13;:11;;;;;;;;;;;;;;;;;;:13::i;:::-;104670:32;:22;104683:8;104670:22;;:12;:22::i;:::-;:30;:32::i;:::-;:39;;:54;;;;:::i;:::-;:62;:64::i;:::-;:71;;:144;;;;:::i;:::-;104651:163;;104825:19;:57;;;;;;;;;;;;;;;;;;;104992:23;105018:36;105041:12;:2;:10;:12::i;:::-;105018:15;:5;:13;:15::i;:::-;:22;;:36;;;;:::i;:::-;104992:62;;105075:32;105093:3;105098:8;105075:17;:32::i;:::-;105118:39;105137:8;105147:9;105118:18;:39::i;:::-;104418:747;;;;;;;:::o;106601:254::-;106678:19;106700:33;106714:5;:18;;;106700:13;:33::i;:::-;106678:55;;106785:12;:16;106798:2;106785:16;;;;;;;;;;;;;;;:23;;;;106754:15;:28;106770:11;106754:28;;;;;;;;;;;:54;;;;106819:12;:16;106832:2;106819:16;;;;;;;;;;;;;;;106841:5;106819:28;;39:1:-1;33:3;27:10;23:18;57:10;52:3;45:23;79:10;72:17;;0:93;106819:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106601:254;;;:::o;69422:211::-;69477:7;69522:1;69505:19;;:5;:19;;;;69497:74;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;69591:34;:17;:24;69609:5;69591:24;;;;;;;;;;;;;;;:32;:34::i;:::-;69584:41;;69422:211;;;:::o;105296:1293::-;105562:19;105584:33;105598:5;:18;;;105584:13;:33::i;:::-;105562:55;;105630:22;105655:32;105685:1;105655:12;:18;105668:4;105655:18;;;;;;;;;;;;;;;:25;;;;:29;;:32;;;;:::i;:::-;105630:57;;105698:18;105719:15;:28;105735:11;105719:28;;;;;;;;;;;;105698:49;;105868:14;105854:10;:28;105850:409;;105899:22;;:::i;:::-;105924:12;:18;105937:4;105924:18;;;;;;;;;;;;;;;105943:14;105924:34;;;;;;;;;;;;;;;;;;105899:59;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;105973:23;105999:37;106013:9;:22;;;105999:13;:37::i;:::-;105973:63;;106086:9;106053:12;:18;106066:4;106053:18;;;;;;;;;;;;;;;106072:10;106053:30;;;;;;;;;;;;;;;;;;:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106203:10;106168:15;:32;106184:15;106168:32;;;;;;;;;;;:45;;;;105850:409;;;106348:12;:18;106361:4;106348:18;;;;;;;;;;;;;;;:27;;;;;;;;;;;;:::i;:::-;;105296:1293;;;;;:::o;76734:333::-;76819:4;76844:16;76852:7;76844;:16::i;:::-;76836:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;76920:13;76936:16;76944:7;76936;:16::i;:::-;76920:32;;76982:5;76971:16;;:7;:16;;;:51;;;;77015:7;76991:31;;:20;77003:7;76991:11;:20::i;:::-;:31;;;76971:51;:87;;;;77026:32;77043:5;77050:7;77026:16;:32::i;:::-;76971:87;76963:96;;;76734:333;;;;:::o;75735:272::-;75845:32;75859:4;75865:2;75869:7;75845:13;:32::i;:::-;75896:48;75919:4;75925:2;75929:7;75938:5;75896:22;:48::i;:::-;75888:111;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75735:272;;;;:::o;91404:203::-;91460:13;91494:16;91502:7;91494;:16::i;:::-;91486:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91580:10;:19;91591:7;91580:19;;;;;;;;;;;91573:26;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;91404:203;;;:::o;891:216::-;951:12;;:::i;:::-;976:8;1036:4;1030;1026:15;1019:22;;1069:30;;;;;;;;1081:4;1075:18;1069:30;;;;1095:3;1069:30;;;1062:37;;;891:216;;;:::o;103022:476::-;103075:13;103110:1;103105;:6;103101:49;;;103128:10;;;;;;;;;;;;;;;;;;;;;103101:49;103160:6;103169:1;103160:10;;103181:8;103200:69;103212:1;103207;:6;103200:69;;103230:5;;;;;;;103255:2;103250:7;;;;;;;;;103200:69;;;103279:17;103309:3;103299:14;;;;;;;;;;;;;;;;;;;;;;;;;29:1:-1;21:6;17:14;116:4;104:10;96:6;87:34;147:4;139:6;135:17;125:27;;0:156;103299:14:0;;;;103279:34;;103324:6;103339:1;103333:3;:7;103324:16;;103351:100;103363:1;103358;:6;103351:100;;103413:2;103409:1;:6;;;;;;103404:2;:11;103393:24;;103381:4;103386:3;;;;;;;103381:9;;;;;;;;;;;:36;;;;;;;;;;;103437:2;103432:7;;;;;;;;;103351:100;;;103485:4;103471:19;;;;;;103022:476;;;;:::o;22633:362::-;22711:13;22737:17;22780:5;:10;;;22768:4;:9;;;:22;22757:34;;;;;;;;;;;;;;;;;;;;;;;;;29:1:-1;21:6;17:14;116:4;104:10;96:6;87:34;147:4;139:6;135:17;125:27;;0:156;22757:34:0;;;;22737:54;;22802:11;22854:2;22849:3;22845:12;22835:22;;22869:36;22876:6;22884:4;:9;;;22895:4;:9;;;22869:6;:36::i;:::-;22916:50;22932:4;:9;;;22923:6;:18;22943:5;:10;;;22955:5;:10;;;22916:6;:50::i;:::-;22984:3;22977:10;;;;22633:362;;;;:::o;66682:229::-;66776:1;66756:22;;:8;:22;;;;66748:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66866:8;66837:38;;66858:6;;;;;;;;;;;66837:38;;;;;;;;;;;;66895:8;66886:6;;:17;;;;;;;;;;;;;;;;;;66682:229;:::o;83808:245::-;83894:38;83914:4;83920:2;83924:7;83894:19;:38::i;:::-;83945:47;83978:4;83984:7;83945:32;:47::i;:::-;84005:40;84033:2;84037:7;84005:27;:40::i;:::-;83808:245;;;:::o;84318:214::-;84388:30;84406:2;84410:7;84388:17;:30::i;:::-;84431:40;84459:2;84463:7;84431:27;:40::i;:::-;84484;84516:7;84484:31;:40::i;:::-;84318:214;;:::o;91854:195::-;91940:16;91948:7;91940;:16::i;:::-;91932:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;92038:3;92016:10;:19;92027:7;92016:19;;;;;;;;;;;:25;;;;;;;;;;;;:::i;:::-;;91854:195;;:::o;38539:114::-;38604:7;38631;:14;;;38624:21;;38539:114;;;:::o;31215:136::-;31273:7;31300:43;31304:1;31307;31300:43;;;;;;;;;;;;;;;;;:3;:43::i;:::-;31293:50;;31215:136;;;;:::o;79947:358::-;80069:4;80096:15;:2;:13;;;:15::i;:::-;80091:60;;80135:4;80128:11;;;;80091:60;80163:13;80195:2;80179:36;;;80216:12;:10;:12::i;:::-;80230:4;80236:7;80245:5;80179:72;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;80179:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;80179:72:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;80179:72:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;80179:72:0;;;;;;;;;;;;;;;;80163:88;;67623:10;80280:16;;80270:26;;;:6;:26;;;;80262:35;;;79947:358;;;;;;;:::o;119:565::-;241:170;254:2;247:3;:9;241:170;;331:3;325:10;319:4;312:24;373:2;365:10;;;;397:2;390:9;;;;265:2;258:9;;;;241:170;;;456:9;488:1;481:3;476:2;:8;468:3;:17;:21;456:33;;559:4;555:9;549:3;543:10;539:26;612:4;605;599:11;595:22;657:7;647:8;644:21;638:4;631:35;509:168;;;;;;:::o;78886:459::-;79000:4;78980:24;;:16;78988:7;78980;:16::i;:::-;:24;;;78972:78;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79083:1;79069:16;;:2;:16;;;;79061:65;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79139:23;79154:7;79139:14;:23::i;:::-;79175:35;:17;:23;79193:4;79175:23;;;;;;;;;;;;;;;:33;:35::i;:::-;79221:33;:17;:21;79239:2;79221:21;;;;;;;;;;;;;;;:31;:33::i;:::-;79290:2;79267:11;:20;79279:7;79267:20;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;79329:7;79325:2;79310:27;;79319:4;79310:27;;;;;;;;;;;;78886:459;;;:::o;87005:1148::-;87271:22;87296:32;87326:1;87296:12;:18;87309:4;87296:18;;;;;;;;;;;;;;;:25;;;;:29;;:32;;;;:::i;:::-;87271:57;;87339:18;87360:17;:26;87378:7;87360:26;;;;;;;;;;;;87339:47;;87507:14;87493:10;:28;87489:328;;87538:19;87560:12;:18;87573:4;87560:18;;;;;;;;;;;;;;;87579:14;87560:34;;;;;;;;;;;;;;;;87538:56;;87644:11;87611:12;:18;87624:4;87611:18;;;;;;;;;;;;;;;87630:10;87611:30;;;;;;;;;;;;;;;:44;;;;87761:10;87728:17;:30;87746:11;87728:30;;;;;;;;;;;:43;;;;87489:328;;87906:12;:18;87919:4;87906:18;;;;;;;;;;;;;;;:27;;;;;;;;;;;;:::i;:::-;;87005:1148;;;;:::o;85827:186::-;85941:12;:16;85954:2;85941:16;;;;;;;;;;;;;;;:23;;;;85912:17;:26;85930:7;85912:26;;;;;;;;;;;:52;;;;85975:12;:16;85988:2;85975:16;;;;;;;;;;;;;;;85997:7;85975:30;;39:1:-1;33:3;27:10;23:18;57:10;52:3;45:23;79:10;72:17;;0:93;85975:30:0;;;;;;;;;;;;;;;;;;;;;;85827:186;;:::o;77320:290::-;77412:1;77398:16;;:2;:16;;;;77390:61;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77471:16;77479:7;77471;:16::i;:::-;77470:17;77462:58;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;77556:2;77533:11;:20;77545:7;77533:20;;;;;;;;;;;;:25;;;;;;;;;;;;;;;;;;77569:33;:17;:21;77587:2;77569:21;;;;;;;;;;;;;;;:31;:33::i;:::-;77320:290;;:::o;86214:164::-;86318:10;:17;;;;86291:15;:24;86307:7;86291:24;;;;;;;;;;;:44;;;;86346:10;86362:7;86346:24;;39:1:-1;33:3;27:10;23:18;57:10;52:3;45:23;79:10;72:17;;0:93;86346:24:0;;;;;;;;;;;;;;;;;;;;;;86214:164;:::o;31801:192::-;31887:7;31920:1;31915;:6;;31923:12;31907:29;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;31907:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;31947:9;31963:1;31959;:5;31947:17;;31984:1;31977:8;;;31801:192;;;;;:::o;36236:810::-;36296:4;36749:16;36776:19;36798:66;36776:88;;;;36967:7;36955:20;36943:32;;37007:3;36995:15;;:8;:15;;:42;;;;;37026:11;37014:8;:23;;36995:42;36987:51;;;;36236:810;;;:::o;80473:175::-;80573:1;80537:38;;:15;:24;80553:7;80537:24;;;;;;;;;;;;;;;;;;;;;:38;;;80533:108;;80627:1;80592:15;:24;80608:7;80592:24;;;;;;;;;;;;:37;;;;;;;;;;;;;;;;;;80533:108;80473:175;:::o;38850:110::-;38931:21;38950:1;38931:7;:14;;;:18;;:21;;;;:::i;:::-;38914:7;:14;;:38;;;;38850:110;:::o;38661:181::-;38833:1;38815:7;:14;;;:19;;;;;;;;;;;38661:181;:::o;92844:15086::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o
Swarm Source
bzzr://876931c215f7956d3a852fd29294df62b37bd1b5c267f0ba3dfa8814f2f4f2e0
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.