Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0.000002194920981487 ETH
Eth Value
Less Than $0.01 (@ $2,347.63/ETH)Latest 25 from a total of 345 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Buy With Ether | 13125653 | 1660 days ago | IN | 0.01745656 ETH | 0.01728766 | ||||
| Buy With Ether | 13125615 | 1660 days ago | IN | 0.08362814 ETH | 0.02026036 | ||||
| Buy With Ether | 13123955 | 1660 days ago | IN | 0.06978263 ETH | 0.02373329 | ||||
| Buy With Ether | 13123924 | 1660 days ago | IN | 0.0872392 ETH | 0.03111503 | ||||
| Buy With Ether | 13123370 | 1660 days ago | IN | 0.0567207 ETH | 0.02676132 | ||||
| Buy With Ether | 13116253 | 1661 days ago | IN | 0.00435855 ETH | 0.020583 | ||||
| Buy With Ether | 13115337 | 1661 days ago | IN | 0.13935612 ETH | 0.02089917 | ||||
| Buy With Ether | 13114936 | 1661 days ago | IN | 0.04354957 ETH | 0.02600847 | ||||
| Buy With Ether | 13113439 | 1662 days ago | IN | 0.08356963 ETH | 0.01735617 | ||||
| Buy With Ether | 13113424 | 1662 days ago | IN | 0.12524483 ETH | 0.02148646 | ||||
| Buy With Ether | 13112169 | 1662 days ago | IN | 0.08690344 ETH | 0.02537653 | ||||
| Buy With Ether | 13109136 | 1662 days ago | IN | 0.34717354 ETH | 0.04850785 | ||||
| Buy With Ether | 13107146 | 1663 days ago | IN | 0.12511341 ETH | 0.03053782 | ||||
| Buy With Ether | 13105539 | 1663 days ago | IN | 0.08690344 ETH | 0.02159242 | ||||
| Buy With Ether | 13100757 | 1664 days ago | IN | 0.12498214 ETH | 0.01740509 | ||||
| Buy With Ether | 13100757 | 1664 days ago | IN | 0.08266795 ETH | 0.00275853 | ||||
| Buy With Ether | 13100757 | 1664 days ago | IN | 0.12402364 ETH | 0.00276587 | ||||
| Buy With Ether | 13098633 | 1664 days ago | IN | 0.08324856 ETH | 0.0286966 | ||||
| Buy With Ether | 13098482 | 1664 days ago | IN | 0.41536997 ETH | 0.02314633 | ||||
| Buy With Ether | 13098450 | 1664 days ago | IN | 0.41391897 ETH | 0.02553691 | ||||
| Buy With Ether | 13098404 | 1664 days ago | IN | 0.34544222 ETH | 0.02715414 | ||||
| Buy With Ether | 13097386 | 1664 days ago | IN | 0.08664314 ETH | 0.03337015 | ||||
| Buy With Ether | 13097040 | 1664 days ago | IN | 0.12049735 ETH | 0.02278237 | ||||
| Buy With Ether | 13091489 | 1665 days ago | IN | 0.0259423 ETH | 0.01864945 | ||||
| Buy With Ether | 13086245 | 1666 days ago | IN | 0.04318532 ETH | 0.01536296 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| - | 13152858 | 1656 days ago | 22.12447 ETH | ||||
| - | 13125653 | 1660 days ago | 0.00008684 ETH | ||||
| - | 13125615 | 1660 days ago | 0.00041606 ETH | ||||
| - | 13123955 | 1660 days ago | 0.00034717 ETH | ||||
| - | 13123370 | 1660 days ago | 0.00028219 ETH | ||||
| - | 13116253 | 1661 days ago | 0.00002168 ETH | ||||
| - | 13115337 | 1661 days ago | 0.00069331 ETH | ||||
| - | 13114936 | 1661 days ago | 0.00021666 ETH | ||||
| - | 13113439 | 1662 days ago | 0.00041576 ETH | ||||
| - | 13113424 | 1662 days ago | 0.0006231 ETH | ||||
| - | 13112169 | 1662 days ago | 0.00043235 ETH | ||||
| - | 13109136 | 1662 days ago | 0.00172723 ETH | ||||
| - | 13107146 | 1663 days ago | 0.00062245 ETH | ||||
| - | 13100757 | 1664 days ago | 0.0006218 ETH | ||||
| - | 13098633 | 1664 days ago | 0.00041417 ETH | ||||
| - | 13098482 | 1664 days ago | 0.00206651 ETH | ||||
| - | 13098450 | 1664 days ago | 0.00205929 ETH | ||||
| - | 13098404 | 1664 days ago | 0.00171861 ETH | ||||
| - | 13097386 | 1664 days ago | 0.00043106 ETH | ||||
| - | 13097040 | 1664 days ago | 0.00059948 ETH | ||||
| - | 13091489 | 1665 days ago | 0.00012906 ETH | ||||
| - | 13086245 | 1666 days ago | 0.00021485 ETH | ||||
| - | 13086219 | 1666 days ago | 0.00021453 ETH | ||||
| - | 13085597 | 1666 days ago | 0.00085459 ETH | ||||
| - | 13085539 | 1666 days ago | 0.00085246 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
GunPreOrder
Compiler Version
v0.5.17+commit.d19bba13
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2020-03-29
*/
/**
*Submitted for verification at Etherscan.io on 2019-10-18
*/
pragma solidity ^0.5.5;
library strings {
struct slice {
uint _len;
uint _ptr;
}
function memcpy(uint dest, uint src, uint len) private pure {
// Copy word-length chunks while possible
for(; len >= 32; len -= 32) {
assembly {
mstore(dest, mload(src))
}
dest += 32;
src += 32;
}
// Copy remaining bytes
uint mask = 256 ** (32 - len) - 1;
assembly {
let srcpart := and(mload(src), not(mask))
let destpart := and(mload(dest), mask)
mstore(dest, or(destpart, srcpart))
}
}
/*
* @dev Returns a slice containing the entire string.
* @param self The string to make a slice from.
* @return A newly allocated slice containing the entire string.
*/
function toSlice(string memory self) internal pure returns (slice memory) {
uint ptr;
assembly {
ptr := add(self, 0x20)
}
return slice(bytes(self).length, ptr);
}
/*
* @dev Returns the length of a null-terminated bytes32 string.
* @param self The value to find the length of.
* @return The length of the string, from 0 to 32.
*/
function len(bytes32 self) internal pure returns (uint) {
uint ret;
if (self == 0)
return 0;
if (uint(self) & 0xffffffffffffffffffffffffffffffff == 0) {
ret += 16;
self = bytes32(uint(self) / 0x100000000000000000000000000000000);
}
if (uint(self) & 0xffffffffffffffff == 0) {
ret += 8;
self = bytes32(uint(self) / 0x10000000000000000);
}
if (uint(self) & 0xffffffff == 0) {
ret += 4;
self = bytes32(uint(self) / 0x100000000);
}
if (uint(self) & 0xffff == 0) {
ret += 2;
self = bytes32(uint(self) / 0x10000);
}
if (uint(self) & 0xff == 0) {
ret += 1;
}
return 32 - ret;
}
/*
* @dev Returns a slice containing the entire bytes32, interpreted as a
* null-terminated utf-8 string.
* @param self The bytes32 value to convert to a slice.
* @return A new slice containing the value of the input argument up to the
* first null.
*/
function toSliceB32(bytes32 self) internal pure returns (slice memory ret) {
// Allocate space for `self` in memory, copy it there, and point ret at it
assembly {
let ptr := mload(0x40)
mstore(0x40, add(ptr, 0x20))
mstore(ptr, self)
mstore(add(ret, 0x20), ptr)
}
ret._len = len(self);
}
/*
* @dev Returns a new slice containing the same data as the current slice.
* @param self The slice to copy.
* @return A new slice containing the same data as `self`.
*/
function copy(slice memory self) internal pure returns (slice memory) {
return slice(self._len, self._ptr);
}
/*
* @dev Copies a slice to a new string.
* @param self The slice to copy.
* @return A newly allocated string containing the slice's text.
*/
function toString(slice memory self) internal pure returns (string memory) {
string memory ret = new string(self._len);
uint retptr;
assembly { retptr := add(ret, 32) }
memcpy(retptr, self._ptr, self._len);
return ret;
}
/*
* @dev Returns the length in runes of the slice. Note that this operation
* takes time proportional to the length of the slice; avoid using it
* in loops, and call `slice.empty()` if you only need to know whether
* the slice is empty or not.
* @param self The slice to operate on.
* @return The length of the slice in runes.
*/
function len(slice memory self) internal pure returns (uint l) {
// Starting at ptr-31 means the LSB will be the byte we care about
uint ptr = self._ptr - 31;
uint end = ptr + self._len;
for (l = 0; ptr < end; l++) {
uint8 b;
assembly { b := and(mload(ptr), 0xFF) }
if (b < 0x80) {
ptr += 1;
} else if(b < 0xE0) {
ptr += 2;
} else if(b < 0xF0) {
ptr += 3;
} else if(b < 0xF8) {
ptr += 4;
} else if(b < 0xFC) {
ptr += 5;
} else {
ptr += 6;
}
}
}
/*
* @dev Returns true if the slice is empty (has a length of 0).
* @param self The slice to operate on.
* @return True if the slice is empty, False otherwise.
*/
function empty(slice memory self) internal pure returns (bool) {
return self._len == 0;
}
/*
* @dev Returns a positive number if `other` comes lexicographically after
* `self`, a negative number if it comes before, or zero if the
* contents of the two slices are equal. Comparison is done per-rune,
* on unicode codepoints.
* @param self The first slice to compare.
* @param other The second slice to compare.
* @return The result of the comparison.
*/
function compare(slice memory self, slice memory other) internal pure returns (int) {
uint shortest = self._len;
if (other._len < self._len)
shortest = other._len;
uint selfptr = self._ptr;
uint otherptr = other._ptr;
for (uint idx = 0; idx < shortest; idx += 32) {
uint a;
uint b;
assembly {
a := mload(selfptr)
b := mload(otherptr)
}
if (a != b) {
// Mask out irrelevant bytes and check again
uint256 mask = uint256(-1); // 0xffff...
if(shortest < 32) {
mask = ~(2 ** (8 * (32 - shortest + idx)) - 1);
}
uint256 diff = (a & mask) - (b & mask);
if (diff != 0)
return int(diff);
}
selfptr += 32;
otherptr += 32;
}
return int(self._len) - int(other._len);
}
/*
* @dev Returns true if the two slices contain the same text.
* @param self The first slice to compare.
* @param self The second slice to compare.
* @return True if the slices are equal, false otherwise.
*/
function equals(slice memory self, slice memory other) internal pure returns (bool) {
return compare(self, other) == 0;
}
/*
* @dev Extracts the first rune in the slice into `rune`, advancing the
* slice to point to the next rune and returning `self`.
* @param self The slice to operate on.
* @param rune The slice that will contain the first rune.
* @return `rune`.
*/
function nextRune(slice memory self, slice memory rune) internal pure returns (slice memory) {
rune._ptr = self._ptr;
if (self._len == 0) {
rune._len = 0;
return rune;
}
uint l;
uint b;
// Load the first byte of the rune into the LSBs of b
assembly { b := and(mload(sub(mload(add(self, 32)), 31)), 0xFF) }
if (b < 0x80) {
l = 1;
} else if(b < 0xE0) {
l = 2;
} else if(b < 0xF0) {
l = 3;
} else {
l = 4;
}
// Check for truncated codepoints
if (l > self._len) {
rune._len = self._len;
self._ptr += self._len;
self._len = 0;
return rune;
}
self._ptr += l;
self._len -= l;
rune._len = l;
return rune;
}
/*
* @dev Returns the first rune in the slice, advancing the slice to point
* to the next rune.
* @param self The slice to operate on.
* @return A slice containing only the first rune from `self`.
*/
function nextRune(slice memory self) internal pure returns (slice memory ret) {
nextRune(self, ret);
}
/*
* @dev Returns the number of the first codepoint in the slice.
* @param self The slice to operate on.
* @return The number of the first codepoint in the slice.
*/
function ord(slice memory self) internal pure returns (uint ret) {
if (self._len == 0) {
return 0;
}
uint word;
uint length;
uint divisor = 2 ** 248;
// Load the rune into the MSBs of b
assembly { word:= mload(mload(add(self, 32))) }
uint b = word / divisor;
if (b < 0x80) {
ret = b;
length = 1;
} else if(b < 0xE0) {
ret = b & 0x1F;
length = 2;
} else if(b < 0xF0) {
ret = b & 0x0F;
length = 3;
} else {
ret = b & 0x07;
length = 4;
}
// Check for truncated codepoints
if (length > self._len) {
return 0;
}
for (uint i = 1; i < length; i++) {
divisor = divisor / 256;
b = (word / divisor) & 0xFF;
if (b & 0xC0 != 0x80) {
// Invalid UTF-8 sequence
return 0;
}
ret = (ret * 64) | (b & 0x3F);
}
return ret;
}
/*
* @dev Returns the keccak-256 hash of the slice.
* @param self The slice to hash.
* @return The hash of the slice.
*/
function keccak(slice memory self) internal pure returns (bytes32 ret) {
assembly {
ret := keccak256(mload(add(self, 32)), mload(self))
}
}
/*
* @dev Returns true if `self` starts with `needle`.
* @param self The slice to operate on.
* @param needle The slice to search for.
* @return True if the slice starts with the provided text, false otherwise.
*/
function startsWith(slice memory self, slice memory needle) internal pure returns (bool) {
if (self._len < needle._len) {
return false;
}
if (self._ptr == needle._ptr) {
return true;
}
bool equal;
assembly {
let length := mload(needle)
let selfptr := mload(add(self, 0x20))
let needleptr := mload(add(needle, 0x20))
equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
}
return equal;
}
/*
* @dev If `self` starts with `needle`, `needle` is removed from the
* beginning of `self`. Otherwise, `self` is unmodified.
* @param self The slice to operate on.
* @param needle The slice to search for.
* @return `self`
*/
function beyond(slice memory self, slice memory needle) internal pure returns (slice memory) {
if (self._len < needle._len) {
return self;
}
bool equal = true;
if (self._ptr != needle._ptr) {
assembly {
let length := mload(needle)
let selfptr := mload(add(self, 0x20))
let needleptr := mload(add(needle, 0x20))
equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
}
}
if (equal) {
self._len -= needle._len;
self._ptr += needle._len;
}
return self;
}
/*
* @dev Returns true if the slice ends with `needle`.
* @param self The slice to operate on.
* @param needle The slice to search for.
* @return True if the slice starts with the provided text, false otherwise.
*/
function endsWith(slice memory self, slice memory needle) internal pure returns (bool) {
if (self._len < needle._len) {
return false;
}
uint selfptr = self._ptr + self._len - needle._len;
if (selfptr == needle._ptr) {
return true;
}
bool equal;
assembly {
let length := mload(needle)
let needleptr := mload(add(needle, 0x20))
equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
}
return equal;
}
/*
* @dev If `self` ends with `needle`, `needle` is removed from the
* end of `self`. Otherwise, `self` is unmodified.
* @param self The slice to operate on.
* @param needle The slice to search for.
* @return `self`
*/
function until(slice memory self, slice memory needle) internal pure returns (slice memory) {
if (self._len < needle._len) {
return self;
}
uint selfptr = self._ptr + self._len - needle._len;
bool equal = true;
if (selfptr != needle._ptr) {
assembly {
let length := mload(needle)
let needleptr := mload(add(needle, 0x20))
equal := eq(keccak256(selfptr, length), keccak256(needleptr, length))
}
}
if (equal) {
self._len -= needle._len;
}
return self;
}
// Returns the memory address of the first byte of the first occurrence of
// `needle` in `self`, or the first byte after `self` if not found.
function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {
uint ptr = selfptr;
uint idx;
if (needlelen <= selflen) {
if (needlelen <= 32) {
bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));
bytes32 needledata;
assembly { needledata := and(mload(needleptr), mask) }
uint end = selfptr + selflen - needlelen;
bytes32 ptrdata;
assembly { ptrdata := and(mload(ptr), mask) }
while (ptrdata != needledata) {
if (ptr >= end)
return selfptr + selflen;
ptr++;
assembly { ptrdata := and(mload(ptr), mask) }
}
return ptr;
} else {
// For long needles, use hashing
bytes32 hash;
assembly { hash := keccak256(needleptr, needlelen) }
for (idx = 0; idx <= selflen - needlelen; idx++) {
bytes32 testHash;
assembly { testHash := keccak256(ptr, needlelen) }
if (hash == testHash)
return ptr;
ptr += 1;
}
}
}
return selfptr + selflen;
}
// Returns the memory address of the first byte after the last occurrence of
// `needle` in `self`, or the address of `self` if not found.
function rfindPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private pure returns (uint) {
uint ptr;
if (needlelen <= selflen) {
if (needlelen <= 32) {
bytes32 mask = bytes32(~(2 ** (8 * (32 - needlelen)) - 1));
bytes32 needledata;
assembly { needledata := and(mload(needleptr), mask) }
ptr = selfptr + selflen - needlelen;
bytes32 ptrdata;
assembly { ptrdata := and(mload(ptr), mask) }
while (ptrdata != needledata) {
if (ptr <= selfptr)
return selfptr;
ptr--;
assembly { ptrdata := and(mload(ptr), mask) }
}
return ptr + needlelen;
} else {
// For long needles, use hashing
bytes32 hash;
assembly { hash := keccak256(needleptr, needlelen) }
ptr = selfptr + (selflen - needlelen);
while (ptr >= selfptr) {
bytes32 testHash;
assembly { testHash := keccak256(ptr, needlelen) }
if (hash == testHash)
return ptr + needlelen;
ptr -= 1;
}
}
}
return selfptr;
}
/*
* @dev Modifies `self` to contain everything from the first occurrence of
* `needle` to the end of the slice. `self` is set to the empty slice
* if `needle` is not found.
* @param self The slice to search and modify.
* @param needle The text to search for.
* @return `self`.
*/
function find(slice memory self, slice memory needle) internal pure returns (slice memory) {
uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);
self._len -= ptr - self._ptr;
self._ptr = ptr;
return self;
}
/*
* @dev Modifies `self` to contain the part of the string from the start of
* `self` to the end of the first occurrence of `needle`. If `needle`
* is not found, `self` is set to the empty slice.
* @param self The slice to search and modify.
* @param needle The text to search for.
* @return `self`.
*/
function rfind(slice memory self, slice memory needle) internal pure returns (slice memory) {
uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);
self._len = ptr - self._ptr;
return self;
}
/*
* @dev Splits the slice, setting `self` to everything after the first
* occurrence of `needle`, and `token` to everything before it. If
* `needle` does not occur in `self`, `self` is set to the empty slice,
* and `token` is set to the entirety of `self`.
* @param self The slice to split.
* @param needle The text to search for in `self`.
* @param token An output parameter to which the first token is written.
* @return `token`.
*/
function split(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) {
uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr);
token._ptr = self._ptr;
token._len = ptr - self._ptr;
if (ptr == self._ptr + self._len) {
// Not found
self._len = 0;
} else {
self._len -= token._len + needle._len;
self._ptr = ptr + needle._len;
}
return token;
}
/*
* @dev Splits the slice, setting `self` to everything after the first
* occurrence of `needle`, and returning everything before it. If
* `needle` does not occur in `self`, `self` is set to the empty slice,
* and the entirety of `self` is returned.
* @param self The slice to split.
* @param needle The text to search for in `self`.
* @return The part of `self` up to the first occurrence of `delim`.
*/
function split(slice memory self, slice memory needle) internal pure returns (slice memory token) {
split(self, needle, token);
}
/*
* @dev Splits the slice, setting `self` to everything before the last
* occurrence of `needle`, and `token` to everything after it. If
* `needle` does not occur in `self`, `self` is set to the empty slice,
* and `token` is set to the entirety of `self`.
* @param self The slice to split.
* @param needle The text to search for in `self`.
* @param token An output parameter to which the first token is written.
* @return `token`.
*/
function rsplit(slice memory self, slice memory needle, slice memory token) internal pure returns (slice memory) {
uint ptr = rfindPtr(self._len, self._ptr, needle._len, needle._ptr);
token._ptr = ptr;
token._len = self._len - (ptr - self._ptr);
if (ptr == self._ptr) {
// Not found
self._len = 0;
} else {
self._len -= token._len + needle._len;
}
return token;
}
/*
* @dev Splits the slice, setting `self` to everything before the last
* occurrence of `needle`, and returning everything after it. If
* `needle` does not occur in `self`, `self` is set to the empty slice,
* and the entirety of `self` is returned.
* @param self The slice to split.
* @param needle The text to search for in `self`.
* @return The part of `self` after the last occurrence of `delim`.
*/
function rsplit(slice memory self, slice memory needle) internal pure returns (slice memory token) {
rsplit(self, needle, token);
}
/*
* @dev Counts the number of nonoverlapping occurrences of `needle` in `self`.
* @param self The slice to search.
* @param needle The text to search for in `self`.
* @return The number of occurrences of `needle` found in `self`.
*/
function count(slice memory self, slice memory needle) internal pure returns (uint cnt) {
uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len;
while (ptr <= self._ptr + self._len) {
cnt++;
ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len;
}
}
/*
* @dev Returns True if `self` contains `needle`.
* @param self The slice to search.
* @param needle The text to search for in `self`.
* @return True if `needle` is found in `self`, false otherwise.
*/
function contains(slice memory self, slice memory needle) internal pure returns (bool) {
return rfindPtr(self._len, self._ptr, needle._len, needle._ptr) != self._ptr;
}
/*
* @dev Returns a newly allocated string containing the concatenation of
* `self` and `other`.
* @param self The first slice to concatenate.
* @param other The second slice to concatenate.
* @return The concatenation of the two strings.
*/
function concat(slice memory self, slice memory other) internal pure returns (string memory) {
string memory ret = new string(self._len + other._len);
uint retptr;
assembly { retptr := add(ret, 32) }
memcpy(retptr, self._ptr, self._len);
memcpy(retptr + self._len, other._ptr, other._len);
return ret;
}
/*
* @dev Joins an array of slices, using `self` as a delimiter, returning a
* newly allocated string.
* @param self The delimiter to use.
* @param parts A list of slices to join.
* @return A newly allocated string containing all the slices in `parts`,
* joined with `self`.
*/
function join(slice memory self, slice[] memory parts) internal pure returns (string memory) {
if (parts.length == 0)
return "";
uint length = self._len * (parts.length - 1);
for(uint i = 0; i < parts.length; i++)
length += parts[i]._len;
string memory ret = new string(length);
uint retptr;
assembly { retptr := add(ret, 32) }
for(uint i = 0; i < parts.length; i++) {
memcpy(retptr, parts[i]._ptr, parts[i]._len);
retptr += parts[i]._len;
if (i < parts.length - 1) {
memcpy(retptr, self._ptr, self._len);
retptr += self._len;
}
}
return ret;
}
}
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
/**
* @dev Required interface of an ERC721 compliant contract.
*/
contract IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of NFTs in `owner`'s account.
*/
function balanceOf(address owner) public view returns (uint256 balance);
/**
* @dev Returns the owner of the NFT specified by `tokenId`.
*/
function ownerOf(uint256 tokenId) public view returns (address owner);
/**
* @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
* another (`to`).
*
*
*
* Requirements:
* - `from`, `to` cannot be zero.
* - `tokenId` must be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this
* NFT by either {approve} or {setApprovalForAll}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public;
/**
* @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
* another (`to`).
*
* Requirements:
* - If the caller is not `from`, it must be approved to move this NFT by
* either {approve} or {setApprovalForAll}.
*/
function transferFrom(address from, address to, uint256 tokenId) public;
function approve(address to, uint256 tokenId) public;
function getApproved(uint256 tokenId) public view returns (address operator);
function setApprovalForAll(address operator, bool _approved) public;
function isApprovedForAll(address owner, address operator) public view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
contract IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
contract Context {
// Empty internal constructor, to prevent people from mistakenly deploying
// an instance of this contract, which should be used via inheritance.
constructor () internal { }
// solhint-disable-previous-line no-empty-blocks
function _msgSender() internal view returns (address payable) {
return msg.sender;
}
function _msgData() internal view returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
contract IERC721Enumerable is IERC721 {
function totalSupply() public view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256 tokenId);
function tokenByIndex(uint256 index) public view returns (uint256);
}
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
contract IERC721Receiver {
/**
* @notice Handle the receipt of an NFT
* @dev The ERC721 smart contract calls this function on the recipient
* after a {IERC721-safeTransferFrom}. This function MUST return the function selector,
* otherwise the caller will revert the transaction. The selector to be
* returned can be obtained as `this.onERC721Received.selector`. This
* function MAY throw to revert and reject the transfer.
* Note: the ERC721 contract address is always the message sender.
* @param operator The address which called `safeTransferFrom` function
* @param from The address which previously owned the token
* @param tokenId The NFT identifier which is being transferred
* @param data Additional data with no specified format
* @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
*/
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data)
public returns (bytes4);
}
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*
* NOTE: This is a feature of the next version of OpenZeppelin Contracts.
* @dev Get it via `npm install @openzeppelin/contracts@next`.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
* NOTE: This is a feature of the next version of OpenZeppelin Contracts.
* @dev Get it via `npm install @openzeppelin/contracts@next`.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*
* NOTE: This is a feature of the next version of OpenZeppelin Contracts.
* @dev Get it via `npm install @openzeppelin/contracts@next`.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* This test is non-exhaustive, and there may be false-negatives: during the
* execution of a contract's constructor, its address will be reported as
* not containing a contract.
*
* IMPORTANT: It is unsafe to assume that an address for which this
* function returns false is an externally-owned account (EOA) and not a
* contract.
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
// for accounts without code, i.e. `keccak256('')`
bytes32 codehash;
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
// solhint-disable-next-line no-inline-assembly
assembly { codehash := extcodehash(account) }
return (codehash != 0x0 && codehash != accountHash);
}
/**
* @dev Converts an `address` into `address payable`. Note that this is
* simply a type cast: the actual underlying value is not changed.
*
* NOTE: This is a feature of the next version of OpenZeppelin Contracts.
* @dev Get it via `npm install @openzeppelin/contracts@next`.
*/
function toPayable(address account) internal pure returns (address payable) {
return address(uint160(account));
}
}
/**
* @title Counters
* @author Matt Condon (@shrugs)
* @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
* of elements in a mapping, issuing ERC721 ids, or counting request ids.
*
* Include with `using Counters for Counters.Counter;`
* Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
* overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
* directly accessed.
*/
library Counters {
using SafeMath for uint256;
struct Counter {
// This variable should never be directly accessed by users of the library: interactions must be restricted to
// the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
// this feature: see https://github.com/ethereum/solidity/issues/4637
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
// The {SafeMath} overflow check can be skipped here, see the comment at the top
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts may inherit from this and call {_registerInterface} to declare
* their support of an interface.
*/
contract ERC165 is IERC165 {
/*
* bytes4(keccak256('supportsInterface(bytes4)')) == 0x01ffc9a7
*/
bytes4 private constant _INTERFACE_ID_ERC165 = 0x01ffc9a7;
/**
* @dev Mapping of interface ids to whether or not it's supported.
*/
mapping(bytes4 => bool) private _supportedInterfaces;
constructor () internal {
// Derived contracts need only register support for their own interfaces,
// we register support for ERC165 itself here
_registerInterface(_INTERFACE_ID_ERC165);
}
/**
* @dev See {IERC165-supportsInterface}.
*
* Time complexity O(1), guaranteed to always use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool) {
return _supportedInterfaces[interfaceId];
}
/**
* @dev Registers the contract as an implementer of the interface defined by
* `interfaceId`. Support of the actual ERC165 interface is automatic and
* registering its interface id is not required.
*
* See {IERC165-supportsInterface}.
*
* Requirements:
*
* - `interfaceId` cannot be the ERC165 invalid interface (`0xffffffff`).
*/
function _registerInterface(bytes4 interfaceId) internal {
require(interfaceId != 0xffffffff, "ERC165: invalid interface id");
_supportedInterfaces[interfaceId] = true;
}
}
/**
* @title ERC721 Non-Fungible Token Standard basic implementation
* @dev see https://eips.ethereum.org/EIPS/eip-721
*/
contract ERC721 is Context, ERC165, IERC721 {
using SafeMath for uint256;
using Address for address;
using Counters for Counters.Counter;
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
// Mapping from token ID to owner
mapping (uint256 => address) private _tokenOwner;
// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;
// Mapping from owner to number of owned token
mapping (address => Counters.Counter) private _ownedTokensCount;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
/*
* bytes4(keccak256('balanceOf(address)')) == 0x70a08231
* bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
* bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
* bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
* bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
*
* => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
* 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
*/
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
constructor () public {
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721);
}
/**
* @dev Gets the balance of the specified address.
* @param owner address to query the balance of
* @return uint256 representing the amount owned by the passed address
*/
function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _ownedTokensCount[owner].current();
}
/**
* @dev Gets the owner of the specified token ID.
* @param tokenId uint256 ID of the token to query the owner of
* @return address currently marked as the owner of the given token ID
*/
function ownerOf(uint256 tokenId) public view returns (address) {
address owner = _tokenOwner[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev Approves another address to transfer the given token ID
* The zero address indicates there is no approved address.
* There can only be one approved address per token at a given time.
* Can only be called by the token owner or an approved operator.
* @param to address to be approved for the given token ID
* @param tokenId uint256 ID of the token to be approved
*/
function approve(address to, uint256 tokenId) public {
address owner = ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}
/**
* @dev Gets the approved address for a token ID, or zero if no address set
* Reverts if the token ID does not exist.
* @param tokenId uint256 ID of the token to query the approval of
* @return address currently approved for the given token ID
*/
function getApproved(uint256 tokenId) public view returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev Sets or unsets the approval of a given operator
* An operator is allowed to transfer all tokens of the sender on their behalf.
* @param to operator address to set the approval
* @param approved representing the status of the approval to be set
*/
function setApprovalForAll(address to, bool approved) public {
require(to != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][to] = approved;
emit ApprovalForAll(_msgSender(), to, approved);
}
/**
* @dev Tells whether an operator is approved by a given owner.
* @param owner owner address which you want to query the approval of
* @param operator operator address which you want to query the approval of
* @return bool whether the given operator is approved by the given owner
*/
function isApprovedForAll(address owner, address operator) public view returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev Transfers the ownership of a given token ID to another address.
* Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
* Requires the msg.sender to be the owner, approved, or operator.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function transferFrom(address from, address to, uint256 tokenId) public {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transferFrom(from, to, tokenId);
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the msg.sender to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the _msgSender() to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes data to send along with a safe transfer check
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransferFrom(from, to, tokenId, _data);
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement `onERC721Received`,
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the msg.sender to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes data to send along with a safe transfer check
*/
function _safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) internal {
_transferFrom(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether the specified token exists.
* @param tokenId uint256 ID of the token to query the existence of
* @return bool whether the token exists
*/
function _exists(uint256 tokenId) internal view returns (bool) {
address owner = _tokenOwner[tokenId];
return owner != address(0);
}
/**
* @dev Returns whether the given spender can transfer a given token ID.
* @param spender address of the spender to query
* @param tokenId uint256 ID of the token to be transferred
* @return bool whether the msg.sender is approved for the given token ID,
* is an operator of the owner, or is the owner of the token
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Internal function to safely mint a new token.
* Reverts if the given token ID already exists.
* If the target address is a contract, it must implement `onERC721Received`,
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* @param to The address that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function _safeMint(address to, uint256 tokenId) internal {
_safeMint(to, tokenId, "");
}
/**
* @dev Internal function to safely mint a new token.
* Reverts if the given token ID already exists.
* If the target address is a contract, it must implement `onERC721Received`,
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* @param to The address that will own the minted token
* @param tokenId uint256 ID of the token to be minted
* @param _data bytes data to send along with a safe transfer check
*/
function _safeMint(address to, uint256 tokenId, bytes memory _data) internal {
_mint(to, tokenId);
require(_checkOnERC721Received(address(0), to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Internal function to mint a new token.
* Reverts if the given token ID already exists.
* @param to The address that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function _mint(address to, uint256 tokenId) internal {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_tokenOwner[tokenId] = to;
_ownedTokensCount[to].increment();
emit Transfer(address(0), to, tokenId);
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use {_burn} instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned
*/
function _burn(address owner, uint256 tokenId) internal {
require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own");
_clearApproval(tokenId);
_ownedTokensCount[owner].decrement();
_tokenOwner[tokenId] = address(0);
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* @param tokenId uint256 ID of the token being burned
*/
function _burn(uint256 tokenId) internal {
_burn(ownerOf(tokenId), tokenId);
}
/**
* @dev Internal function to transfer ownership of a given token ID to another address.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function _transferFrom(address from, address to, uint256 tokenId) internal {
require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_clearApproval(tokenId);
_ownedTokensCount[from].decrement();
_ownedTokensCount[to].increment();
_tokenOwner[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* This function is deprecated.
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
internal returns (bool)
{
if (!to.isContract()) {
return true;
}
bytes4 retval = IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data);
return (retval == _ERC721_RECEIVED);
}
/**
* @dev Private function to clear current approval of a given token ID.
* @param tokenId uint256 ID of the token to be transferred
*/
function _clearApproval(uint256 tokenId) private {
if (_tokenApprovals[tokenId] != address(0)) {
_tokenApprovals[tokenId] = address(0);
}
}
}
/**
* @title ERC-721 Non-Fungible Token with optional enumeration extension logic
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
contract ERC721Enumerable is Context, ERC165, ERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => uint256[]) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/*
* bytes4(keccak256('totalSupply()')) == 0x18160ddd
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
* bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
*
* => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
*/
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
/**
* @dev Constructor function.
*/
constructor () public {
// register the supported interface to conform to ERC721Enumerable via ERC165
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
}
/**
* @dev Gets the token ID at a given index of the tokens list of the requested owner.
* @param owner address owning the tokens list to be accessed
* @param index uint256 representing the index to be accessed of the requested tokens list
* @return uint256 token ID at the given index of the tokens list owned by the requested address
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev Gets the total amount of tokens stored by the contract.
* @return uint256 representing the total amount of tokens
*/
function totalSupply() public view returns (uint256) {
return _allTokens.length;
}
/**
* @dev Gets the token ID at a given index of all the tokens in this contract
* Reverts if the index is greater or equal to the total number of tokens.
* @param index uint256 representing the index to be accessed of the tokens list
* @return uint256 token ID at the given index of the tokens list
*/
function tokenByIndex(uint256 index) public view returns (uint256) {
require(index < totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Internal function to transfer ownership of a given token ID to another address.
* As opposed to transferFrom, this imposes no restrictions on msg.sender.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function _transferFrom(address from, address to, uint256 tokenId) internal {
super._transferFrom(from, to, tokenId);
_removeTokenFromOwnerEnumeration(from, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
}
/**
* @dev Internal function to mint a new token.
* Reverts if the given token ID already exists.
* @param to address the beneficiary that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function _mint(address to, uint256 tokenId) internal {
super._mint(to, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
_addTokenToAllTokensEnumeration(tokenId);
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use {ERC721-_burn} instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned
*/
function _burn(address owner, uint256 tokenId) internal {
super._burn(owner, tokenId);
_removeTokenFromOwnerEnumeration(owner, tokenId);
// Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund
_ownedTokensIndex[tokenId] = 0;
_removeTokenFromAllTokensEnumeration(tokenId);
}
/**
* @dev Gets the list of token IDs of the requested owner.
* @param owner address owning the tokens
* @return uint256[] List of token IDs owned by the requested address
*/
function _tokensOfOwner(address owner) internal view returns (uint256[] storage) {
return _ownedTokens[owner];
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
_ownedTokensIndex[tokenId] = _ownedTokens[to].length;
_ownedTokens[to].push(tokenId);
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
_ownedTokens[from].length--;
// Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by
// lastTokenId, or just over the end of the array if the token was the last one).
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length.sub(1);
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
_allTokens.length--;
_allTokensIndex[tokenId] = 0;
}
}
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/
function isOwner() public view returns (bool) {
return _msgSender() == _owner;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
/**
* @title ERC721 Non-Fungible Token Standard basic implementation
* Modified to remove the mint function and to replace it
* with the _addTokenTo function.
* This function is very similar to the _mint function, but it
* does not emit a Transfer event
* @dev see https://eips.ethereum.org/EIPS/eip-721
*/
contract NoMintERC721 is Context, ERC165, IERC721 {
using SafeMath for uint256;
using Address for address;
using Counters for Counters.Counter;
// Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
// which can be also obtained as `IERC721Receiver(0).onERC721Received.selector`
bytes4 private constant _ERC721_RECEIVED = 0x150b7a02;
// Mapping from token ID to owner
mapping (uint256 => address) private _tokenOwner;
// Mapping from token ID to approved address
mapping (uint256 => address) private _tokenApprovals;
// Mapping from owner to number of owned token
mapping (address => Counters.Counter) private _ownedTokensCount;
// Mapping from owner to operator approvals
mapping (address => mapping (address => bool)) private _operatorApprovals;
/*
* bytes4(keccak256('balanceOf(address)')) == 0x70a08231
* bytes4(keccak256('ownerOf(uint256)')) == 0x6352211e
* bytes4(keccak256('approve(address,uint256)')) == 0x095ea7b3
* bytes4(keccak256('getApproved(uint256)')) == 0x081812fc
* bytes4(keccak256('setApprovalForAll(address,bool)')) == 0xa22cb465
* bytes4(keccak256('isApprovedForAll(address,address)')) == 0xe985e9c5
* bytes4(keccak256('transferFrom(address,address,uint256)')) == 0x23b872dd
* bytes4(keccak256('safeTransferFrom(address,address,uint256)')) == 0x42842e0e
* bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) == 0xb88d4fde
*
* => 0x70a08231 ^ 0x6352211e ^ 0x095ea7b3 ^ 0x081812fc ^
* 0xa22cb465 ^ 0xe985e9c ^ 0x23b872dd ^ 0x42842e0e ^ 0xb88d4fde == 0x80ac58cd
*/
bytes4 private constant _INTERFACE_ID_ERC721 = 0x80ac58cd;
constructor () public {
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721);
}
/**
* @dev Gets the balance of the specified address.
* @param owner address to query the balance of
* @return uint256 representing the amount owned by the passed address
*/
function balanceOf(address owner) public view returns (uint256) {
require(owner != address(0), "ERC721: balance query for the zero address");
return _ownedTokensCount[owner].current();
}
/**
* @dev Gets the owner of the specified token ID.
* @param tokenId uint256 ID of the token to query the owner of
* @return address currently marked as the owner of the given token ID
*/
function ownerOf(uint256 tokenId) public view returns (address) {
address owner = _tokenOwner[tokenId];
require(owner != address(0), "ERC721: owner query for nonexistent token");
return owner;
}
/**
* @dev Approves another address to transfer the given token ID
* The zero address indicates there is no approved address.
* There can only be one approved address per token at a given time.
* Can only be called by the token owner or an approved operator.
* @param to address to be approved for the given token ID
* @param tokenId uint256 ID of the token to be approved
*/
function approve(address to, uint256 tokenId) public {
address owner = ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not owner nor approved for all"
);
_tokenApprovals[tokenId] = to;
emit Approval(owner, to, tokenId);
}
/**
* @dev Gets the approved address for a token ID, or zero if no address set
* Reverts if the token ID does not exist.
* @param tokenId uint256 ID of the token to query the approval of
* @return address currently approved for the given token ID
*/
function getApproved(uint256 tokenId) public view returns (address) {
require(_exists(tokenId), "ERC721: approved query for nonexistent token");
return _tokenApprovals[tokenId];
}
/**
* @dev Sets or unsets the approval of a given operator
* An operator is allowed to transfer all tokens of the sender on their behalf.
* @param to operator address to set the approval
* @param approved representing the status of the approval to be set
*/
function setApprovalForAll(address to, bool approved) public {
require(to != _msgSender(), "ERC721: approve to caller");
_operatorApprovals[_msgSender()][to] = approved;
emit ApprovalForAll(_msgSender(), to, approved);
}
/**
* @dev Tells whether an operator is approved by a given owner.
* @param owner owner address which you want to query the approval of
* @param operator operator address which you want to query the approval of
* @return bool whether the given operator is approved by the given owner
*/
function isApprovedForAll(address owner, address operator) public view returns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev Transfers the ownership of a given token ID to another address.
* Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
* Requires the msg.sender to be the owner, approved, or operator.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function transferFrom(address from, address to, uint256 tokenId) public {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_transferFrom(from, to, tokenId);
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the msg.sender to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public {
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement {IERC721Receiver-onERC721Received},
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the _msgSender() to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes data to send along with a safe transfer check
*/
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: transfer caller is not owner nor approved");
_safeTransferFrom(from, to, tokenId, _data);
}
/**
* @dev Safely transfers the ownership of a given token ID to another address
* If the target address is a contract, it must implement `onERC721Received`,
* which is called upon a safe transfer, and return the magic value
* `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
* the transfer is reverted.
* Requires the msg.sender to be the owner, approved, or operator
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes data to send along with a safe transfer check
*/
function _safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) internal {
_transferFrom(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, _data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns whether the specified token exists.
* @param tokenId uint256 ID of the token to query the existence of
* @return bool whether the token exists
*/
function _exists(uint256 tokenId) internal view returns (bool) {
address owner = _tokenOwner[tokenId];
return owner != address(0);
}
/**
* @dev Returns whether the given spender can transfer a given token ID.
* @param spender address of the spender to query
* @param tokenId uint256 ID of the token to be transferred
* @return bool whether the msg.sender is approved for the given token ID,
* is an operator of the owner, or is the owner of the token
*/
function _isApprovedOrOwner(address spender, uint256 tokenId) internal view returns (bool) {
require(_exists(tokenId), "ERC721: operator query for nonexistent token");
address owner = ownerOf(tokenId);
return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender));
}
/**
* @dev Internal function to mint a new token.
* Reverts if the given token ID already exists.
* @param to The address that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function _addTokenTo(address to, uint256 tokenId) internal {
require(to != address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_tokenOwner[tokenId] = to;
_ownedTokensCount[to].increment();
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use {_burn} instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned
*/
function _burn(address owner, uint256 tokenId) internal {
require(ownerOf(tokenId) == owner, "ERC721: burn of token that is not own");
_clearApproval(tokenId);
_ownedTokensCount[owner].decrement();
_tokenOwner[tokenId] = address(0);
emit Transfer(owner, address(0), tokenId);
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* @param tokenId uint256 ID of the token being burned
*/
function _burn(uint256 tokenId) internal {
_burn(ownerOf(tokenId), tokenId);
}
/**
* @dev Internal function to transfer ownership of a given token ID to another address.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function _transferFrom(address from, address to, uint256 tokenId) internal {
require(ownerOf(tokenId) == from, "ERC721: transfer of token that is not own");
require(to != address(0), "ERC721: transfer to the zero address");
_clearApproval(tokenId);
_ownedTokensCount[from].decrement();
_ownedTokensCount[to].increment();
_tokenOwner[tokenId] = to;
emit Transfer(from, to, tokenId);
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* This function is deprecated.
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param _data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/
function _checkOnERC721Received(address from, address to, uint256 tokenId, bytes memory _data)
internal returns (bool)
{
if (!to.isContract()) {
return true;
}
bytes4 retval = IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data);
return (retval == _ERC721_RECEIVED);
}
/**
* @dev Private function to clear current approval of a given token ID.
* @param tokenId uint256 ID of the token to be transferred
*/
function _clearApproval(uint256 tokenId) private {
if (_tokenApprovals[tokenId] != address(0)) {
_tokenApprovals[tokenId] = address(0);
}
}
}
/**
* @title ERC-721 Non-Fungible Token with optional enumeration extension logic
* Modified to work with the NoMintERC721 contract
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
contract NoMintERC721Enumerable is Context, ERC165, NoMintERC721, IERC721Enumerable {
// Mapping from owner to list of owned token IDs
mapping(address => uint256[]) private _ownedTokens;
// Mapping from token ID to index of the owner tokens list
mapping(uint256 => uint256) private _ownedTokensIndex;
// Array with all token ids, used for enumeration
uint256[] private _allTokens;
// Mapping from token id to position in the allTokens array
mapping(uint256 => uint256) private _allTokensIndex;
/*
* bytes4(keccak256('totalSupply()')) == 0x18160ddd
* bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) == 0x2f745c59
* bytes4(keccak256('tokenByIndex(uint256)')) == 0x4f6ccce7
*
* => 0x18160ddd ^ 0x2f745c59 ^ 0x4f6ccce7 == 0x780e9d63
*/
bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
/**
* @dev Constructor function.
*/
constructor () public {
// register the supported interface to conform to ERC721Enumerable via ERC165
_registerInterface(_INTERFACE_ID_ERC721_ENUMERABLE);
}
/**
* @dev Gets the token ID at a given index of the tokens list of the requested owner.
* @param owner address owning the tokens list to be accessed
* @param index uint256 representing the index to be accessed of the requested tokens list
* @return uint256 token ID at the given index of the tokens list owned by the requested address
*/
function tokenOfOwnerByIndex(address owner, uint256 index) public view returns (uint256) {
require(index < balanceOf(owner), "ERC721Enumerable: owner index out of bounds");
return _ownedTokens[owner][index];
}
/**
* @dev Gets the total amount of tokens stored by the contract.
* @return uint256 representing the total amount of tokens
*/
function totalSupply() public view returns (uint256) {
return _allTokens.length;
}
/**
* @dev Gets the token ID at a given index of all the tokens in this contract
* Reverts if the index is greater or equal to the total number of tokens.
* @param index uint256 representing the index to be accessed of the tokens list
* @return uint256 token ID at the given index of the tokens list
*/
function tokenByIndex(uint256 index) public view returns (uint256) {
require(index < totalSupply(), "ERC721Enumerable: global index out of bounds");
return _allTokens[index];
}
/**
* @dev Internal function to transfer ownership of a given token ID to another address.
* As opposed to transferFrom, this imposes no restrictions on msg.sender.
* @param from current owner of the token
* @param to address to receive the ownership of the given token ID
* @param tokenId uint256 ID of the token to be transferred
*/
function _transferFrom(address from, address to, uint256 tokenId) internal {
super._transferFrom(from, to, tokenId);
_removeTokenFromOwnerEnumeration(from, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
}
/**
* @dev Internal function to mint a new token.
* Reverts if the given token ID already exists.
* @param to address the beneficiary that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function _addTokenTo(address to, uint256 tokenId) internal {
super._addTokenTo(to, tokenId);
_addTokenToOwnerEnumeration(to, tokenId);
_addTokenToAllTokensEnumeration(tokenId);
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use {ERC721-_burn} instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned
*/
function _burn(address owner, uint256 tokenId) internal {
super._burn(owner, tokenId);
_removeTokenFromOwnerEnumeration(owner, tokenId);
// Since tokenId will be deleted, we can clear its slot in _ownedTokensIndex to trigger a gas refund
_ownedTokensIndex[tokenId] = 0;
_removeTokenFromAllTokensEnumeration(tokenId);
}
/**
* @dev Gets the list of token IDs of the requested owner.
* @param owner address owning the tokens
* @return uint256[] List of token IDs owned by the requested address
*/
function _tokensOfOwner(address owner) internal view returns (uint256[] storage) {
return _ownedTokens[owner];
}
/**
* @dev Private function to add a token to this extension's ownership-tracking data structures.
* @param to address representing the new owner of the given token ID
* @param tokenId uint256 ID of the token to be added to the tokens list of the given address
*/
function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private {
_ownedTokensIndex[tokenId] = _ownedTokens[to].length;
_ownedTokens[to].push(tokenId);
}
/**
* @dev Private function to add a token to this extension's token tracking data structures.
* @param tokenId uint256 ID of the token to be added to the tokens list
*/
function _addTokenToAllTokensEnumeration(uint256 tokenId) private {
_allTokensIndex[tokenId] = _allTokens.length;
_allTokens.push(tokenId);
}
/**
* @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that
* while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for
* gas optimizations e.g. when performing a transfer operation (avoiding double writes).
* This has O(1) time complexity, but alters the order of the _ownedTokens array.
* @param from address representing the previous owner of the given token ID
* @param tokenId uint256 ID of the token to be removed from the tokens list of the given address
*/
function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private {
// To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _ownedTokens[from].length.sub(1);
uint256 tokenIndex = _ownedTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
uint256 lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
}
// This also deletes the contents at the last position of the array
_ownedTokens[from].length--;
// Note that _ownedTokensIndex[tokenId] hasn't been cleared: it still points to the old slot (now occupied by
// lastTokenId, or just over the end of the array if the token was the last one).
}
/**
* @dev Private function to remove a token from this extension's token tracking data structures.
* This has O(1) time complexity, but alters the order of the _allTokens array.
* @param tokenId uint256 ID of the token to be removed from the tokens list
*/
function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private {
// To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and
// then delete the last slot (swap and pop).
uint256 lastTokenIndex = _allTokens.length.sub(1);
uint256 tokenIndex = _allTokensIndex[tokenId];
// When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so
// rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding
// an 'if' statement (like in _removeTokenFromOwnerEnumeration)
uint256 lastTokenId = _allTokens[lastTokenIndex];
_allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index
// This also deletes the contents at the last position of the array
_allTokens.length--;
_allTokensIndex[tokenId] = 0;
}
}
/**
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension
* Modified to change
* function tokenURI(uint256 tokenId) external view returns (string memory);
* to
* function tokenURI(uint256 tokenId) public view returns (string memory);
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
contract OveridableERC721Metadata is Context, ERC165, NoMintERC721, IERC721Metadata {
// Token name
string private _name;
// Token symbol
string private _symbol;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_ERC721_METADATA = 0x5b5e139f;
/**
* @dev Constructor function
*/
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
// register the supported interfaces to conform to ERC721 via ERC165
_registerInterface(_INTERFACE_ID_ERC721_METADATA);
}
/**
* @dev Gets the token name.
* @return string representing the token name
*/
function name() external view returns (string memory) {
return _name;
}
/**
* @dev Gets the token symbol.
* @return string representing the token symbol
*/
function symbol() external view returns (string memory) {
return _symbol;
}
/**
* @dev Returns an URI for a given token ID.
* Throws if the token ID does not exist. May return an empty string.
* @param tokenId uint256 ID of the token to query
*/
function tokenURI(uint256 tokenId) public view returns (string memory) {
require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
return _tokenURIs[tokenId];
}
/**
* @dev Internal function to set the token URI for a given token.
* Reverts if the token ID does not exist.
* @param tokenId uint256 ID of the token to set its URI
* @param uri string URI to assign
*/
function _setTokenURI(uint256 tokenId, string memory uri) internal {
require(_exists(tokenId), "ERC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = uri;
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use _burn(uint256) instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned by the msg.sender
*/
function _burn(address owner, uint256 tokenId) internal {
super._burn(owner, tokenId);
// Clear metadata (if any)
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}
/**
* ERC-721 implementation that allows
* tokens (of the same category) to be minted in batches. Each batch
* contains enough data to generate all
* token ids inside the batch, and to
* generate the tokenURI in the batch
*/
contract GunToken is NoMintERC721, NoMintERC721Enumerable, OveridableERC721Metadata, Ownable {
using strings for *;
address internal factory;
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;
mapping(uint256 => bool) public outOfBatch;
//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();
}
function fallbackCount(address __owner) public view returns (uint256) {
}
function fallbackIndex(address __owner, uint256 index) public view returns (uint256) {
}
function migrate(uint256 count) public onlyOwner returns (uint256) {
//Empty for interface
}
function migrateSingle() public onlyOwner returns (uint256) {
//Empty for interface
}
function recoverBatch2(uint256 index, uint256 tokenStart, uint256 tokenEnd) public onlyOwner {
}
function migrateBatch(uint256 index) public onlyOwner returns (uint256) {
}
function recoverBatch1(uint256 index) public onlyOwner {
}
/**
* @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 updateGunFactory(address _factory) public onlyOwner {
}
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[2] = (requiredEther * (COMMISSION_PERCENT + commissionRate[referal])) / 100;
address payable _referal = address(uint160(referal));
_referal.transfer(prices[2]);
}
}
//Constructor
constructor(
address tokenAddress,
address tokenFactory,
address gp,
address isd,
address bzn_address
) public {
token = GunToken(tokenAddress);
factory = GunFactory(tokenFactory);
ethFeed = IDSValue(isd);
bzn = StandardBurnableToken(bzn_address);
gamePool = gp;
//Set percent increases
categoryPercentIncrease[1] = 100035;
categoryPercentBase[1] = 100000;
categoryPercentIncrease[2] = 100025;
categoryPercentBase[2] = 100000;
categoryPercentIncrease[3] = 100015;
categoryPercentBase[3] = 100000;
commissionRate[OPENSEA] = 10;
}
function createCategory(uint8 category) public onlyOwner {
require(allowCreateCategory);
categoryExists[category] = true;
}
function disableCreateCategories() public onlyOwner {
allowCreateCategory = false;
}
//Set the referal commision rate for an address
function setCommission(address referral, uint256 percent) public onlyOwner {
require(percent > COMMISSION_PERCENT);
require(percent < 95);
percent = percent - COMMISSION_PERCENT;
commissionRate[referral] = percent;
}
//Set the price increase/base for skinned or regular guns
function setPercentIncrease(uint256 increase, uint256 base, uint8 category) public onlyOwner {
require(increase > base);
categoryPercentIncrease[category] = increase;
categoryPercentBase[category] = base;
}
function setEtherPercent(uint256 percent, uint256 base, uint8 category) public onlyOwner {
requiredEtherPercent[category] = percent;
requiredEtherPercentBase[category] = base;
}
function killCategory(uint8 category) public onlyOwner {
require(!categoryKilled[category]);
categoryOpen[category] = false;
categoryKilled[category] = true;
}
//Open/Close the skinned or regular guns shop
function setShopState(uint8 category, bool open) public onlyOwner {
require(category == 1 || category == 2 || category == 3);
require(!categoryKilled[category]);
require(categoryExists[category]);
categoryOpen[category] = open;
}
/**
* Set the price for any given category in USD.
*/
function setPrice(uint8 category, uint256 price, bool inWei) public onlyOwner {
uint256 multiply = 1e18;
if (inWei) {
multiply = 1;
}
categoryPrice[category] = price * multiply;
}
/**
Withdraw the amount from the contract's balance. Only the contract owner can execute this function
*/
function withdraw(uint256 amount) public onlyOwner {
uint256 balance = address(this).balance;
require(amount <= balance, "Requested to much");
address payable _owner = address(uint160(owner()));
_owner.transfer(amount);
emit Withdrawal(amount);
}
function setBZNFeedContract(address new_bzn_feed) public onlyOwner {
bznFeed = BZNFeed(new_bzn_feed);
}
//Buy many skinned or regular guns with BZN. This will reserve the amount of guns and allows the new_owner to invoke claimGuns for free
function buyWithBZN(address referal, uint8 category, address payable new_owner, uint16 quanity) ensureShopOpen(category) payInBZN(referal, category, new_owner, quanity) public payable returns (bool) {
factory.mintFor(new_owner, quanity, category);
return true;
}
//Buy many skinned or regular guns with ETH. This will reserve the amount of guns and allows the new_owner to invoke claimGuns for free
function buyWithEther(address referal, uint8 category, address new_owner, uint16 quanity) ensureShopOpen(category) payInETH(referal, category, new_owner, quanity) public payable returns (bool) {
factory.mintFor(new_owner, quanity, category);
return true;
}
function convert(uint256 usdValue, bool isBZN) public view returns (uint256) {
if (isBZN) {
return bznFeed.convert(usdValue);
} else {
bool temp;
bytes32 aaa;
(aaa, temp) = ethFeed.peek();
uint256 priceForEtherInUsdWei = uint256(aaa);
return usdValue / (priceForEtherInUsdWei / 1e18);
}
}
/**
Get the price for skinned or regular guns in USD (wei)
*/
function priceFor(uint8 category, uint16 quanity) public view returns (uint256, uint256) {
require(quanity > 0);
uint256 percent = categoryPercentIncrease[category];
uint256 base = categoryPercentBase[category];
uint256 currentPrice = categoryPrice[category];
uint256 nextPrice = currentPrice;
uint256 totalPrice = 0;
//We can't use exponents because we'll overflow quickly
//Only for loop :(
for (uint i = 0; i < quanity; i++) {
nextPrice = (currentPrice * percent) / base;
currentPrice = nextPrice;
totalPrice += nextPrice;
}
//Return the next price, as this is the true price
return (nextPrice, totalPrice);
}
//Determine if a tokenId exists (has been sold)
function sold(uint256 _tokenId) public view returns (bool) {
return token.exists(_tokenId);
}
function receiveApproval(address from, uint256 tokenAmount, address tokenContract, bytes memory data) public payable returns (bool) {
address referal;
uint8 category;
uint16 quanity;
(referal, category, quanity) = abi.decode(data, (address, uint8, uint16));
require(quanity >= 1);
address payable _from = address(uint160(from));
buyWithBZN(referal, category, _from, quanity);
return true;
}
}
contract GunFactory is Ownable {
using strings for *;
uint8 public constant PREMIUM_CATEGORY = 1;
uint8 public constant MIDGRADE_CATEGORY = 2;
uint8 public constant REGULAR_CATEGORY = 3;
uint256 public constant ONE_MONTH = 2628000;
uint256 public mintedGuns = 0;
address preOrderAddress;
GunToken token;
mapping(uint8 => uint256) internal gunsMintedByCategory;
mapping(uint8 => uint256) internal totalGunsMintedByCategory;
mapping(uint8 => uint256) internal firstMonthLimit;
mapping(uint8 => uint256) internal secondMonthLimit;
mapping(uint8 => uint256) internal thirdMonthLimit;
uint256 internal startTime;
mapping(uint8 => uint256) internal currentMonthEnd;
uint256 internal monthOneEnd;
uint256 internal monthTwoEnd;
modifier onlyPreOrder {
require(msg.sender == preOrderAddress, "Not authorized");
_;
}
modifier isInitialized {
require(preOrderAddress != address(0), "No linked preorder");
require(address(token) != address(0), "No linked token");
_;
}
constructor() public {
firstMonthLimit[PREMIUM_CATEGORY] = 5000;
firstMonthLimit[MIDGRADE_CATEGORY] = 20000;
firstMonthLimit[REGULAR_CATEGORY] = 30000;
secondMonthLimit[PREMIUM_CATEGORY] = 2500;
secondMonthLimit[MIDGRADE_CATEGORY] = 10000;
secondMonthLimit[REGULAR_CATEGORY] = 15000;
thirdMonthLimit[PREMIUM_CATEGORY] = 600;
thirdMonthLimit[MIDGRADE_CATEGORY] = 3000;
thirdMonthLimit[REGULAR_CATEGORY] = 6000;
startTime = block.timestamp;
monthOneEnd = startTime + ONE_MONTH;
monthTwoEnd = startTime + ONE_MONTH + ONE_MONTH;
currentMonthEnd[PREMIUM_CATEGORY] = monthOneEnd;
currentMonthEnd[MIDGRADE_CATEGORY] = monthOneEnd;
currentMonthEnd[REGULAR_CATEGORY] = monthOneEnd;
}
function uintToString(uint v) internal pure returns (string memory) {
if (v == 0) {
return "0";
}
uint j = v;
uint len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint k = len - 1;
while (v != 0) {
bstr[k--] = byte(uint8(48 + v % 10));
v /= 10;
}
return string(bstr);
}
function mintFor(address newOwner, uint16 size, uint8 category) public onlyPreOrder isInitialized returns (uint256) {
GunPreOrder preOrder = GunPreOrder(preOrderAddress);
require(preOrder.categoryExists(category), "Invalid category");
require(!hasReachedLimit(category), "The monthly limit has been reached");
token.claimAllocation(newOwner, size, category);
mintedGuns++;
gunsMintedByCategory[category] = gunsMintedByCategory[category] + 1;
totalGunsMintedByCategory[category] = totalGunsMintedByCategory[category] + 1;
}
function hasReachedLimit(uint8 category) internal returns (bool) {
uint256 currentTime = block.timestamp;
uint256 limit = currentLimit(category);
uint256 monthEnd = currentMonthEnd[category];
//If the current block time is greater than or equal to the end of the month
if (currentTime >= monthEnd) {
//It's a new month, reset all limits
//gunsMintedByCategory[PREMIUM_CATEGORY] = 0;
//gunsMintedByCategory[MIDGRADE_CATEGORY] = 0;
//gunsMintedByCategory[REGULAR_CATEGORY] = 0;
gunsMintedByCategory[category] = 0;
//Set next month end to be equal one month in advance
//do this while the current time is greater than the next month end
while (currentTime >= monthEnd) {
monthEnd = monthEnd + ONE_MONTH;
}
//Finally, update the limit
limit = currentLimit(category);
currentMonthEnd[category] = monthEnd;
}
//Check if the limit has been reached
return gunsMintedByCategory[category] >= limit;
}
function reachedLimit(uint8 category) public view returns (bool) {
uint256 limit = currentLimit(category);
return gunsMintedByCategory[category] >= limit;
}
function currentLimit(uint8 category) public view returns (uint256) {
uint256 currentTime = block.timestamp;
uint256 limit;
if (currentTime < monthOneEnd) {
limit = firstMonthLimit[category];
} else if (currentTime < monthTwoEnd) {
limit = secondMonthLimit[category];
} else {
limit = thirdMonthLimit[category];
}
return limit;
}
function setCategoryLimit(uint8 category, uint256 firstLimit, uint256 secondLimit, uint256 thirdLimit) public onlyOwner {
require(firstMonthLimit[category] == 0);
require(secondMonthLimit[category] == 0);
require(thirdMonthLimit[category] == 0);
firstMonthLimit[category] = firstLimit;
secondMonthLimit[category] = secondLimit;
thirdMonthLimit[category] = thirdLimit;
}
/**
Attach the preOrder that will be receiving tokens being marked for sale by the
sellCar function
*/
function attachPreOrder(address dst) public onlyOwner {
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[{"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":"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":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"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"},{"constant":true,"inputs":[],"name":"COMMISSION_PERCENT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allowCreateCategory","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","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":"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":true,"inputs":[],"name":"bznFeed","outputs":[{"internalType":"contract BZNFeed","name":"","type":"address"}],"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":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"categoryKilled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":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":[{"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"},{"internalType":"address","name":"","type":"address"}],"name":"categoryReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":false,"inputs":[{"internalType":"uint8","name":"category","type":"uint8"}],"name":"createCategory","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"disableCreateCategories","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ethFeed","outputs":[{"internalType":"contract IDSValue","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":"uint8","name":"category","type":"uint8"}],"name":"killCategory","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"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":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":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","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":true,"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"requiredEtherPercentBase","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":"referral","type":"address"},{"internalType":"uint256","name":"percent","type":"uint256"}],"name":"setCommission","outputs":[],"payable":false,"stateMutability":"nonpayable","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":"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":"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":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":"uint256","name":"_tokenId","type":"uint256"}],"name":"sold","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"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","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"}]Contract Creation Code
60806040526001600b60006101000a81548160ff0219169083151502179055503480156200002c57600080fd5b50604051620035e2380380620035e2833981810160405260a08110156200005257600080fd5b81019080805190602001909291908051906020019092919080519060200190929190805190602001909291908051906020019092919050505060006200009d6200039e60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35084600b60016101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600d60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082601060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620186c360066000600160ff16815260200190815260200160002081905550620186a060076000600160ff16815260200190815260200160002081905550620186b960066000600260ff16815260200190815260200160002081905550620186a060076000600260ff16815260200190815260200160002081905550620186af60066000600360ff16815260200190815260200160002081905550620186a060076000600360ff16815260200190815260200160002081905550600a60046000735b3256965e7c3cf26e11fcaf296dfc8807c0107373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050505050620003a6565b600033905090565b61322c80620003b66000396000f3fe6080604052600436106101f85760003560e01c80638f4ffcb11161010d578063c768ad1a116100a0578063e5174e081161006f578063e5174e0814610bb5578063e950879314610c06578063f2fde38b14610c9d578063f8160b5014610cee578063fc0c546a14610d1d576101f8565b8063c768ad1a14610a30578063c8e5ae4c14610ac7578063ccba093214610b11578063d5deb15b14610b63576101f8565b8063aa30b420116100dc578063aa30b42014610909578063b404e0011461095d578063b51bcc0e14610988578063bea82b06146109de576101f8565b80638f4ffcb1146106e85780639a5ef369146108055780639c03facb14610860578063a68b8552146108b3576101f8565b80633d17604511610190578063715018a61161015f578063715018a6146105a657806373c81a8b146105bd578063762c8d1f146105fb5780638da5cb5b146106625780638f32d59b146106b9576101f8565b80633d17604514610454578063512ceb3d146104a65780635e19d05c146104f8578063690d5ff41461054f576101f8565b806324b5b280116101cc57806324b5b280146103165780632e07a5be1461036c5780632e1a7d4d146103be57806331729a45146103f9576101f8565b80627a7776146101fd57806301b49e821461024f57806321bf73841461026657806323539a84146102a4575b600080fd5b34801561020957600080fd5b506102396004803603602081101561022057600080fd5b81019080803560ff169060200190929190505050610d74565b6040518082815260200191505060405180910390f35b34801561025b57600080fd5b50610264610d8c565b005b34801561027257600080fd5b506102a26004803603602081101561028957600080fd5b81019080803560ff169060200190929190505050610e23565b005b3480156102b057600080fd5b50610300600480360360408110156102c757600080fd5b81019080803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f35565b6040518082815260200191505060405180910390f35b34801561032257600080fd5b506103526004803603602081101561033957600080fd5b81019080803560ff169060200190929190505050610f5a565b604051808215151515815260200191505060405180910390f35b34801561037857600080fd5b506103bc6004803603606081101561038f57600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050610f7a565b005b3480156103ca57600080fd5b506103f7600480360360208110156103e157600080fd5b8101908080359060200190929190505050611041565b005b34801561040557600080fd5b506104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506111c5565b005b34801561046057600080fd5b506104906004803603602081101561047757600080fd5b81019080803560ff1690602001909291905050506112a7565b6040518082815260200191505060405180910390f35b3480156104b257600080fd5b506104e2600480360360208110156104c957600080fd5b81019080803560ff1690602001909291905050506112bf565b6040518082815260200191505060405180910390f35b34801561050457600080fd5b5061050d6112d7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561055b57600080fd5b506105646112fd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156105b257600080fd5b506105bb611323565b005b3480156105c957600080fd5b506105f9600480360360208110156105e057600080fd5b81019080803560ff16906020019092919050505061145c565b005b34801561060757600080fd5b506106456004803603604081101561061e57600080fd5b81019080803560ff169060200190929190803561ffff169060200190929190505050611523565b604051808381526020018281526020019250505060405180910390f35b34801561066e57600080fd5b506106776115e3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156106c557600080fd5b506106ce61160c565b604051808215151515815260200191505060405180910390f35b6107eb600480360360808110156106fe57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561076557600080fd5b82018360208201111561077757600080fd5b8035906020019184600183028401116401000000008311171561079957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061166a565b604051808215151515815260200191505060405180910390f35b34801561081157600080fd5b5061084a6004803603604081101561082857600080fd5b81019080803590602001909291908035151590602001909291905050506116ed565b6040518082815260200191505060405180910390f35b34801561086c57600080fd5b506108996004803603602081101561088357600080fd5b8101908080359060200190929190505050611890565b604051808215151515815260200191505060405180910390f35b3480156108bf57600080fd5b506108ef600480360360208110156108d657600080fd5b81019080803560ff169060200190929190505050611947565b604051808215151515815260200191505060405180910390f35b34801561091557600080fd5b5061095b6004803603606081101561092c57600080fd5b81019080803560ff16906020019092919080359060200190929190803515159060200190929190505050611967565b005b34801561096957600080fd5b50610972611a1f565b6040518082815260200191505060405180910390f35b34801561099457600080fd5b506109c4600480360360208110156109ab57600080fd5b81019080803560ff169060200190929190505050611a24565b604051808215151515815260200191505060405180910390f35b3480156109ea57600080fd5b50610a2e60048036036060811015610a0157600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050611a44565b005b610aad60048036036080811015610a4657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff169060200190929190505050611aff565b604051808215151515815260200191505060405180910390f35b348015610ad357600080fd5b50610b0f60048036036040811015610aea57600080fd5b81019080803560ff1690602001909291908035151590602001909291905050506126d4565b005b348015610b1d57600080fd5b50610b4d60048036036020811015610b3457600080fd5b81019080803560ff169060200190929190505050612810565b6040518082815260200191505060405180910390f35b348015610b6f57600080fd5b50610b9f60048036036020811015610b8657600080fd5b81019080803560ff169060200190929190505050612828565b6040518082815260200191505060405180910390f35b348015610bc157600080fd5b50610c0460048036036020811015610bd857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612840565b005b610c8360048036036080811015610c1c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff1690602001909291905050506128fe565b604051808215151515815260200191505060405180910390f35b348015610ca957600080fd5b50610cec60048036036020811015610cc057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612f54565b005b348015610cfa57600080fd5b50610d03612fda565b604051808215151515815260200191505060405180910390f35b348015610d2957600080fd5b50610d32612fed565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600a6020528060005260406000206000915090505481565b610d9461160c565b610e06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000600b60006101000a81548160ff021916908315150217905550565b610e2b61160c565b610e9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600360008260ff1660ff16815260200190815260200160002060009054906101000a900460ff1615610ece57600080fd5b6000600260008360ff1660ff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600360008360ff1660ff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6005602052816000526040600020602052806000526040600020600091509150505481565b60026020528060005260406000206000915054906101000a900460ff1681565b610f8261160c565b610ff4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b81831161100057600080fd5b82600660008360ff1660ff1681526020019081526020016000208190555081600760008360ff1660ff16815260200190815260200160002081905550505050565b61104961160c565b6110bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600047905080821115611136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f52657175657374656420746f206d75636800000000000000000000000000000081525060200191505060405180910390fd5b60006111406115e3565b90508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015611188573d6000803e3d6000fd5b507f4e70a604b23a8edee2b1d0a656e9b9c00b73ad8bb1afc2c59381ee9f69197de7836040518082815260200191505060405180910390a1505050565b6111cd61160c565b61123f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6005811161124c57600080fd5b605f811061125957600080fd5b60058103905080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b60076020528060005260406000206000915090505481565b60066020528060005260406000206000915090505481565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61132b61160c565b61139d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61146461160c565b6114d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600b60009054906101000a900460ff166114ef57600080fd5b60018060008360ff1660ff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008060008361ffff161161153757600080fd5b6000600660008660ff1660ff1681526020019081526020016000205490506000600760008760ff1660ff1681526020019081526020016000205490506000600860008860ff1660ff1681526020019081526020016000205490506000819050600080905060008090505b8861ffff168110156115d05784868502816115b857fe5b049250829350828201915080806001019150506115a1565b5081819650965050505050509250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661164e613013565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60008060008084806020019051606081101561168557600080fd5b8101908080519060200190929190805190602001909291908051906020019092919050505082925080935081945082955050505060018161ffff1610156116cb57600080fd5b60008890506116dc84848385611aff565b506001945050505050949350505050565b600081156117aa57600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3908e1b846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561176857600080fd5b505afa15801561177c573d6000803e3d6000fd5b505050506040513d602081101561179257600080fd5b8101908080519060200190929190505050905061188a565b600080600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166359e02dd76040518163ffffffff1660e01b8152600401604080518083038186803b15801561181457600080fd5b505afa158015611828573d6000803e3d6000fd5b505050506040513d604081101561183e57600080fd5b810190808051906020019092919080519060200190929190505050809350819250505060008160001c9050670de0b6b3a7640000818161187a57fe5b04868161188357fe5b0493505050505b92915050565b6000600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f558e79836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561190557600080fd5b505afa158015611919573d6000803e3d6000fd5b505050506040513d602081101561192f57600080fd5b81019080805190602001909291905050509050919050565b60036020528060005260406000206000915054906101000a900460ff1681565b61196f61160c565b6119e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000670de0b6b3a7640000905081156119f957600190505b808302600860008660ff1660ff1681526020019081526020016000208190555050505050565b600581565b60016020528060005260406000206000915054906101000a900460ff1681565b611a4c61160c565b611abe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b82600960008360ff1660ff1681526020019081526020016000208190555081600a60008360ff1660ff16815260200190815260200160002081905550505050565b600083600160008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16611b9b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f43617465676f727920646f65736e27742065786973742100000000000000000081525060200191505060405180910390fd5b600260008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16611c34576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f43617465676f7279206973206e6f74206f70656e21000000000000000000000081525060200191505060405180910390fd5b8585858560606004604051908082528060200260200182016040528015611c6a5781602001602082028038833980820191505090505b509050611c778483611523565b82600081518110611c8457fe5b6020026020010183600381518110611c9857fe5b6020026020010182815250828152505050600081600081518110611cb857fe5b602002602001015111611d33576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5072696365206e6f74207965742073657400000000000000000000000000000081525060200191505060405180910390fd5b80600081518110611d4057fe5b6020026020010151600860008660ff1660ff16815260200190815260200160002081905550611d8481600381518110611d7557fe5b602002602001015160016116ed565b81600181518110611d9157fe5b602002602001018181525050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614611e4e576064600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050182600181518110611e2357fe5b60200260200101510281611e3357fe5b0481600281518110611e4157fe5b6020026020010181815250505b6000600a60008660ff1660ff16815260200190815260200160002054600960008760ff1660ff16815260200190815260200160002054611ea384600381518110611e9457fe5b602002602001015160006116ed565b0281611eab57fe5b04905080341015611f07576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806131a96024913960400191505060405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379cc6790856064601e86600281518110611f5757fe5b602002602001015187600181518110611f6c57fe5b6020026020010151030281611f7d57fe5b046040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015611fe757600080fd5b505af1158015611ffb573d6000803e3d6000fd5b50505050600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd85601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166064601e8760028151811061207257fe5b60200260200101518860018151811061208757fe5b602002602001015103028161209857fe5b04866002815181106120a657fe5b6020026020010151876001815181106120bb57fe5b602002602001015103036040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561216157600080fd5b505af1158015612175573d6000803e3d6000fd5b505050506040513d602081101561218b57600080fd5b810190808051906020019092919050505050600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336896c7f8b8b8e6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018361ffff1661ffff1681526020018260ff1660ff1681526020019350505050602060405180830381600087803b15801561225c57600080fd5b505af1158015612270573d6000803e3d6000fd5b505050506040513d602081101561228657600080fd5b81019080805190602001909291905050505060019750803411156122ee578373ffffffffffffffffffffffffffffffffffffffff166108fc8234039081150290604051600060405180830381858888f193505050501580156122ec573d6000803e3d6000fd5b505b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146126c5573373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156123c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546865207265666572616c2063616e6e6f74206265207468652073656e64657281525060200191505060405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415612449576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806131cd602b913960400191505060405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156124ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131606023913960400191505060405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd85888560028151811061251b57fe5b60200260200101516040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156125bf57600080fd5b505af11580156125d3573d6000803e3d6000fd5b505050506040513d60208110156125e957600080fd5b8101908080519060200190929190505050506064600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050182028161264957fe5b048260028151811061265757fe5b60200260200101818152505060008690508073ffffffffffffffffffffffffffffffffffffffff166108fc8460028151811061268f57fe5b60200260200101519081150290604051600060405180830381858888f193505050501580156126c2573d6000803e3d6000fd5b50505b50505050505050949350505050565b6126dc61160c565b61274e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60018260ff161480612763575060028260ff16145b80612771575060038260ff16145b61277a57600080fd5b600360008360ff1660ff16815260200190815260200160002060009054906101000a900460ff16156127ab57600080fd5b600160008360ff1660ff16815260200190815260200160002060009054906101000a900460ff166127db57600080fd5b80600260008460ff1660ff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60086020528060005260406000206000915090505481565b60096020528060005260406000206000915090505481565b61284861160c565b6128ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600083600160008260ff1660ff16815260200190815260200160002060009054906101000a900460ff1661299a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f43617465676f727920646f65736e27742065786973742100000000000000000081525060200191505060405180910390fd5b600260008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16612a33576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f43617465676f7279206973206e6f74206f70656e21000000000000000000000081525060200191505060405180910390fd5b85858585600080612a448584611523565b809250819350505060008211612ac2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5072696365206e6f74207965742073657400000000000000000000000000000081525060200191505060405180910390fd5b81600860008760ff1660ff168152602001908152602001600020819055506000612aed8260006116ed565b905080341015612b65576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4e6f7420656e6f7567682045746865722073656e74210000000000000000000081525060200191505060405180910390fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336896c7f8c8c8f6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018361ffff1661ffff1681526020018260ff1660ff1681526020019350505050602060405180830381600087803b158015612c2457600080fd5b505af1158015612c38573d6000803e3d6000fd5b505050506040513d6020811015612c4e57600080fd5b8101908080519060200190929190505050506001985080341115612cbc57600081340390503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612cb9573d6000803e3d6000fd5b50505b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614612f44573373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612d92576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546865207265666572616c2063616e6e6f74206265207468652073656e64657281525060200191505060405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806131cd602b913960400191505060405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612e9c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131606023913960400191505060405180910390fd5b6000600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050190506000606482840281612ef157fe5b04905060008990508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612f3f573d6000803e3d6000fd5b505050505b5050505050505050949350505050565b612f5c61160c565b612fce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612fd78161301b565b50565b600b60009054906101000a900460ff1681565b600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156130a1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806131836026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fe546865207265666572616c2063616e6e6f7420626520746865206e6577206f776e65724f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373427579696e67207769746820425a4e20726571756972657320736f6d6520457468657221546865207265666572616c2063616e6e6f7420626520746865207472616e616374696f6e206f726967696ea265627a7a72315820de6d5c9442b4a25390dc8dc47b7d73bea357bee6df3688f508502cacb779edda64736f6c634300051100320000000000000000000000002d6e10561b320c4f31a903bf0fa92a1ed58637c00000000000000000000000000e8c6f144e0327f4ffc38277b2fd8c5a7c5476e300000000000000000000000083f11770176d959b19f9cc6e2d5a051cb101bdaf000000000000000000000000729d19f657bd0614b4985cf1d82531c67569197b0000000000000000000000006524b87960c2d573ae514fd4181777e7842435d4
Deployed Bytecode
0x6080604052600436106101f85760003560e01c80638f4ffcb11161010d578063c768ad1a116100a0578063e5174e081161006f578063e5174e0814610bb5578063e950879314610c06578063f2fde38b14610c9d578063f8160b5014610cee578063fc0c546a14610d1d576101f8565b8063c768ad1a14610a30578063c8e5ae4c14610ac7578063ccba093214610b11578063d5deb15b14610b63576101f8565b8063aa30b420116100dc578063aa30b42014610909578063b404e0011461095d578063b51bcc0e14610988578063bea82b06146109de576101f8565b80638f4ffcb1146106e85780639a5ef369146108055780639c03facb14610860578063a68b8552146108b3576101f8565b80633d17604511610190578063715018a61161015f578063715018a6146105a657806373c81a8b146105bd578063762c8d1f146105fb5780638da5cb5b146106625780638f32d59b146106b9576101f8565b80633d17604514610454578063512ceb3d146104a65780635e19d05c146104f8578063690d5ff41461054f576101f8565b806324b5b280116101cc57806324b5b280146103165780632e07a5be1461036c5780632e1a7d4d146103be57806331729a45146103f9576101f8565b80627a7776146101fd57806301b49e821461024f57806321bf73841461026657806323539a84146102a4575b600080fd5b34801561020957600080fd5b506102396004803603602081101561022057600080fd5b81019080803560ff169060200190929190505050610d74565b6040518082815260200191505060405180910390f35b34801561025b57600080fd5b50610264610d8c565b005b34801561027257600080fd5b506102a26004803603602081101561028957600080fd5b81019080803560ff169060200190929190505050610e23565b005b3480156102b057600080fd5b50610300600480360360408110156102c757600080fd5b81019080803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610f35565b6040518082815260200191505060405180910390f35b34801561032257600080fd5b506103526004803603602081101561033957600080fd5b81019080803560ff169060200190929190505050610f5a565b604051808215151515815260200191505060405180910390f35b34801561037857600080fd5b506103bc6004803603606081101561038f57600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050610f7a565b005b3480156103ca57600080fd5b506103f7600480360360208110156103e157600080fd5b8101908080359060200190929190505050611041565b005b34801561040557600080fd5b506104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506111c5565b005b34801561046057600080fd5b506104906004803603602081101561047757600080fd5b81019080803560ff1690602001909291905050506112a7565b6040518082815260200191505060405180910390f35b3480156104b257600080fd5b506104e2600480360360208110156104c957600080fd5b81019080803560ff1690602001909291905050506112bf565b6040518082815260200191505060405180910390f35b34801561050457600080fd5b5061050d6112d7565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561055b57600080fd5b506105646112fd565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156105b257600080fd5b506105bb611323565b005b3480156105c957600080fd5b506105f9600480360360208110156105e057600080fd5b81019080803560ff16906020019092919050505061145c565b005b34801561060757600080fd5b506106456004803603604081101561061e57600080fd5b81019080803560ff169060200190929190803561ffff169060200190929190505050611523565b604051808381526020018281526020019250505060405180910390f35b34801561066e57600080fd5b506106776115e3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156106c557600080fd5b506106ce61160c565b604051808215151515815260200191505060405180910390f35b6107eb600480360360808110156106fe57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019064010000000081111561076557600080fd5b82018360208201111561077757600080fd5b8035906020019184600183028401116401000000008311171561079957600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061166a565b604051808215151515815260200191505060405180910390f35b34801561081157600080fd5b5061084a6004803603604081101561082857600080fd5b81019080803590602001909291908035151590602001909291905050506116ed565b6040518082815260200191505060405180910390f35b34801561086c57600080fd5b506108996004803603602081101561088357600080fd5b8101908080359060200190929190505050611890565b604051808215151515815260200191505060405180910390f35b3480156108bf57600080fd5b506108ef600480360360208110156108d657600080fd5b81019080803560ff169060200190929190505050611947565b604051808215151515815260200191505060405180910390f35b34801561091557600080fd5b5061095b6004803603606081101561092c57600080fd5b81019080803560ff16906020019092919080359060200190929190803515159060200190929190505050611967565b005b34801561096957600080fd5b50610972611a1f565b6040518082815260200191505060405180910390f35b34801561099457600080fd5b506109c4600480360360208110156109ab57600080fd5b81019080803560ff169060200190929190505050611a24565b604051808215151515815260200191505060405180910390f35b3480156109ea57600080fd5b50610a2e60048036036060811015610a0157600080fd5b810190808035906020019092919080359060200190929190803560ff169060200190929190505050611a44565b005b610aad60048036036080811015610a4657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff169060200190929190505050611aff565b604051808215151515815260200191505060405180910390f35b348015610ad357600080fd5b50610b0f60048036036040811015610aea57600080fd5b81019080803560ff1690602001909291908035151590602001909291905050506126d4565b005b348015610b1d57600080fd5b50610b4d60048036036020811015610b3457600080fd5b81019080803560ff169060200190929190505050612810565b6040518082815260200191505060405180910390f35b348015610b6f57600080fd5b50610b9f60048036036020811015610b8657600080fd5b81019080803560ff169060200190929190505050612828565b6040518082815260200191505060405180910390f35b348015610bc157600080fd5b50610c0460048036036020811015610bd857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612840565b005b610c8360048036036080811015610c1c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803560ff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803561ffff1690602001909291905050506128fe565b604051808215151515815260200191505060405180910390f35b348015610ca957600080fd5b50610cec60048036036020811015610cc057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612f54565b005b348015610cfa57600080fd5b50610d03612fda565b604051808215151515815260200191505060405180910390f35b348015610d2957600080fd5b50610d32612fed565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b600a6020528060005260406000206000915090505481565b610d9461160c565b610e06576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000600b60006101000a81548160ff021916908315150217905550565b610e2b61160c565b610e9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600360008260ff1660ff16815260200190815260200160002060009054906101000a900460ff1615610ece57600080fd5b6000600260008360ff1660ff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600360008360ff1660ff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6005602052816000526040600020602052806000526040600020600091509150505481565b60026020528060005260406000206000915054906101000a900460ff1681565b610f8261160c565b610ff4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b81831161100057600080fd5b82600660008360ff1660ff1681526020019081526020016000208190555081600760008360ff1660ff16815260200190815260200160002081905550505050565b61104961160c565b6110bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600047905080821115611136576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f52657175657374656420746f206d75636800000000000000000000000000000081525060200191505060405180910390fd5b60006111406115e3565b90508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015611188573d6000803e3d6000fd5b507f4e70a604b23a8edee2b1d0a656e9b9c00b73ad8bb1afc2c59381ee9f69197de7836040518082815260200191505060405180910390a1505050565b6111cd61160c565b61123f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6005811161124c57600080fd5b605f811061125957600080fd5b60058103905080600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055505050565b60076020528060005260406000206000915090505481565b60066020528060005260406000206000915090505481565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61132b61160c565b61139d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b61146461160c565b6114d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600b60009054906101000a900460ff166114ef57600080fd5b60018060008360ff1660ff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008060008361ffff161161153757600080fd5b6000600660008660ff1660ff1681526020019081526020016000205490506000600760008760ff1660ff1681526020019081526020016000205490506000600860008860ff1660ff1681526020019081526020016000205490506000819050600080905060008090505b8861ffff168110156115d05784868502816115b857fe5b049250829350828201915080806001019150506115a1565b5081819650965050505050509250929050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661164e613013565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b60008060008084806020019051606081101561168557600080fd5b8101908080519060200190929190805190602001909291908051906020019092919050505082925080935081945082955050505060018161ffff1610156116cb57600080fd5b60008890506116dc84848385611aff565b506001945050505050949350505050565b600081156117aa57600f60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a3908e1b846040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561176857600080fd5b505afa15801561177c573d6000803e3d6000fd5b505050506040513d602081101561179257600080fd5b8101908080519060200190929190505050905061188a565b600080600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166359e02dd76040518163ffffffff1660e01b8152600401604080518083038186803b15801561181457600080fd5b505afa158015611828573d6000803e3d6000fd5b505050506040513d604081101561183e57600080fd5b810190808051906020019092919080519060200190929190505050809350819250505060008160001c9050670de0b6b3a7640000818161187a57fe5b04868161188357fe5b0493505050505b92915050565b6000600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16634f558e79836040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561190557600080fd5b505afa158015611919573d6000803e3d6000fd5b505050506040513d602081101561192f57600080fd5b81019080805190602001909291905050509050919050565b60036020528060005260406000206000915054906101000a900460ff1681565b61196f61160c565b6119e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000670de0b6b3a7640000905081156119f957600190505b808302600860008660ff1660ff1681526020019081526020016000208190555050505050565b600581565b60016020528060005260406000206000915054906101000a900460ff1681565b611a4c61160c565b611abe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b82600960008360ff1660ff1681526020019081526020016000208190555081600a60008360ff1660ff16815260200190815260200160002081905550505050565b600083600160008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16611b9b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f43617465676f727920646f65736e27742065786973742100000000000000000081525060200191505060405180910390fd5b600260008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16611c34576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f43617465676f7279206973206e6f74206f70656e21000000000000000000000081525060200191505060405180910390fd5b8585858560606004604051908082528060200260200182016040528015611c6a5781602001602082028038833980820191505090505b509050611c778483611523565b82600081518110611c8457fe5b6020026020010183600381518110611c9857fe5b6020026020010182815250828152505050600081600081518110611cb857fe5b602002602001015111611d33576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5072696365206e6f74207965742073657400000000000000000000000000000081525060200191505060405180910390fd5b80600081518110611d4057fe5b6020026020010151600860008660ff1660ff16815260200190815260200160002081905550611d8481600381518110611d7557fe5b602002602001015160016116ed565b81600181518110611d9157fe5b602002602001018181525050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614611e4e576064600460008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050182600181518110611e2357fe5b60200260200101510281611e3357fe5b0481600281518110611e4157fe5b6020026020010181815250505b6000600a60008660ff1660ff16815260200190815260200160002054600960008760ff1660ff16815260200190815260200160002054611ea384600381518110611e9457fe5b602002602001015160006116ed565b0281611eab57fe5b04905080341015611f07576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806131a96024913960400191505060405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166379cc6790856064601e86600281518110611f5757fe5b602002602001015187600181518110611f6c57fe5b6020026020010151030281611f7d57fe5b046040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b158015611fe757600080fd5b505af1158015611ffb573d6000803e3d6000fd5b50505050600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd85601060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166064601e8760028151811061207257fe5b60200260200101518860018151811061208757fe5b602002602001015103028161209857fe5b04866002815181106120a657fe5b6020026020010151876001815181106120bb57fe5b602002602001015103036040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b15801561216157600080fd5b505af1158015612175573d6000803e3d6000fd5b505050506040513d602081101561218b57600080fd5b810190808051906020019092919050505050600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336896c7f8b8b8e6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018361ffff1661ffff1681526020018260ff1660ff1681526020019350505050602060405180830381600087803b15801561225c57600080fd5b505af1158015612270573d6000803e3d6000fd5b505050506040513d602081101561228657600080fd5b81019080805190602001909291905050505060019750803411156122ee578373ffffffffffffffffffffffffffffffffffffffff166108fc8234039081150290604051600060405180830381858888f193505050501580156122ec573d6000803e3d6000fd5b505b600073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16146126c5573373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156123c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546865207265666572616c2063616e6e6f74206265207468652073656e64657281525060200191505060405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff161415612449576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806131cd602b913960400191505060405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1614156124ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131606023913960400191505060405180910390fd5b600d60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd85888560028151811061251b57fe5b60200260200101516040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019350505050602060405180830381600087803b1580156125bf57600080fd5b505af11580156125d3573d6000803e3d6000fd5b505050506040513d60208110156125e957600080fd5b8101908080519060200190929190505050506064600460008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050182028161264957fe5b048260028151811061265757fe5b60200260200101818152505060008690508073ffffffffffffffffffffffffffffffffffffffff166108fc8460028151811061268f57fe5b60200260200101519081150290604051600060405180830381858888f193505050501580156126c2573d6000803e3d6000fd5b50505b50505050505050949350505050565b6126dc61160c565b61274e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60018260ff161480612763575060028260ff16145b80612771575060038260ff16145b61277a57600080fd5b600360008360ff1660ff16815260200190815260200160002060009054906101000a900460ff16156127ab57600080fd5b600160008360ff1660ff16815260200190815260200160002060009054906101000a900460ff166127db57600080fd5b80600260008460ff1660ff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60086020528060005260406000206000915090505481565b60096020528060005260406000206000915090505481565b61284861160c565b6128ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600f60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600083600160008260ff1660ff16815260200190815260200160002060009054906101000a900460ff1661299a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f43617465676f727920646f65736e27742065786973742100000000000000000081525060200191505060405180910390fd5b600260008260ff1660ff16815260200190815260200160002060009054906101000a900460ff16612a33576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f43617465676f7279206973206e6f74206f70656e21000000000000000000000081525060200191505060405180910390fd5b85858585600080612a448584611523565b809250819350505060008211612ac2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f5072696365206e6f74207965742073657400000000000000000000000000000081525060200191505060405180910390fd5b81600860008760ff1660ff168152602001908152602001600020819055506000612aed8260006116ed565b905080341015612b65576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f4e6f7420656e6f7567682045746865722073656e74210000000000000000000081525060200191505060405180910390fd5b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166336896c7f8c8c8f6040518463ffffffff1660e01b8152600401808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018361ffff1661ffff1681526020018260ff1660ff1681526020019350505050602060405180830381600087803b158015612c2457600080fd5b505af1158015612c38573d6000803e3d6000fd5b505050506040513d6020811015612c4e57600080fd5b8101908080519060200190929190505050506001985080341115612cbc57600081340390503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015612cb9573d6000803e3d6000fd5b50505b600073ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff1614612f44573373ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612d92576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f546865207265666572616c2063616e6e6f74206265207468652073656e64657281525060200191505060405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612e17576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001806131cd602b913960400191505060405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff161415612e9c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806131606023913960400191505060405180910390fd5b6000600460008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205460050190506000606482840281612ef157fe5b04905060008990508073ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f19350505050158015612f3f573d6000803e3d6000fd5b505050505b5050505050505050949350505050565b612f5c61160c565b612fce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612fd78161301b565b50565b600b60009054906101000a900460ff1681565b600b60019054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156130a1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806131836026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fe546865207265666572616c2063616e6e6f7420626520746865206e6577206f776e65724f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373427579696e67207769746820425a4e20726571756972657320736f6d6520457468657221546865207265666572616c2063616e6e6f7420626520746865207472616e616374696f6e206f726967696ea265627a7a72315820de6d5c9442b4a25390dc8dc47b7d73bea357bee6df3688f508502cacb779edda64736f6c63430005110032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002d6e10561b320c4f31a903bf0fa92a1ed58637c00000000000000000000000000e8c6f144e0327f4ffc38277b2fd8c5a7c5476e300000000000000000000000083f11770176d959b19f9cc6e2d5a051cb101bdaf000000000000000000000000729d19f657bd0614b4985cf1d82531c67569197b0000000000000000000000006524b87960c2d573ae514fd4181777e7842435d4
-----Decoded View---------------
Arg [0] : tokenAddress (address): 0x2D6e10561B320C4F31a903bF0FA92a1Ed58637C0
Arg [1] : tokenFactory (address): 0x0e8c6F144e0327F4FfC38277B2Fd8C5A7C5476e3
Arg [2] : gp (address): 0x83f11770176d959B19F9cC6E2d5a051cb101bdAf
Arg [3] : isd (address): 0x729D19f657BD0614b4985Cf1D82531c67569197B
Arg [4] : bzn_address (address): 0x6524B87960c2d573AE514fd4181777E7842435d4
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000002d6e10561b320c4f31a903bf0fa92a1ed58637c0
Arg [1] : 0000000000000000000000000e8c6f144e0327f4ffc38277b2fd8c5a7c5476e3
Arg [2] : 00000000000000000000000083f11770176d959b19f9cc6e2d5a051cb101bdaf
Arg [3] : 000000000000000000000000729d19f657bd0614b4985cf1d82531c67569197b
Arg [4] : 0000000000000000000000006524b87960c2d573ae514fd4181777e7842435d4
Deployed Bytecode Sourcemap
128123:11998:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;129723:57;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129723:57:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;129723:57:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;134782:98;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134782:98:0;;;:::i;:::-;;135759:201;;8:9:-1;5:2;;;30:1;27;20:12;5:2;135759:201:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;135759:201:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;129113:74;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129113:74:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;129113:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;128785:42;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128785:42:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128785:42:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;135287:248;;8:9:-1;5:2;;;30:1;27;20:12;5:2;135287:248:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;135287:248:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;136750:320;;8:9:-1;5:2;;;30:1;27;20:12;5:2;136750:320:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;136750:320:0;;;;;;;;;;;;;;;;;:::i;:::-;;134945:267;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134945:267:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;134945:267:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;129443:52;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129443:52:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;129443:52:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;129380:56;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129380:56:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;129380:56:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;130059:23;;8:9:-1;5:2;;;30:1;27;20:12;5:2;130059:23:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;130089:22;;8:9:-1;5:2;;;30:1;27;20:12;5:2;130089:22:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;66243:140;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66243:140:0;;;:::i;:::-;;134614:156;;8:9:-1;5:2;;;30:1;27;20:12;5:2;134614:156:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;134614:156:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;138624:796;;8:9:-1;5:2;;;30:1;27;20:12;5:2;138624:796:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;138624:796:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;65432:79;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65432:79:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;65798:94;;8:9:-1;5:2;;;30:1;27;20:12;5:2;65798:94:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;139600:518;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;139600:518:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;21:11:-1;8;5:28;2:2;;;46:1;43;36:12;2:2;139600:518:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;139600: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;139600: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;;139600:518:0;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;138105:430;;8:9:-1;5:2;;;30:1;27;20:12;5:2;138105:430:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;138105:430:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;139481:107;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139481:107:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;139481:107:0;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;128834:44;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128834:44:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128834:44:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;136378:243;;8:9:-1;5:2;;;30:1;27;20:12;5:2;136378:243:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;136378:243:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;128643:46;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128643:46:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;128734:44;;8:9:-1;5:2;;;30:1;27;20:12;5:2;128734:44:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;128734:44:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;135547:200;;8:9:-1;5:2;;;30:1;27;20:12;5:2;135547:200:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;135547:200:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;137352:299;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;137352:299:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;136019:280;;8:9:-1;5:2;;;30:1;27;20:12;5:2;136019:280:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;136019:280:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;129549:46;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129549:46:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;129549:46:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;129663:53;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129663:53:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;129663:53:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;137082:117;;8:9:-1;5:2;;;30:1;27;20:12;5:2;137082:117:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;137082:117:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;137804:289;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;137804:289:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;66538:109;;8:9:-1;5:2;;;30:1;27;20:12;5:2;66538:109:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;66538:109:0;;;;;;;;;;;;;;;;;;;:::i;:::-;;129787:38;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129787:38:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;129864:21;;8:9:-1;5:2;;;30:1;27;20:12;5:2;129864:21:0;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;129723:57;;;;;;;;;;;;;;;;;:::o;134782:98::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134867:5;134845:19;;:27;;;;;;;;;;;;;;;;;;134782:98::o;135759:201::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135834:14;:24;135849:8;135834:24;;;;;;;;;;;;;;;;;;;;;;;;;135833:25;135825:34;;;;;;135905:5;135880:12;:22;135893:8;135880:22;;;;;;;;;;;;;;;;:30;;;;;;;;;;;;;;;;;;135948:4;135921:14;:24;135936:8;135921:24;;;;;;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;135759:201;:::o;129113:74::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;128785:42::-;;;;;;;;;;;;;;;;;;;;;;:::o;135287:248::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135410:4;135399:8;:15;135391:24;;;;;;135472:8;135436:23;:33;135460:8;135436:33;;;;;;;;;;;;;;;:44;;;;135523:4;135491:19;:29;135511:8;135491:29;;;;;;;;;;;;;;;:36;;;;135287:248;;;:::o;136750:320::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136812:15;136830:21;136812:39;;136882:7;136872:6;:17;;136864:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136932:22;136973:7;:5;:7::i;:::-;136932:50;;137003:6;:15;;:23;137019:6;137003:23;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;137003:23:0;137044:18;137055:6;137044:18;;;;;;;;;;;;;;;;;;65701:1;;136750:320;:::o;134945:267::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;128688:1;135039:7;:28;135031:37;;;;;;135097:2;135087:7;:12;135079:21;;;;;;128688:1;135121:7;:28;135111:38;;135197:7;135170:14;:24;135185:8;135170:24;;;;;;;;;;;;;;;:34;;;;134945:267;;:::o;129443:52::-;;;;;;;;;;;;;;;;;:::o;129380:56::-;;;;;;;;;;;;;;;;;:::o;130059:23::-;;;;;;;;;;;;;:::o;130089:22::-;;;;;;;;;;;;;:::o;66243:140::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66342:1;66305:40;;66326:6;;;;;;;;;;;66305:40;;;;;;;;;;;;66373:1;66356:6;;:19;;;;;;;;;;;;;;;;;;66243:140::o;134614:156::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;134690:19;;;;;;;;;;;134682:28;;;;;;134758:4;134731:14;:24;134746:8;134731:24;;;;;;;;;;;;;;;;:31;;;;;;;;;;;;;;;;;;134614:156;:::o;138624:796::-;138695:7;138704;138742:1;138732:7;:11;;;138724:20;;;;;;138755:15;138773:23;:33;138797:8;138773:33;;;;;;;;;;;;;;;;138755:51;;138817:12;138832:19;:29;138852:8;138832:29;;;;;;;;;;;;;;;;138817:44;;138874:20;138897:13;:23;138911:8;138897:23;;;;;;;;;;;;;;;;138874:46;;138931:17;138951:12;138931:32;;138974:18;138995:1;138974:22;;139105:6;139114:1;139105:10;;139100:210;139121:7;139117:11;;:1;:11;139100:210;;;139189:4;139178:7;139163:12;:22;139162:31;;;;;;139150:43;;139237:9;139222:24;;139289:9;139275:23;;;;139130:3;;;;;;;139100:210;;;;139390:9;139401:10;139382:30;;;;;;;;;138624:796;;;;;:::o;65432:79::-;65470:7;65497:6;;;;;;;;;;;65490:13;;65432:79;:::o;65798:94::-;65838:4;65878:6;;;;;;;;;;;65862:22;;:12;:10;:12::i;:::-;:22;;;65855:29;;65798:94;:::o;139600:518::-;139726:4;139743:15;139769:14;139794;139871:4;139860:42;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;139860:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;139829:73;;;;;;;;;;;;;;;139942:1;139931:7;:12;;;;139923:21;;;;;;139965;140005:4;139965:46;;140033:45;140044:7;140053:8;140063:5;140070:7;140033:10;:45::i;:::-;;140106:4;140099:11;;;;;;139600:518;;;;;;:::o;138105:430::-;138173:7;138197:5;138193:335;;;138226:7;;;;;;;;;;;:15;;;138242:8;138226:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;138226:25:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;138226:25:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;138226:25:0;;;;;;;;;;;;;;;;138219:32;;;;138193:335;138284:9;138308:11;138348:7;;;;;;;;;;;:12;;;:14;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;138348:14:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;138348:14:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;138348:14:0;;;;;;;;;;;;;;;;;;;;;;;;;138334:28;;;;;;;;138395:29;138435:3;138427:12;;138395:44;;138511:4;138487:21;:28;;;;;;138475:8;:41;;;;;;138468:48;;;;;138105:430;;;;;:::o;139481:107::-;139534:4;139558:5;;;;;;;;;;;:12;;;139571:8;139558:22;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;139558:22:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;139558:22:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;139558:22:0;;;;;;;;;;;;;;;;139551:29;;139481:107;;;:::o;128834:44::-;;;;;;;;;;;;;;;;;;;;;;:::o;136378:243::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136467:16;136486:4;136467:23;;136505:5;136501:50;;;136538:1;136527:12;;136501:50;136605:8;136597:5;:16;136571:13;:23;136585:8;136571:23;;;;;;;;;;;;;;;:42;;;;65701:1;136378:243;;;:::o;128643:46::-;128688:1;128643:46;:::o;128734:44::-;;;;;;;;;;;;;;;;;;;;;;:::o;135547:200::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;135680:7;135647:20;:30;135668:8;135647:30;;;;;;;;;;;;;;;:40;;;;135735:4;135698:24;:34;135723:8;135698:34;;;;;;;;;;;;;;;:41;;;;135547:200;;;:::o;137352:299::-;137545:4;137463:8;130296:14;:24;130311:8;130296:24;;;;;;;;;;;;;;;;;;;;;;;;;130288:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130367:12;:22;130380:8;130367:22;;;;;;;;;;;;;;;;;;;;;;;;;130359:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137482:7;137491:8;137501:9;137512:7;131990:23;132030:1;132016: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;132016:16:0;;;;131990:42;;132150:27;132159:8;132169:7;132150:8;:27::i;:::-;132126:6;132133:1;132126:9;;;;;;;;;;;;;132137:6;132144:1;132137:9;;;;;;;;;;;;;132125:52;;;;;;;;;;132208:1;132196:6;132203:1;132196:9;;;;;;;;;;;;;;:13;132188:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132282:6;132289:1;132282:9;;;;;;;;;;;;;;132256:13;:23;132270:8;132256:23;;;;;;;;;;;;;;;:35;;;;132324:24;132332:6;132339:1;132332:9;;;;;;;;;;;;;;132343:4;132324:7;:24::i;:::-;132312:6;132319:1;132312:9;;;;;;;;;;;;;:36;;;;;132507:1;132488:21;;:7;:21;;;132484:132;;132601:3;132573:14;:23;132588:7;132573:23;;;;;;;;;;;;;;;;128688:1;132552:44;132539:6;132546:1;132539:9;;;;;;;;;;;;;;:58;132538:66;;;;;;132526:6;132533:1;132526:9;;;;;;;;;;;;;:78;;;;;132484:132;132636:21;132723:24;:34;132748:8;132723:34;;;;;;;;;;;;;;;;132689:20;:30;132710:8;132689:30;;;;;;;;;;;;;;;;132661:25;132669:6;132676:1;132669:9;;;;;;;;;;;;;;132680:5;132661:7;:25::i;:::-;:58;132660:97;;;;;;132636:121;;132799:13;132786:9;:26;;132778:75;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;132874:3;;;;;;;;;;;:12;;;132887:9;132932:3;132926:2;132913:6;132920:1;132913:9;;;;;;;;;;;;;;132901:6;132908:1;132901:9;;;;;;;;;;;;;;:21;132900:28;132899:36;;;;;;132874:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132874:63:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132874:63:0;;;;132948:3;;;;;;;;;;;:16;;;132965:9;132976:8;;;;;;;;;;;133044:3;133038:2;133025:6;133032:1;133025:9;;;;;;;;;;;;;;133013:6;133020:1;133013:9;;;;;;;;;;;;;;:21;133012:28;133011:36;;;;;;132998:6;133005:1;132998:9;;;;;;;;;;;;;;132986:6;132993:1;132986:9;;;;;;;;;;;;;;:21;:62;132948:101;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;132948:101:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;132948:101:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;132948:101:0;;;;;;;;;;;;;;;;;137562:7;;;;;;;;;;;:15;;;137578:9;137589:7;137598:8;137562:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;137562:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;137562:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;137562:45:0;;;;;;;;;;;;;;;;;137639:4;137632:11;;133108:13;133096:9;:25;133092:103;;;133138:9;:18;;:45;133169:13;133157:9;:25;133138:45;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;133138:45:0;133092:103;133238:1;133219:21;;:7;:21;;;133215:607;;133276:10;133265:21;;:7;:21;;;;133257:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133357:9;133346:20;;:7;:20;;;;133338:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133448:9;133437:20;;:7;:20;;;;133429:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;133526:3;;;;;;;;;;;:16;;;133543:9;133554:7;133563:6;133570:1;133563:9;;;;;;;;;;;;;;133526:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;133526:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;133526:47:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;133526:47:0;;;;;;;;;;;;;;;;;133681:3;133653:14;:23;133668:7;133653:23;;;;;;;;;;;;;;;;128688:1;133632:44;133615:13;:62;133614:70;;;;;;133602:6;133609:1;133602:9;;;;;;;;;;;;;:82;;;;;133713:24;133756:7;133713:52;;133782:8;:17;;:28;133800:6;133807:1;133800:9;;;;;;;;;;;;;;133782:28;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;133782:28:0;133215:607;;130426:1;;;;;;137352:299;;;;;;;:::o;136019:280::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;136116:1;136104:8;:13;;;:30;;;;136133:1;136121:8;:13;;;136104:30;:47;;;;136150:1;136138:8;:13;;;136104:47;136096:56;;;;;;136172:14;:24;136187:8;136172:24;;;;;;;;;;;;;;;;;;;;;;;;;136171:25;136163:34;;;;;;136216:14;:24;136231:8;136216:24;;;;;;;;;;;;;;;;;;;;;;;;;136208:33;;;;;;136287:4;136262:12;:22;136275:8;136262:22;;;;;;;;;;;;;;;;:29;;;;;;;;;;;;;;;;;;136019:280;;:::o;129549:46::-;;;;;;;;;;;;;;;;;:::o;129663:53::-;;;;;;;;;;;;;;;;;:::o;137082:117::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137178:12;137160:7;;:31;;;;;;;;;;;;;;;;;;137082:117;:::o;137804:289::-;137991:4;137909:8;130296:14;:24;130311:8;130296:24;;;;;;;;;;;;;;;;;;;;;;;;;130288:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130367:12;:22;130380:8;130367:22;;;;;;;;;;;;;;;;;;;;;;;;;130359:56;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;137928:7;137937:8;137947:9;137958:7;130590:16;130617:18;130671:27;130680:8;130690:7;130671:8;:27::i;:::-;130646:52;;;;;;;;130728:1;130717:8;:12;130709:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;130798:8;130772:13;:23;130786:8;130772:23;;;;;;;;;;;;;;;:34;;;;130845:13;130861:26;130869:10;130881:5;130861:7;:26::i;:::-;130845:42;;130929:5;130916:9;:18;;130908:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;138008:7;;;;;;;;;;;:15;;;138024:9;138035:7;138044:8;138008:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;138008:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;138008:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;138008:45:0;;;;;;;;;;;;;;;;;138081:4;138074:11;;131020:5;131008:9;:17;131004:128;;;131042:14;131071:5;131059:9;:17;131042:34;;131093:10;:19;;:27;131113:6;131093:27;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;131093:27:0;131004:128;;131175:1;131156:21;;:7;:21;;;131152:668;;131213:10;131202:21;;:7;:21;;;;131194:66;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131294:9;131283:20;;:7;:20;;;;131275:76;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131385:9;131374:20;;:7;:20;;;;131366:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;131546:22;131592:14;:23;131607:7;131592:23;;;;;;;;;;;;;;;;128688:1;131571:44;131546:69;;131632:17;131679:3;131661:14;131653:5;:22;131652:30;;;;;;131632:50;;131711:24;131754:7;131711:52;;131780:8;:17;;:28;131798:9;131780:28;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;131780:28:0;131152:668;;;;130426:1;;;;;;;137804:289;;;;;;;:::o;66538:109::-;65644:9;:7;:9::i;:::-;65636:54;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66611:28;66630:8;66611:18;:28::i;:::-;66538:109;:::o;129787:38::-;;;;;;;;;;;;;:::o;129864:21::-;;;;;;;;;;;;;:::o;28032:98::-;28077:15;28112:10;28105:17;;28032:98;:::o;66753:229::-;66847:1;66827:22;;:8;:22;;;;66819:73;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66937:8;66908:38;;66929:6;;;;;;;;;;;66908:38;;;;;;;;;;;;66966:8;66957:6;;:17;;;;;;;;;;;;;;;;;;66753:229;:::o
Swarm Source
bzzr://de6d5c9442b4a25390dc8dc47b7d73bea357bee6df3688f508502cacb779edda
Loading...
Loading
Loading...
Loading
Net Worth in USD
$30.28
Net Worth in ETH
0.012898
Token Allocations
BNB
99.97%
ETH
0.02%
POL
0.01%
Multichain Portfolio | 33 Chains
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.