Source Code
Latest 25 from a total of 28 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Transfer Ownersh... | 8762668 | 2322 days ago | IN | 0 ETH | 0.00009137 | ||||
| Set Shop State | 8762367 | 2322 days ago | IN | 0 ETH | 0.00005675 | ||||
| Set Shop State | 8762367 | 2322 days ago | IN | 0 ETH | 0.00005678 | ||||
| Set Shop State | 8762358 | 2322 days ago | IN | 0 ETH | 0.00005682 | ||||
| Buy With Ether | 8760276 | 2322 days ago | IN | 0.38830537 ETH | 0.0005521 | ||||
| Buy With Ether | 8760234 | 2322 days ago | IN | 0.37917686 ETH | 0.0005821 | ||||
| Buy With Ether | 8760148 | 2322 days ago | IN | 0.23920915 ETH | 0.00028389 | ||||
| Buy With Ether | 8760147 | 2322 days ago | IN | 0.05975716 ETH | 0.00029105 | ||||
| Buy With Ether | 8759507 | 2322 days ago | IN | 0.05954282 ETH | 0.00113181 | ||||
| Buy With Ether | 8759233 | 2322 days ago | IN | 0.05949826 ETH | 0.00066252 | ||||
| Transfer Ownersh... | 8756618 | 2323 days ago | IN | 0 ETH | 0.00006091 | ||||
| Buy With Ether | 8756301 | 2323 days ago | IN | 0.11450004 ETH | 0.00082815 | ||||
| Set Shop State | 8755911 | 2323 days ago | IN | 0 ETH | 0.00008695 | ||||
| Set Shop State | 8755911 | 2323 days ago | IN | 0 ETH | 0.00008691 | ||||
| Set Shop State | 8755911 | 2323 days ago | IN | 0 ETH | 0.00008688 | ||||
| Create Category | 8755904 | 2323 days ago | IN | 0 ETH | 0.00008543 | ||||
| Create Category | 8755904 | 2323 days ago | IN | 0 ETH | 0.00008543 | ||||
| Create Category | 8755904 | 2323 days ago | IN | 0 ETH | 0.00008543 | ||||
| Set BZN Feed Con... | 8755903 | 2323 days ago | IN | 0 ETH | 0.00008713 | ||||
| Set Price | 8755901 | 2323 days ago | IN | 0 ETH | 0.00008522 | ||||
| Set Price | 8755901 | 2323 days ago | IN | 0 ETH | 0.00008522 | ||||
| Set Price | 8755898 | 2323 days ago | IN | 0 ETH | 0.00008522 | ||||
| Set Ether Percen... | 8755894 | 2323 days ago | IN | 0 ETH | 0.00012585 | ||||
| Set Ether Percen... | 8755894 | 2323 days ago | IN | 0 ETH | 0.00012585 | ||||
| Set Ether Percen... | 8755890 | 2323 days ago | IN | 0 ETH | 0.00006585 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| - | 8881835 | 2303 days ago | 25.4875914 ETH | ||||
| - | 8766309 | 2321 days ago | 0.0345335 ETH | ||||
| - | 8766271 | 2321 days ago | 0.0345335 ETH | ||||
| - | 8761847 | 2322 days ago | 0.00642269 ETH | ||||
| - | 8761847 | 2322 days ago | 0.13487656 ETH | ||||
| - | 8761847 | 2322 days ago | 0.00316644 ETH | ||||
| - | 8761847 | 2322 days ago | 0.06649541 ETH | ||||
| - | 8761838 | 2322 days ago | 0.01601745 ETH | ||||
| - | 8761838 | 2322 days ago | 0.33636658 ETH | ||||
| - | 8761763 | 2322 days ago | 0.00319677 ETH | ||||
| - | 8761763 | 2322 days ago | 0.06713218 ETH | ||||
| - | 8761740 | 2322 days ago | 0.00434689 ETH | ||||
| - | 8761740 | 2322 days ago | 0.09128488 ETH | ||||
| - | 8761721 | 2322 days ago | 0.01262629 ETH | ||||
| - | 8761721 | 2322 days ago | 0.26515213 ETH | ||||
| - | 8761712 | 2322 days ago | 0.01083876 ETH | ||||
| - | 8761712 | 2322 days ago | 0.2276141 ETH | ||||
| - | 8761706 | 2322 days ago | 0.00798214 ETH | ||||
| - | 8761706 | 2322 days ago | 0.16762504 ETH | ||||
| - | 8761703 | 2322 days ago | 0.00796819 ETH | ||||
| - | 8761703 | 2322 days ago | 0.167332 ETH | ||||
| - | 8761699 | 2322 days ago | 0.0107982 ETH | ||||
| - | 8761699 | 2322 days ago | 0.22676221 ETH | ||||
| - | 8761698 | 2322 days ago | 0.00628951 ETH | ||||
| - | 8761698 | 2322 days ago | 0.13207979 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
GunPreOrder
Compiler Version
v0.5.11+commit.c082d0b4
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2019-10-17
*/
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;
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) public OveridableERC721Metadata("WarRiders Gun", "WRG") {
factory = factoryAddress;
}
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 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[1] = convert(prices[3], false);
prices[2] = (prices[1] * (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 {
require(preOrderAddress == address(0));
require(dst != address(0));
//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
Contract ABI
API[{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"requiredEtherPercentBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"disableCreateCategories","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint8","name":"category","type":"uint8"}],"name":"killCategory","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"address","name":"","type":"address"}],"name":"categoryReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"categoryOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"increase","type":"uint256"},{"internalType":"uint256","name":"base","type":"uint256"},{"internalType":"uint8","name":"category","type":"uint8"}],"name":"setPercentIncrease","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"referral","type":"address"},{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setCommission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"categoryPercentBase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"categoryPercentIncrease","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ethFeed","outputs":[{"internalType":"contract IDSValue","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bznFeed","outputs":[{"internalType":"contract BZNFeed","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint8","name":"category","type":"uint8"}],"name":"createCategory","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"uint16","name":"quanity","type":"uint16"}],"name":"priceFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":false,"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"receiveApproval","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"usdValue","type":"uint256"},{"internalType":"bool","name":"isBZN","type":"bool"}],"name":"convert","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"sold","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"categoryKilled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"bool","name":"inWei","type":"bool"}],"name":"setPrice","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"COMMISSION_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"categoryExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"percent","type":"uint256"},{"internalType":"uint256","name":"base","type":"uint256"},{"internalType":"uint8","name":"category","type":"uint8"}],"name":"setEtherPercent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"referal","type":"address"},{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"address payable","name":"new_owner","type":"address"},{"internalType":"uint16","name":"quanity","type":"uint16"}],"name":"buyWithBZN","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"bool","name":"open","type":"bool"}],"name":"setShopState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"categoryPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"requiredEtherPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"new_bzn_feed","type":"address"}],"name":"setBZNFeedContract","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"referal","type":"address"},{"internalType":"uint8","name":"category","type":"uint8"},{"internalType":"address","name":"new_owner","type":"address"},{"internalType":"uint16","name":"quanity","type":"uint16"}],"name":"buyWithEther","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"allowCreateCategory","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"internalType":"contract GunToken","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"tokenFactory","type":"address"},{"internalType":"address","name":"gp","type":"address"},{"internalType":"address","name":"isd","type":"address"},{"internalType":"address","name":"bzn_address","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"category","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"quanity","type":"uint256"},{"indexed":false,"internalType":"address","name":"reserver","type":"address"}],"name":"consumerBulkBuy","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"gunId","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint8","name":"category","type":"uint8"}],"name":"GunsBought","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","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"}]Contract Creation Code
60806040526001600b60006101000a81548160ff0219169083151502179055503480156200002c57600080fd5b506040516200364538038062003645833981810160405260a08110156200005257600080fd5b81019080805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919050505060006200009d6200039e60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35084600b60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620186c360066000600160ff16815260200190815260200160002081905550620186a060076000600160ff16815260200190815260200160002081905550620186b960066000600260ff16815260200190815260200160002081905550620186a060076000600260ff16815260200190815260200160002081905550620186af60066000600360ff16815260200190815260200160002081905550620186a060076000600360ff16815260200190815260200160002081905550600a60046000735b3256965e7c3cf26e11fcaf296dfc8807c0107373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050505050620003a6565b600033905090565b61328f80620003b66000396000f3fe6080604052600436106101f85760003560e01c80638f4ffcb11161010d578063c768ad1a116100a0578063e5174e081161006f578063e5174e0814610bb5578063e950879314610c06578063f2fde38b14610c9d578063f8160b5014610cee578063fc0c546a14610d1d576101f8565b8063c768ad1a14610a30578063c8e5ae4c14610ac7578063ccba093214610b11578063d5deb15b14610b63576101f8565b8063aa30b420116100dc578063aa30b42014610909578063b404e0011461095d578063b51bcc0e14610988578063bea82b06146109de576101f8565b80638f4ffcb1146106e85780639a5ef369146108055780639c03facb14610860578063a68b8552146108b3576101f8565b80633d17604511610190578063715018a61161015f578063715018a6146105a657806373c81a8b146105bd578063762c8d1f146105fb5780638da5cb5b146106625780638f32d59b146106b9576101f8565b80633d17604514610454578063512ceb3d146104a65780635e19d05c146104f8578063690d5ff41461054f576101f8565b806324b5b280116101cc57806324b5b280146103165780632e07a5be1461036c5780632e1a7d4d146103be57806331729a45146103f9576101f8565b80627a7776146101fd57806301b49e821461024f57806321bf73841461026657806323539a84146102a4575b600080fd5b34801561020957600080fd5b506102396004803603602081101561022057600080fd5b81019080803560ff169060200190929190505050610d74565b6040518082815260200191505060405180910390f35b34801561025b57600080fd5b50610264610d8c565b005b34801561027257600080fd5b506102a26004803603602081101561028957600080fd5b81019080803560ff169060200190929190505050610e23565b005b3480156102b057600080fd5b50610300600480360360408110156102c757600080fd5b81019080803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f35565b6040518082815260200191505060405180910390f35b34801561032257600080fd5b506103526004803603602081101561033957600080fd5b81019080803560ff169060200190929190505050610f5a565b604051808215151515815260200191505060405180910390f35b34801561037857600080fd5b506103bc6004803603606081101561038f57600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050610f7a565b005b3480156103ca57600080fd5b506103f7600480360360208110156103e157600080fd5b8101908080359060200190929190505050611041565b005b34801561040557600080fd5b506104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506111dc565b005b34801561046057600080fd5b506104906004803603602081101561047757600080fd5b81019080803560ff1690602001909291905050506112be565b6040518082815260200191505060405180910390f35b3480156104b257600080fd5b506104e2600480360360208110156104c957600080fd5b81019080803560ff1690602001909291905050506112d6565b6040518082815260200191505060405180910390f35b34801561050457600080fd5b5061050d6112ee565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561055b57600080fd5b50610564611314565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156105b257600080fd5b506105bb61133a565b005b3480156105c957600080fd5b506105f9600480360360208110156105e057600080fd5b81019080803560ff169060200190929190505050611473565b005b34801561060757600080fd5b506106456004803603604081101561061e57600080fd5b81019080803560ff169060200190929190803561ffff16906020019092919050505061153a565b604051808381526020018281526020019250505060405180910390f35b34801561066e57600080fd5b506106776115fa565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156106c557600080fd5b506106ce611623565b604051808215151515815260200191505060405180910390f35b6107eb600480360360808110156106fe57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561076557600080fd5b82018360208201111561077757600080fd5b8035906020019184600183028401116401000000008311171561079957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611681565b604051808215151515815260200191505060405180910390f35b34801561081157600080fd5b5061084a6004803603604081101561082857600080fd5b8101908080359060200190929190803515159060200190929190505050611704565b6040518082815260200191505060405180910390f35b34801561086c57600080fd5b506108996004803603602081101561088357600080fd5b81019080803590602001909291905050506118a7565b604051808215151515815260200191505060405180910390f35b3480156108bf57600080fd5b506108ef600480360360208110156108d657600080fd5b81019080803560ff16906020019092919050505061195e565b604051808215151515815260200191505060405180910390f35b34801561091557600080fd5b5061095b6004803603606081101561092c57600080fd5b81019080803560ff1690602001909291908035906020019092919080351515906020019092919050505061197e565b005b34801561096957600080fd5b50610972611a36565b6040518082815260200191505060405180910390f35b34801561099457600080fd5b506109c4600480360360208110156109ab57600080fd5b81019080803560ff169060200190929190505050611a3b565b604051808215151515815260200191505060405180910390f35b3480156109ea57600080fd5b50610a2e60048036036060811015610a0157600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050611a5b565b005b610aad60048036036080811015610a4657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff169060200190929190505050611b16565b604051808215151515815260200191505060405180910390f35b348015610ad357600080fd5b50610b0f60048036036040811015610aea57600080fd5b81019080803560ff169060200190929190803515159060200190929190505050612737565b005b348015610b1d57600080fd5b50610b4d60048036036020811015610b3457600080fd5b81019080803560ff169060200190929190505050612873565b6040518082815260200191505060405180910390f35b348015610b6f57600080fd5b50610b9f60048036036020811015610b8657600080fd5b81019080803560ff16906020019092919050505061288b565b6040518082815260200191505060405180910390f35b348015610bc157600080fd5b50610c0460048036036020811015610bd857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506128a3565b005b610c8360048036036080811015610c1c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff169060200190929190505050612961565b604051808215151515815260200191505060405180910390f35b348015610ca957600080fd5b50610cec60048036036020811015610cc057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612fb7565b005b348015610cfa57600080fd5b50610d0361303d565b604051808215151515815260200191505060405180910390f35b348015610d2957600080fd5b50610d32613050565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600a6020528060005260406000206000915090505481565b610d94611623565b610e06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000600b60006101000a81548160ff021916908315150217905550565b610e2b611623565b610e9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600360008260ff1660ff16815260200190815260200160002060009054906101000a900460ff1615610ece57600080fd5b6000600260008360ff1660ff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600360008360ff1660ff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6005602052816000526040600020602052806000526040600020600091509150505481565b60026020528060005260406000206000915054906101000a900460ff1681565b610f82611623565b610ff4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b81831161100057600080fd5b82600660008360ff1660ff1681526020019081526020016000208190555081600760008360ff1660ff16815260200190815260200160002081905550505050565b611049611623565b6110bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60003073ffffffffffffffffffffffffffffffffffffffff163190508082111561114d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f52657175657374656420746f206d75636800000000000000000000000000000081525060200191505060405180910390fd5b60006111576115fa565b90508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f1935050505015801561119f573d6000803e3d6000fd5b507f4e70a604b23a8edee2b1d0a656e9b9c00b73ad8bb1afc2c59381ee9f69197de7836040518082815260200191505060405180910390a1505050565b6111e4611623565b611256576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6005811161126357600080fd5b605f811061127057600080fd5b60058103905080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b60076020528060005260406000206000915090505481565b60066020528060005260406000206000915090505481565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611342611623565b6113b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61147b611623565b6114ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600b60009054906101000a900460ff1661150657600080fd5b60018060008360ff1660ff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008060008361ffff161161154e57600080fd5b6000600660008660ff1660ff1681526020019081526020016000205490506000600760008760ff1660ff1681526020019081526020016000205490506000600860008860ff1660ff1681526020019081526020016000205490506000819050600080905060008090505b8861ffff168110156115e75784868502816115cf57fe5b049250829350828201915080806001019150506115b8565b5081819650965050505050509250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611665613076565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60008060008084806020019051606081101561169c57600080fd5b8101908080519060200190929190805190602001909291908051906020019092919050505082925080935081945082955050505060018161ffff1610156116e257600080fd5b60008890506116f384848385611b16565b506001945050505050949350505050565b600081156117c157600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3908e1b846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561177f57600080fd5b505afa158015611793573d6000803e3d6000fd5b505050506040513d60208110156117a957600080fd5b810190808051906020019092919050505090506118a1565b600080600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166359e02dd76040518163ffffffff1660e01b8152600401604080518083038186803b15801561182b57600080fd5b505afa15801561183f573d6000803e3d6000fd5b505050506040513d604081101561185557600080fd5b810190808051906020019092919080519060200190929190505050809350819250505060008160001c9050670de0b6b3a7640000818161189157fe5b04868161189a57fe5b0493505050505b92915050565b6000600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f558e79836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561191c57600080fd5b505afa158015611930573d6000803e3d6000fd5b505050506040513d602081101561194657600080fd5b81019080805190602001909291905050509050919050565b60036020528060005260406000206000915054906101000a900460ff1681565b611986611623565b6119f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000670de0b6b3a764000090508115611a1057600190505b808302600860008660ff1660ff1681526020019081526020016000208190555050505050565b600581565b60016020528060005260406000206000915054906101000a900460ff1681565b611a63611623565b611ad5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b82600960008360ff1660ff1681526020019081526020016000208190555081600a60008360ff1660ff16815260200190815260200160002081905550505050565b600083600160008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16611bb2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f43617465676f727920646f65736e27742065786973742100000000000000000081525060200191505060405180910390fd5b600260008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16611c4b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f43617465676f7279206973206e6f74206f70656e21000000000000000000000081525060200191505060405180910390fd5b8585858560606004604051908082528060200260200182016040528015611c815781602001602082028038833980820191505090505b509050611c8e848361153a565b82600081518110611c9b57fe5b6020026020010183600381518110611caf57fe5b6020026020010182815250828152505050600081600081518110611ccf57fe5b602002602001015111611d4a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5072696365206e6f74207965742073657400000000000000000000000000000081525060200191505060405180910390fd5b80600081518110611d5757fe5b6020026020010151600860008660ff1660ff16815260200190815260200160002081905550611d9b81600381518110611d8c57fe5b60200260200101516001611704565b81600181518110611da857fe5b602002602001018181525050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614611e65576064600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050182600181518110611e3a57fe5b60200260200101510281611e4a57fe5b0481600281518110611e5857fe5b6020026020010181815250505b6000600a60008660ff1660ff16815260200190815260200160002054600960008760ff1660ff16815260200190815260200160002054611eba84600381518110611eab57fe5b60200260200101516000611704565b0281611ec257fe5b04905080341015611f1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061320c6024913960400191505060405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379cc6790856064601e86600281518110611f6e57fe5b602002602001015187600181518110611f8357fe5b6020026020010151030281611f9457fe5b046040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015611ffe57600080fd5b505af1158015612012573d6000803e3d6000fd5b50505050600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd85601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166064601e8760028151811061208957fe5b60200260200101518860018151811061209e57fe5b60200260200101510302816120af57fe5b04866002815181106120bd57fe5b6020026020010151876001815181106120d257fe5b602002602001015103036040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561217857600080fd5b505af115801561218c573d6000803e3d6000fd5b505050506040513d60208110156121a257600080fd5b810190808051906020019092919050505050600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336896c7f8b8b8e6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018361ffff1661ffff1681526020018260ff1660ff1681526020019350505050602060405180830381600087803b15801561227357600080fd5b505af1158015612287573d6000803e3d6000fd5b505050506040513d602081101561229d57600080fd5b8101908080519060200190929190505050506001975080341115612305578373ffffffffffffffffffffffffffffffffffffffff166108fc8234039081150290604051600060405180830381858888f19350505050158015612303573d6000803e3d6000fd5b505b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612728573373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156123db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546865207265666572616c2063616e6e6f74206265207468652073656e64657281525060200191505060405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415612460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180613230602b913960400191505060405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156124e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131c36023913960400191505060405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd85888560028151811061253257fe5b60200260200101516040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156125d657600080fd5b505af11580156125ea573d6000803e3d6000fd5b505050506040513d602081101561260057600080fd5b8101908080519060200190929190505050506126318260038151811061262257fe5b60200260200101516000611704565b8260018151811061263e57fe5b6020026020010181815250506064600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546005018360018151811061269c57fe5b602002602001015102816126ac57fe5b04826002815181106126ba57fe5b60200260200101818152505060008690508073ffffffffffffffffffffffffffffffffffffffff166108fc846002815181106126f257fe5b60200260200101519081150290604051600060405180830381858888f19350505050158015612725573d6000803e3d6000fd5b50505b50505050505050949350505050565b61273f611623565b6127b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60018260ff1614806127c6575060028260ff16145b806127d4575060038260ff16145b6127dd57600080fd5b600360008360ff1660ff16815260200190815260200160002060009054906101000a900460ff161561280e57600080fd5b600160008360ff1660ff16815260200190815260200160002060009054906101000a900460ff1661283e57600080fd5b80600260008460ff1660ff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60086020528060005260406000206000915090505481565b60096020528060005260406000206000915090505481565b6128ab611623565b61291d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600083600160008260ff1660ff16815260200190815260200160002060009054906101000a900460ff166129fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f43617465676f727920646f65736e27742065786973742100000000000000000081525060200191505060405180910390fd5b600260008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16612a96576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f43617465676f7279206973206e6f74206f70656e21000000000000000000000081525060200191505060405180910390fd5b85858585600080612aa7858461153a565b809250819350505060008211612b25576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5072696365206e6f74207965742073657400000000000000000000000000000081525060200191505060405180910390fd5b81600860008760ff1660ff168152602001908152602001600020819055506000612b50826000611704565b905080341015612bc8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4e6f7420656e6f7567682045746865722073656e74210000000000000000000081525060200191505060405180910390fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336896c7f8c8c8f6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018361ffff1661ffff1681526020018260ff1660ff1681526020019350505050602060405180830381600087803b158015612c8757600080fd5b505af1158015612c9b573d6000803e3d6000fd5b505050506040513d6020811015612cb157600080fd5b8101908080519060200190929190505050506001985080341115612d1f57600081340390503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612d1c573d6000803e3d6000fd5b50505b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614612fa7573373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612df5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546865207265666572616c2063616e6e6f74206265207468652073656e64657281525060200191505060405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180613230602b913960400191505060405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612eff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131c36023913960400191505060405180910390fd5b6000600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050190506000606482840281612f5457fe5b04905060008990508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612fa2573d6000803e3d6000fd5b505050505b5050505050505050949350505050565b612fbf611623565b613031576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61303a8161307e565b50565b600b60009054906101000a900460ff1681565b600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613104576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806131e66026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fe546865207265666572616c2063616e6e6f7420626520746865206e6577206f776e65724f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373427579696e67207769746820425a4e20726571756972657320736f6d6520457468657221546865207265666572616c2063616e6e6f7420626520746865207472616e616374696f6e206f726967696ea265627a7a723158207cdbbf9780834882f980a8807fec42da53d59ad8db1c79629ab36d03146fc8f564736f6c634300050b003200000000000000000000000018f64687e77c012d062bce0396fbbf7f21e11b77000000000000000000000000f4a01be26b2169deef116c0476676f6205ddf9df00000000000000000000000083f11770176d959b19f9cc6e2d5a051cb101bdaf000000000000000000000000729d19f657bd0614b4985cf1d82531c67569197b0000000000000000000000006524b87960c2d573ae514fd4181777e7842435d4
Deployed Bytecode
0x6080604052600436106101f85760003560e01c80638f4ffcb11161010d578063c768ad1a116100a0578063e5174e081161006f578063e5174e0814610bb5578063e950879314610c06578063f2fde38b14610c9d578063f8160b5014610cee578063fc0c546a14610d1d576101f8565b8063c768ad1a14610a30578063c8e5ae4c14610ac7578063ccba093214610b11578063d5deb15b14610b63576101f8565b8063aa30b420116100dc578063aa30b42014610909578063b404e0011461095d578063b51bcc0e14610988578063bea82b06146109de576101f8565b80638f4ffcb1146106e85780639a5ef369146108055780639c03facb14610860578063a68b8552146108b3576101f8565b80633d17604511610190578063715018a61161015f578063715018a6146105a657806373c81a8b146105bd578063762c8d1f146105fb5780638da5cb5b146106625780638f32d59b146106b9576101f8565b80633d17604514610454578063512ceb3d146104a65780635e19d05c146104f8578063690d5ff41461054f576101f8565b806324b5b280116101cc57806324b5b280146103165780632e07a5be1461036c5780632e1a7d4d146103be57806331729a45146103f9576101f8565b80627a7776146101fd57806301b49e821461024f57806321bf73841461026657806323539a84146102a4575b600080fd5b34801561020957600080fd5b506102396004803603602081101561022057600080fd5b81019080803560ff169060200190929190505050610d74565b6040518082815260200191505060405180910390f35b34801561025b57600080fd5b50610264610d8c565b005b34801561027257600080fd5b506102a26004803603602081101561028957600080fd5b81019080803560ff169060200190929190505050610e23565b005b3480156102b057600080fd5b50610300600480360360408110156102c757600080fd5b81019080803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f35565b6040518082815260200191505060405180910390f35b34801561032257600080fd5b506103526004803603602081101561033957600080fd5b81019080803560ff169060200190929190505050610f5a565b604051808215151515815260200191505060405180910390f35b34801561037857600080fd5b506103bc6004803603606081101561038f57600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050610f7a565b005b3480156103ca57600080fd5b506103f7600480360360208110156103e157600080fd5b8101908080359060200190929190505050611041565b005b34801561040557600080fd5b506104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506111dc565b005b34801561046057600080fd5b506104906004803603602081101561047757600080fd5b81019080803560ff1690602001909291905050506112be565b6040518082815260200191505060405180910390f35b3480156104b257600080fd5b506104e2600480360360208110156104c957600080fd5b81019080803560ff1690602001909291905050506112d6565b6040518082815260200191505060405180910390f35b34801561050457600080fd5b5061050d6112ee565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561055b57600080fd5b50610564611314565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156105b257600080fd5b506105bb61133a565b005b3480156105c957600080fd5b506105f9600480360360208110156105e057600080fd5b81019080803560ff169060200190929190505050611473565b005b34801561060757600080fd5b506106456004803603604081101561061e57600080fd5b81019080803560ff169060200190929190803561ffff16906020019092919050505061153a565b604051808381526020018281526020019250505060405180910390f35b34801561066e57600080fd5b506106776115fa565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156106c557600080fd5b506106ce611623565b604051808215151515815260200191505060405180910390f35b6107eb600480360360808110156106fe57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561076557600080fd5b82018360208201111561077757600080fd5b8035906020019184600183028401116401000000008311171561079957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611681565b604051808215151515815260200191505060405180910390f35b34801561081157600080fd5b5061084a6004803603604081101561082857600080fd5b8101908080359060200190929190803515159060200190929190505050611704565b6040518082815260200191505060405180910390f35b34801561086c57600080fd5b506108996004803603602081101561088357600080fd5b81019080803590602001909291905050506118a7565b604051808215151515815260200191505060405180910390f35b3480156108bf57600080fd5b506108ef600480360360208110156108d657600080fd5b81019080803560ff16906020019092919050505061195e565b604051808215151515815260200191505060405180910390f35b34801561091557600080fd5b5061095b6004803603606081101561092c57600080fd5b81019080803560ff1690602001909291908035906020019092919080351515906020019092919050505061197e565b005b34801561096957600080fd5b50610972611a36565b6040518082815260200191505060405180910390f35b34801561099457600080fd5b506109c4600480360360208110156109ab57600080fd5b81019080803560ff169060200190929190505050611a3b565b604051808215151515815260200191505060405180910390f35b3480156109ea57600080fd5b50610a2e60048036036060811015610a0157600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050611a5b565b005b610aad60048036036080811015610a4657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff169060200190929190505050611b16565b604051808215151515815260200191505060405180910390f35b348015610ad357600080fd5b50610b0f60048036036040811015610aea57600080fd5b81019080803560ff169060200190929190803515159060200190929190505050612737565b005b348015610b1d57600080fd5b50610b4d60048036036020811015610b3457600080fd5b81019080803560ff169060200190929190505050612873565b6040518082815260200191505060405180910390f35b348015610b6f57600080fd5b50610b9f60048036036020811015610b8657600080fd5b81019080803560ff16906020019092919050505061288b565b6040518082815260200191505060405180910390f35b348015610bc157600080fd5b50610c0460048036036020811015610bd857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506128a3565b005b610c8360048036036080811015610c1c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff169060200190929190505050612961565b604051808215151515815260200191505060405180910390f35b348015610ca957600080fd5b50610cec60048036036020811015610cc057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612fb7565b005b348015610cfa57600080fd5b50610d0361303d565b604051808215151515815260200191505060405180910390f35b348015610d2957600080fd5b50610d32613050565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600a6020528060005260406000206000915090505481565b610d94611623565b610e06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000600b60006101000a81548160ff021916908315150217905550565b610e2b611623565b610e9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600360008260ff1660ff16815260200190815260200160002060009054906101000a900460ff1615610ece57600080fd5b6000600260008360ff1660ff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600360008360ff1660ff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6005602052816000526040600020602052806000526040600020600091509150505481565b60026020528060005260406000206000915054906101000a900460ff1681565b610f82611623565b610ff4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b81831161100057600080fd5b82600660008360ff1660ff1681526020019081526020016000208190555081600760008360ff1660ff16815260200190815260200160002081905550505050565b611049611623565b6110bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60003073ffffffffffffffffffffffffffffffffffffffff163190508082111561114d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f52657175657374656420746f206d75636800000000000000000000000000000081525060200191505060405180910390fd5b60006111576115fa565b90508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f1935050505015801561119f573d6000803e3d6000fd5b507f4e70a604b23a8edee2b1d0a656e9b9c00b73ad8bb1afc2c59381ee9f69197de7836040518082815260200191505060405180910390a1505050565b6111e4611623565b611256576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6005811161126357600080fd5b605f811061127057600080fd5b60058103905080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b60076020528060005260406000206000915090505481565b60066020528060005260406000206000915090505481565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611342611623565b6113b4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61147b611623565b6114ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600b60009054906101000a900460ff1661150657600080fd5b60018060008360ff1660ff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008060008361ffff161161154e57600080fd5b6000600660008660ff1660ff1681526020019081526020016000205490506000600760008760ff1660ff1681526020019081526020016000205490506000600860008860ff1660ff1681526020019081526020016000205490506000819050600080905060008090505b8861ffff168110156115e75784868502816115cf57fe5b049250829350828201915080806001019150506115b8565b5081819650965050505050509250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611665613076565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60008060008084806020019051606081101561169c57600080fd5b8101908080519060200190929190805190602001909291908051906020019092919050505082925080935081945082955050505060018161ffff1610156116e257600080fd5b60008890506116f384848385611b16565b506001945050505050949350505050565b600081156117c157600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3908e1b846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561177f57600080fd5b505afa158015611793573d6000803e3d6000fd5b505050506040513d60208110156117a957600080fd5b810190808051906020019092919050505090506118a1565b600080600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166359e02dd76040518163ffffffff1660e01b8152600401604080518083038186803b15801561182b57600080fd5b505afa15801561183f573d6000803e3d6000fd5b505050506040513d604081101561185557600080fd5b810190808051906020019092919080519060200190929190505050809350819250505060008160001c9050670de0b6b3a7640000818161189157fe5b04868161189a57fe5b0493505050505b92915050565b6000600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f558e79836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561191c57600080fd5b505afa158015611930573d6000803e3d6000fd5b505050506040513d602081101561194657600080fd5b81019080805190602001909291905050509050919050565b60036020528060005260406000206000915054906101000a900460ff1681565b611986611623565b6119f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000670de0b6b3a764000090508115611a1057600190505b808302600860008660ff1660ff1681526020019081526020016000208190555050505050565b600581565b60016020528060005260406000206000915054906101000a900460ff1681565b611a63611623565b611ad5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b82600960008360ff1660ff1681526020019081526020016000208190555081600a60008360ff1660ff16815260200190815260200160002081905550505050565b600083600160008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16611bb2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f43617465676f727920646f65736e27742065786973742100000000000000000081525060200191505060405180910390fd5b600260008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16611c4b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f43617465676f7279206973206e6f74206f70656e21000000000000000000000081525060200191505060405180910390fd5b8585858560606004604051908082528060200260200182016040528015611c815781602001602082028038833980820191505090505b509050611c8e848361153a565b82600081518110611c9b57fe5b6020026020010183600381518110611caf57fe5b6020026020010182815250828152505050600081600081518110611ccf57fe5b602002602001015111611d4a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5072696365206e6f74207965742073657400000000000000000000000000000081525060200191505060405180910390fd5b80600081518110611d5757fe5b6020026020010151600860008660ff1660ff16815260200190815260200160002081905550611d9b81600381518110611d8c57fe5b60200260200101516001611704565b81600181518110611da857fe5b602002602001018181525050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614611e65576064600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050182600181518110611e3a57fe5b60200260200101510281611e4a57fe5b0481600281518110611e5857fe5b6020026020010181815250505b6000600a60008660ff1660ff16815260200190815260200160002054600960008760ff1660ff16815260200190815260200160002054611eba84600381518110611eab57fe5b60200260200101516000611704565b0281611ec257fe5b04905080341015611f1e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061320c6024913960400191505060405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379cc6790856064601e86600281518110611f6e57fe5b602002602001015187600181518110611f8357fe5b6020026020010151030281611f9457fe5b046040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015611ffe57600080fd5b505af1158015612012573d6000803e3d6000fd5b50505050600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd85601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166064601e8760028151811061208957fe5b60200260200101518860018151811061209e57fe5b60200260200101510302816120af57fe5b04866002815181106120bd57fe5b6020026020010151876001815181106120d257fe5b602002602001015103036040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561217857600080fd5b505af115801561218c573d6000803e3d6000fd5b505050506040513d60208110156121a257600080fd5b810190808051906020019092919050505050600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336896c7f8b8b8e6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018361ffff1661ffff1681526020018260ff1660ff1681526020019350505050602060405180830381600087803b15801561227357600080fd5b505af1158015612287573d6000803e3d6000fd5b505050506040513d602081101561229d57600080fd5b8101908080519060200190929190505050506001975080341115612305578373ffffffffffffffffffffffffffffffffffffffff166108fc8234039081150290604051600060405180830381858888f19350505050158015612303573d6000803e3d6000fd5b505b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614612728573373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156123db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546865207265666572616c2063616e6e6f74206265207468652073656e64657281525060200191505060405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415612460576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180613230602b913960400191505060405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156124e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131c36023913960400191505060405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd85888560028151811061253257fe5b60200260200101516040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156125d657600080fd5b505af11580156125ea573d6000803e3d6000fd5b505050506040513d602081101561260057600080fd5b8101908080519060200190929190505050506126318260038151811061262257fe5b60200260200101516000611704565b8260018151811061263e57fe5b6020026020010181815250506064600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546005018360018151811061269c57fe5b602002602001015102816126ac57fe5b04826002815181106126ba57fe5b60200260200101818152505060008690508073ffffffffffffffffffffffffffffffffffffffff166108fc846002815181106126f257fe5b60200260200101519081150290604051600060405180830381858888f19350505050158015612725573d6000803e3d6000fd5b50505b50505050505050949350505050565b61273f611623565b6127b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60018260ff1614806127c6575060028260ff16145b806127d4575060038260ff16145b6127dd57600080fd5b600360008360ff1660ff16815260200190815260200160002060009054906101000a900460ff161561280e57600080fd5b600160008360ff1660ff16815260200190815260200160002060009054906101000a900460ff1661283e57600080fd5b80600260008460ff1660ff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60086020528060005260406000206000915090505481565b60096020528060005260406000206000915090505481565b6128ab611623565b61291d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600083600160008260ff1660ff16815260200190815260200160002060009054906101000a900460ff166129fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f43617465676f727920646f65736e27742065786973742100000000000000000081525060200191505060405180910390fd5b600260008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16612a96576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f43617465676f7279206973206e6f74206f70656e21000000000000000000000081525060200191505060405180910390fd5b85858585600080612aa7858461153a565b809250819350505060008211612b25576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5072696365206e6f74207965742073657400000000000000000000000000000081525060200191505060405180910390fd5b81600860008760ff1660ff168152602001908152602001600020819055506000612b50826000611704565b905080341015612bc8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4e6f7420656e6f7567682045746865722073656e74210000000000000000000081525060200191505060405180910390fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336896c7f8c8c8f6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018361ffff1661ffff1681526020018260ff1660ff1681526020019350505050602060405180830381600087803b158015612c8757600080fd5b505af1158015612c9b573d6000803e3d6000fd5b505050506040513d6020811015612cb157600080fd5b8101908080519060200190929190505050506001985080341115612d1f57600081340390503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612d1c573d6000803e3d6000fd5b50505b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614612fa7573373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612df5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546865207265666572616c2063616e6e6f74206265207468652073656e64657281525060200191505060405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612e7a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b815260200180613230602b913960400191505060405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612eff576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131c36023913960400191505060405180910390fd5b6000600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050190506000606482840281612f5457fe5b04905060008990508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612fa2573d6000803e3d6000fd5b505050505b5050505050505050949350505050565b612fbf611623565b613031576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61303a8161307e565b50565b600b60009054906101000a900460ff1681565b600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613104576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806131e66026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fe546865207265666572616c2063616e6e6f7420626520746865206e6577206f776e65724f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373427579696e67207769746820425a4e20726571756972657320736f6d6520457468657221546865207265666572616c2063616e6e6f7420626520746865207472616e616374696f6e206f726967696ea265627a7a723158207cdbbf9780834882f980a8807fec42da53d59ad8db1c79629ab36d03146fc8f564736f6c634300050b0032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000018f64687e77c012d062bce0396fbbf7f21e11b77000000000000000000000000f4a01be26b2169deef116c0476676f6205ddf9df00000000000000000000000083f11770176d959b19f9cc6e2d5a051cb101bdaf000000000000000000000000729d19f657bd0614b4985cf1d82531c67569197b0000000000000000000000006524b87960c2d573ae514fd4181777e7842435d4
-----Decoded View---------------
Arg [0] : tokenAddress (address): 0x18F64687E77C012D062BCe0396FBbF7f21e11B77
Arg [1] : tokenFactory (address): 0xF4a01Be26B2169dEeF116c0476676f6205ddf9DF
Arg [2] : gp (address): 0x83f11770176d959B19F9cC6E2d5a051cb101bdAf
Arg [3] : isd (address): 0x729D19f657BD0614b4985Cf1D82531c67569197B
Arg [4] : bzn_address (address): 0x6524B87960c2d573AE514fd4181777E7842435d4
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 00000000000000000000000018f64687e77c012d062bce0396fbbf7f21e11b77
Arg [1] : 000000000000000000000000f4a01be26b2169deef116c0476676f6205ddf9df
Arg [2] : 00000000000000000000000083f11770176d959b19f9cc6e2d5a051cb101bdaf
Arg [3] : 000000000000000000000000729d19f657bd0614b4985cf1d82531c67569197b
Arg [4] : 0000000000000000000000006524b87960c2d573ae514fd4181777e7842435d4
Deployed Bytecode Sourcemap
127161:12046:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128761:57;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128761:57:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128761:57:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;133868:98;;8:9:-1;5:2;;;30:1;27;20:12;5:2;133868:98:0;;;:::i;:::-;;134845:201;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134845:201:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;134845:201:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;128151:74;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128151:74:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128151:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;127823:42;;8:9:-1;5:2;;;30:1;27;20:12;5:2;127823:42:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;127823:42:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;134373:248;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134373:248:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;134373:248:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;135836:320;;8:9:-1;5:2;;;30:1;27;20:12;5:2;135836:320:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;135836:320:0;;;;;;;;;;;;;;;;;:::i;:::-;;134031:267;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134031:267:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;134031:267:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;128481:52;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128481:52:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128481:52:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;128418:56;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128418:56:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128418:56:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;129097:23;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129097:23:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;129127:22;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129127:22:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;66172:140;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66172:140:0;;;:::i;:::-;;133700:156;;8:9:-1;5:2;;;30:1;27;20:12;5:2;133700:156:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;133700:156:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;137710:796;;8:9:-1;5:2;;;30:1;27;20:12;5:2;137710:796:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;137710:796:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;65361:79;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65361:79:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;65727:94;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65727:94:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;138686:518;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;138686:518:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;138686:518:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;138686:518: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;138686:518: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;;138686:518:0;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;137191:430;;8:9:-1;5:2;;;30:1;27;20:12;5:2;137191:430:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;137191:430:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;138567:107;;8:9:-1;5:2;;;30:1;27;20:12;5:2;138567:107:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;138567:107:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;127872:44;;8:9:-1;5:2;;;30:1;27;20:12;5:2;127872:44:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;127872:44:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;135464:243;;8:9:-1;5:2;;;30:1;27;20:12;5:2;135464:243:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;135464:243:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;127681:46;;8:9:-1;5:2;;;30:1;27;20:12;5:2;127681:46:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;127772:44;;8:9:-1;5:2;;;30:1;27;20:12;5:2;127772:44:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;127772:44:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;134633:200;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134633:200:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;134633:200:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;136438:299;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;136438:299:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;135105:280;;8:9:-1;5:2;;;30:1;27;20:12;5:2;135105:280:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;135105:280:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;128587:46;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128587:46:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128587:46:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;128701:53;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128701:53:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128701:53:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;136168:117;;8:9:-1;5:2;;;30:1;27;20:12;5:2;136168:117:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;136168:117:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;136890:289;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;136890:289:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;66467:109;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66467:109:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;66467:109:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;128825:38;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128825:38:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;128902:21;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128902:21:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;128761:57;;;;;;;;;;;;;;;;;:::o;133868:98::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133953:5;133931:19;;:27;;;;;;;;;;;;;;;;;;133868:98::o;134845:201::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134920:14;:24;134935:8;134920:24;;;;;;;;;;;;;;;;;;;;;;;;;134919:25;134911:34;;;;;;134991:5;134966:12;:22;134979:8;134966:22;;;;;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;;;135034:4;135007:14;:24;135022:8;135007:24;;;;;;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;134845:201;:::o;128151:74::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;127823:42::-;;;;;;;;;;;;;;;;;;;;;;:::o;134373:248::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134496:4;134485:8;:15;134477:24;;;;;;134558:8;134522:23;:33;134546:8;134522:33;;;;;;;;;;;;;;;:44;;;;134609:4;134577:19;:29;134597:8;134577:29;;;;;;;;;;;;;;;:36;;;;134373:248;;;:::o;135836:320::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135898:15;135924:4;135916:21;;;135898:39;;135968:7;135958:6;:17;;135950:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136018:22;136059:7;:5;:7::i;:::-;136018:50;;136089:6;:15;;:23;136105:6;136089:23;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;136089:23:0;136130:18;136141:6;136130:18;;;;;;;;;;;;;;;;;;65630:1;;135836:320;:::o;134031:267::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;127726:1;134125:7;:28;134117:37;;;;;;134183:2;134173:7;:12;134165:21;;;;;;127726:1;134207:7;:28;134197:38;;134283:7;134256:14;:24;134271:8;134256:24;;;;;;;;;;;;;;;:34;;;;134031:267;;:::o;128481:52::-;;;;;;;;;;;;;;;;;:::o;128418:56::-;;;;;;;;;;;;;;;;;:::o;129097:23::-;;;;;;;;;;;;;:::o;129127:22::-;;;;;;;;;;;;;:::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;133700:156::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133776:19;;;;;;;;;;;133768:28;;;;;;133844:4;133817:14;:24;133832:8;133817:24;;;;;;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;133700:156;:::o;137710:796::-;137781:7;137790;137828:1;137818:7;:11;;;137810:20;;;;;;137841:15;137859:23;:33;137883:8;137859:33;;;;;;;;;;;;;;;;137841:51;;137903:12;137918:19;:29;137938:8;137918:29;;;;;;;;;;;;;;;;137903:44;;137960:20;137983:13;:23;137997:8;137983:23;;;;;;;;;;;;;;;;137960:46;;138017:17;138037:12;138017:32;;138060:18;138081:1;138060:22;;138191:6;138200:1;138191:10;;138186:210;138207:7;138203:11;;:1;:11;138186:210;;;138275:4;138264:7;138249:12;:22;138248:31;;;;;;138236:43;;138323:9;138308:24;;138375:9;138361:23;;;;138216:3;;;;;;;138186:210;;;;138476:9;138487:10;138468:30;;;;;;;;;137710:796;;;;;:::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;138686:518::-;138812:4;138829:15;138855:14;138880;138957:4;138946:42;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;138946:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;138915:73;;;;;;;;;;;;;;;139028:1;139017:7;:12;;;;139009:21;;;;;;139051;139091:4;139051:46;;139119:45;139130:7;139139:8;139149:5;139156:7;139119:10;:45::i;:::-;;139192:4;139185:11;;;;;;138686:518;;;;;;:::o;137191:430::-;137259:7;137283:5;137279:335;;;137312:7;;;;;;;;;;;:15;;;137328:8;137312:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;137312:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;137312:25:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;137312:25:0;;;;;;;;;;;;;;;;137305:32;;;;137279:335;137370:9;137394:11;137434:7;;;;;;;;;;;:12;;;:14;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;137434:14:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;137434:14:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;137434:14:0;;;;;;;;;;;;;;;;;;;;;;;;;137420:28;;;;;;;;137481:29;137521:3;137513:12;;137481:44;;137597:4;137573:21;:28;;;;;;137561:8;:41;;;;;;137554:48;;;;;137191:430;;;;;:::o;138567:107::-;138620:4;138644:5;;;;;;;;;;;:12;;;138657:8;138644:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;138644:22:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;138644:22:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;138644:22:0;;;;;;;;;;;;;;;;138637:29;;138567:107;;;:::o;127872:44::-;;;;;;;;;;;;;;;;;;;;;;:::o;135464:243::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135553:16;135572:4;135553:23;;135591:5;135587:50;;;135624:1;135613:12;;135587:50;135691:8;135683:5;:16;135657:13;:23;135671:8;135657:23;;;;;;;;;;;;;;;:42;;;;65630:1;135464:243;;;:::o;127681:46::-;127726:1;127681:46;:::o;127772:44::-;;;;;;;;;;;;;;;;;;;;;;:::o;134633:200::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134766:7;134733:20;:30;134754:8;134733:30;;;;;;;;;;;;;;;:40;;;;134821:4;134784:24;:34;134809:8;134784:34;;;;;;;;;;;;;;;:41;;;;134633:200;;;:::o;136438:299::-;136631:4;136549:8;129334:14;:24;129349:8;129334:24;;;;;;;;;;;;;;;;;;;;;;;;;129326:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;129405:12;:22;129418:8;129405:22;;;;;;;;;;;;;;;;;;;;;;;;;129397:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136568:7;136577:8;136587:9;136598:7;131028:23;131068:1;131054:16;;;;;;;;;;;;;;;;;;;;;;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;131054:16:0;;;;131028:42;;131188:27;131197:8;131207:7;131188:8;:27::i;:::-;131164:6;131171:1;131164:9;;;;;;;;;;;;;131175:6;131182:1;131175:9;;;;;;;;;;;;;131163:52;;;;;;;;;;131246:1;131234:6;131241:1;131234:9;;;;;;;;;;;;;;:13;131226:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131320:6;131327:1;131320:9;;;;;;;;;;;;;;131294:13;:23;131308:8;131294:23;;;;;;;;;;;;;;;:35;;;;131362:24;131370:6;131377:1;131370:9;;;;;;;;;;;;;;131381:4;131362:7;:24::i;:::-;131350:6;131357:1;131350:9;;;;;;;;;;;;;:36;;;;;131545:1;131526:21;;:7;:21;;;131522:132;;131639:3;131611:14;:23;131626:7;131611:23;;;;;;;;;;;;;;;;127726:1;131590:44;131577:6;131584:1;131577:9;;;;;;;;;;;;;;:58;131576:66;;;;;;131564:6;131571:1;131564:9;;;;;;;;;;;;;:78;;;;;131522:132;131674:21;131761:24;:34;131786:8;131761:34;;;;;;;;;;;;;;;;131727:20;:30;131748:8;131727:30;;;;;;;;;;;;;;;;131699:25;131707:6;131714:1;131707:9;;;;;;;;;;;;;;131718:5;131699:7;:25::i;:::-;:58;131698:97;;;;;;131674:121;;131837:13;131824:9;:26;;131816:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131912:3;;;;;;;;;;;:12;;;131925:9;131970:3;131964:2;131951:6;131958:1;131951:9;;;;;;;;;;;;;;131939:6;131946:1;131939:9;;;;;;;;;;;;;;:21;131938:28;131937:36;;;;;;131912:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;131912:63:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;131912:63:0;;;;131986:3;;;;;;;;;;;:16;;;132003:9;132014:8;;;;;;;;;;;132082:3;132076:2;132063:6;132070:1;132063:9;;;;;;;;;;;;;;132051:6;132058:1;132051:9;;;;;;;;;;;;;;:21;132050:28;132049:36;;;;;;132036:6;132043:1;132036:9;;;;;;;;;;;;;;132024:6;132031:1;132024:9;;;;;;;;;;;;;;:21;:62;131986:101;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;131986:101:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;131986:101:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;131986:101:0;;;;;;;;;;;;;;;;;136648:7;;;;;;;;;;;:15;;;136664:9;136675:7;136684:8;136648:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;136648:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;136648:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;136648:45:0;;;;;;;;;;;;;;;;;136725:4;136718:11;;132146:13;132134:9;:25;132130:103;;;132176:9;:18;;:45;132207:13;132195:9;:25;132176:45;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132176:45:0;132130:103;132276:1;132257:21;;:7;:21;;;132253:655;;132314:10;132303:21;;:7;:21;;;;132295:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132395:9;132384:20;;:7;:20;;;;132376:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132486:9;132475:20;;:7;:20;;;;132467:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132564:3;;;;;;;;;;;:16;;;132581:9;132592:7;132601:6;132608:1;132601:9;;;;;;;;;;;;;;132564:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132564:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132564:47:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;132564:47:0;;;;;;;;;;;;;;;;;132652:25;132660:6;132667:1;132660:9;;;;;;;;;;;;;;132671:5;132652:7;:25::i;:::-;132640:6;132647:1;132640:9;;;;;;;;;;;;;:37;;;;;132767:3;132739:14;:23;132754:7;132739:23;;;;;;;;;;;;;;;;127726:1;132718:44;132705:6;132712:1;132705:9;;;;;;;;;;;;;;:58;132704:66;;;;;;132692:6;132699:1;132692:9;;;;;;;;;;;;;:78;;;;;132799:24;132842:7;132799:52;;132868:8;:17;;:28;132886:6;132893:1;132886:9;;;;;;;;;;;;;;132868:28;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132868:28:0;132253:655;;129464:1;;;;;;136438:299;;;;;;;:::o;135105:280::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135202:1;135190:8;:13;;;:30;;;;135219:1;135207:8;:13;;;135190:30;:47;;;;135236:1;135224:8;:13;;;135190:47;135182:56;;;;;;135258:14;:24;135273:8;135258:24;;;;;;;;;;;;;;;;;;;;;;;;;135257:25;135249:34;;;;;;135302:14;:24;135317:8;135302:24;;;;;;;;;;;;;;;;;;;;;;;;;135294:33;;;;;;135373:4;135348:12;:22;135361:8;135348:22;;;;;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;135105:280;;:::o;128587:46::-;;;;;;;;;;;;;;;;;:::o;128701:53::-;;;;;;;;;;;;;;;;;:::o;136168:117::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136264:12;136246:7;;:31;;;;;;;;;;;;;;;;;;136168:117;:::o;136890:289::-;137077:4;136995:8;129334:14;:24;129349:8;129334:24;;;;;;;;;;;;;;;;;;;;;;;;;129326:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;129405:12;:22;129418:8;129405:22;;;;;;;;;;;;;;;;;;;;;;;;;129397:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137014:7;137023:8;137033:9;137044:7;129628:16;129655:18;129709:27;129718:8;129728:7;129709:8;:27::i;:::-;129684:52;;;;;;;;129766:1;129755:8;:12;129747:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;129836:8;129810:13;:23;129824:8;129810:23;;;;;;;;;;;;;;;:34;;;;129883:13;129899:26;129907:10;129919:5;129899:7;:26::i;:::-;129883:42;;129967:5;129954:9;:18;;129946:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137094:7;;;;;;;;;;;:15;;;137110:9;137121:7;137130:8;137094:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;137094:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;137094:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;137094:45:0;;;;;;;;;;;;;;;;;137167:4;137160:11;;130058:5;130046:9;:17;130042:128;;;130080:14;130109:5;130097:9;:17;130080:34;;130131:10;:19;;:27;130151:6;130131:27;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;130131:27:0;130042:128;;130213:1;130194:21;;:7;:21;;;130190:668;;130251:10;130240:21;;:7;:21;;;;130232:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130332:9;130321:20;;:7;:20;;;;130313:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130423:9;130412:20;;:7;:20;;;;130404:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130584:22;130630:14;:23;130645:7;130630:23;;;;;;;;;;;;;;;;127726:1;130609:44;130584:69;;130670:17;130717:3;130699:14;130691:5;:22;130690:30;;;;;;130670:50;;130749:24;130792:7;130749:52;;130818:8;:17;;:28;130836:9;130818:28;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;130818:28:0;130190:668;;;;129464:1;;;;;;;136890:289;;;;;;;:::o;66467:109::-;65573:9;:7;:9::i;:::-;65565:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66540:28;66559:8;66540:18;:28::i;:::-;66467:109;:::o;128825:38::-;;;;;;;;;;;;;:::o;128902:21::-;;;;;;;;;;;;;:::o;27961:98::-;28006:15;28041:10;28034:17;;27961:98;:::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
Swarm Source
bzzr://7cdbbf9780834882f980a8807fec42da53d59ad8db1c79629ab36d03146fc8f5
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Token Allocations
ETH
100.00%
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $1,955.52 | 0.000000000000000007 | <$0.000001 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.