Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Grant Role | 15888893 | 838 days ago | IN | 0 ETH | 0.00086988 |
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
GrowerPrinter
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import "@openzeppelin/contracts/access/AccessControl.sol"; import "@openzeppelin/contracts/utils/Base64.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "./strings.sol"; contract GrowerPrinter is AccessControl { using Strings for uint256; using strings for *; bytes32 public constant CONSUMER_ROLE = keccak256("CONSUMER_ROLE"); constructor() { _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); } function json( string memory growerPunk, string memory attrs, uint256 length, uint256 maxLength, uint256 tokenId ) external view onlyRole(CONSUMER_ROLE) returns (string memory) { strings.slice memory sliceAttr = attrs.toSlice(); strings.slice memory delimAttr = ", ".toSlice(); string[] memory attrParts = new string[](sliceAttr.count(delimAttr) + 1); for (uint256 i = 0; i < attrParts.length; i++) { attrParts[i] = sliceAttr.split(delimAttr).toString(); } string memory attributes = string.concat('","attributes":[{"trait_type":"Head","value":"', attrParts[0], '"}'); for (uint256 i = 1; i < attrParts.length; i++) { attributes = string.concat(attributes, ',{"trait_type":"Features","value":"', attrParts[i], '"}'); } if (length >= maxLength) { attributes = string.concat(attributes, ',{"trait_type":"Growth","value":"GROWN"}'); } else { string memory growth = "O"; uint256 count = 1; while (count < length / 10) { growth = string.concat(growth, "O"); count += 2; } attributes = string.concat(attributes, ',{"trait_type":"Growth","value":"GR', growth, 'WING"}'); } return Base64.encode( bytes( string.concat( '{"name":"GrowerPunk #', tokenId.toString(), attributes, '],"description":"GrowerPunks","image":"data:image/svg+xml;base64,', Base64.encode(bytes(growerPunk)), '"}' ) ) ); } function svg( string memory punk, string memory attrs, uint256 length ) external view onlyRole(CONSUMER_ROLE) returns (string memory) { strings.slice memory slicePunk = punk.toSlice(); slicePunk .beyond( 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 24 24">' .toSlice() ) .until("</svg>".toSlice()); // determine gender + skin color bool isMale = !hasAttr("Female", attrs); string memory skinColor = colorAtPixel(slicePunk, isMale ? "7" : "9", "23"); // draw the shaft if (isMale) { // draw tip string memory colorAtTipTop = colorAtPixel(slicePunk, "12", "5"); string memory colorAtTipBot = colorAtPixel(slicePunk, "12", "6"); if (colorAtTipTop.toSlice().equals(skinColor.toSlice())) { slicePunk = slicePunk .concat( '<rect x="12" y="5" width="1" height="1" shape-rendering="crispEdges" fill="#000000ff"/>' .toSlice() ) .toSlice(); } if (colorAtTipBot.toSlice().equals(skinColor.toSlice())) { slicePunk = slicePunk .concat( '<rect x="12" y="6" width="1" height="1" shape-rendering="crispEdges" fill="#000000ff"/>' .toSlice() ) .toSlice(); } // bit of makeup if (!hasAttr("Big Beard", attrs)) { slicePunk = slicePunk .concat( string .concat( '<rect x="10" y="23" width="1" height="1" shape-rendering="crispEdges" fill="', skinColor, '"/>' ) .toSlice() ) .toSlice(); } if (hasAttr("Hoodie", attrs)) { // draw a nice long sheathed shaft slicePunk = slicePunk .concat( string .concat( '<rect x="4" y="24" width="12" height="', (length + 5).toString(), '" shape-rendering="crispEdges" fill="#000000ff"/><rect x="7" y="24" width="4" height="1" shape-rendering="crispEdges" fill="#000000ff"/>', '<rect x="5" y="24" width="8" shape-rendering="crispEdges" fill="#555555ff"', string.concat(' height="', (length + 5).toString(), '"/>') ) .toSlice() ) .toSlice(); } else { // draw a nice long shaft slicePunk = string .concat( '<rect x="6" y="19" width="10" height="', (length + 5).toString(), '" shape-rendering="crispEdges" fill="#000000ff"/>', '<rect x="7" y="19" width="8" shape-rendering="crispEdges"', string.concat(' fill="', skinColor, '" height="', (length + 5).toString(), '"/>') ) .toSlice() .concat(slicePunk) .toSlice(); // draw additional traits if (hasAttr("Gold Chain", attrs)) { if (!hasAttr("Luxurious Beard", attrs) && !hasAttr("Big Beard", attrs)) { slicePunk = slicePunk .concat( '<rect x="10" y="22" width="5" height="1" shape-rendering="crispEdges" fill="#ffc926ff"/>' .toSlice() ) .toSlice(); } } else if (hasAttr("Chinstrap", attrs) || hasAttr("Front Beard", attrs) || hasAttr("Goat", attrs)) { if (hasAttr("Silver Chain", attrs)) { slicePunk = slicePunk .concat( '<rect x="10" y="22" width="1" height="1" shape-rendering="crispEdges" fill="#dfdfdfff"/><rect x="14" y="22" width="1" height="1" shape-rendering="crispEdges" fill="#dfdfdfff"/>' .toSlice() ) .toSlice(); } else { slicePunk = slicePunk .concat( string .concat( '<rect x="10" y="22" width="1" height="1" shape-rendering="crispEdges" fill="', skinColor, '"/>' ) .toSlice() ) .toSlice(); } } else if (!hasAttr("Big Beard", attrs) && hasAttr("Silver Chain", attrs)) { slicePunk = slicePunk .concat( '<rect x="10" y="22" width="5" height="1" shape-rendering="crispEdges" fill="#dfdfdfff"/>' .toSlice() ) .toSlice(); } } } else { // draw tip if (!hasAttr("Mohawk", attrs)) { string memory colorAtTipTop = colorAtPixel(slicePunk, "12", "8"); string memory colorAtTipBot = colorAtPixel(slicePunk, "12", "9"); if (colorAtTipTop.toSlice().equals(skinColor.toSlice())) { slicePunk = slicePunk .concat( '<rect x="12" y="8" width="1" height="1" shape-rendering="crispEdges" fill="#000000ff"/>' .toSlice() ) .toSlice(); } if (colorAtTipBot.toSlice().equals(skinColor.toSlice())) { slicePunk = slicePunk .concat( '<rect x="12" y="9" width="1" height="1" shape-rendering="crispEdges" fill="#000000ff"/>' .toSlice() ) .toSlice(); } } // draw a nice long shaft slicePunk = string .concat( '<rect x="8" y="19" width="8" height="', (length + 5).toString(), '" shape-rendering="crispEdges" fill="#000000ff"/>', '<rect x="9" y="19" width="6" shape-rendering="crispEdges"', string.concat(' fill="', skinColor, '" height="', (length + 5).toString(), '"/>') ) .toSlice() .concat(slicePunk) .toSlice(); // draw additional traits if (hasAttr("Choker", attrs)) { if (hasAttr("Straight Hair", attrs)) { slicePunk = slicePunk .concat( string .concat( '<rect x="12" y="23" width="1" height="1" shape-rendering="crispEdges"', string.concat(' fill="', skinColor, '"/>') ) .toSlice() ) .toSlice(); } else if (hasAttr("Orange Side", attrs)) { slicePunk = slicePunk .concat( string .concat( '<rect x="12" y="23" width="1" height="1" shape-rendering="crispEdges"', string.concat(' fill="', skinColor, '"/>'), '<rect x="13" y="22" width="1" height="1" shape-rendering="crispEdges" fill="#000000ff"/>' ) .toSlice() ) .toSlice(); } else { slicePunk = slicePunk .concat( string .concat( '<rect x="12" y="23" width="1" height="1" shape-rendering="crispEdges"', string.concat(' fill="', skinColor, '"/>'), '<rect x="14" y="20" width="2" height="2" shape-rendering="crispEdges" fill="#000000ff"/><rect x="13" y="21" width="2" height="2" shape-rendering="crispEdges" fill="#000000ff"/>' ) .toSlice() ) .toSlice(); } } else if (hasAttr("Silver Chain", attrs)) { slicePunk = slicePunk .concat( string .concat( '<rect x="12" y="23" width="1" height="1" shape-rendering="crispEdges"', string.concat(' fill="', skinColor, '"/>'), '<rect x="12" y="22" width="3" height="1" shape-rendering="crispEdges" fill="#dfdfdfff"/>' ) .toSlice() ) .toSlice(); } else if (hasAttr("Gold Chain", attrs)) { slicePunk = slicePunk .concat( string .concat( '<rect x="12" y="23" width="1" height="1" shape-rendering="crispEdges"', string.concat(' fill="', skinColor, '"/>'), '<rect x="12" y="22" width="3" height="1" shape-rendering="crispEdges" fill="#ffc926ff"/>' ) .toSlice() ) .toSlice(); } } return string.concat( '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" viewBox="0 0 24 ', (length + 24).toString(), '"><rect width="100%" height="100%" fill="#6a8494"/>', slicePunk.toString(), "</svg>" ); } function colorAtPixel( strings.slice memory _slicePunk, string memory _x, string memory _y ) internal pure returns (string memory) { strings.slice memory rect; strings.slice memory copy = _slicePunk.copy().find(string.concat('<rect x="', _x, '" y="', _y).toSlice()); copy.split('fill="'.toSlice(), rect); return copy.until(copy.copy().find("ff".toSlice()).beyond("ff".toSlice())).toString(); } function hasAttr(string memory _attr, string memory _attrs) internal pure returns (bool) { strings.slice memory foundAttr = _attrs.toSlice().find(_attr.toSlice()); return !foundAttr.empty(); } }
/* * @title String & slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> * * @dev Functionality in this library is largely implemented using an * abstraction called a 'slice'. A slice represents a part of a string - * anything from the entire string to a single character, or even no * characters at all (a 0-length slice). Since a slice only has to specify * an offset and a length, copying and manipulating slices is a lot less * expensive than copying and manipulating the strings they reference. * * To further reduce gas costs, most functions on slice that need to return * a slice modify the original one instead of allocating a new one; for * instance, `s.split(".")` will return the text up to the first '.', * modifying s to only contain the remainder of the string after the '.'. * In situations where you do not want to modify the original slice, you * can make a copy first with `.copy()`, for example: * `s.copy().split(".")`. Try and avoid using this idiom in loops; since * Solidity has no memory management, it will result in allocating many * short-lived slices that are later discarded. * * Functions that return two slices come in two versions: a non-allocating * version that takes the second slice as an argument, modifying it in * place, and an allocating version that allocates and returns the second * slice; see `nextRune` for example. * * Functions that have to copy string data will return strings rather than * slices; these can be cast back to slices for further processing if * required. * * For convenience, some functions are provided with non-modifying * variants that create a new slice and return both; for instance, * `s.splitNew('.')` leaves s unmodified, and returns two values * corresponding to the left and right parts of the string. */ pragma solidity ^0.8.0; 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 = type(uint).max; if (len > 0) { 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) & type(uint128).max == 0) { ret += 16; self = bytes32(uint(self) / 0x100000000000000000000000000000000); } if (uint(self) & type(uint64).max == 0) { ret += 8; self = bytes32(uint(self) / 0x10000000000000000); } if (uint(self) & type(uint32).max == 0) { ret += 4; self = bytes32(uint(self) / 0x100000000); } if (uint(self) & type(uint16).max == 0) { ret += 2; self = bytes32(uint(self) / 0x10000); } if (uint(self) & type(uint8).max == 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 uint mask = type(uint).max; // 0xffff... if(shortest < 32) { mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); } unchecked { uint 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; if (needlelen > 0) { 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; if (needlelen > 0) { 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; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ``` * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ``` * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(uint160(account), 20), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Base64.sol) pragma solidity ^0.8.0; /** * @dev Provides a set of functions to operate with Base64 strings. * * _Available since v4.5._ */ library Base64 { /** * @dev Base64 Encoding/Decoding Table */ string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /** * @dev Converts a `bytes` to its Bytes64 `string` representation. */ function encode(bytes memory data) internal pure returns (string memory) { /** * Inspired by Brecht Devos (Brechtpd) implementation - MIT licence * https://github.com/Brechtpd/base64/blob/e78d9fd951e7b0977ddca77d92dc85183770daf4/base64.sol */ if (data.length == 0) return ""; // Loads the table into memory string memory table = _TABLE; // Encoding takes 3 bytes chunks of binary data from `bytes` data parameter // and split into 4 numbers of 6 bits. // The final Base64 length should be `bytes` data length multiplied by 4/3 rounded up // - `data.length + 2` -> Round up // - `/ 3` -> Number of 3-bytes chunks // - `4 *` -> 4 characters for each chunk string memory result = new string(4 * ((data.length + 2) / 3)); /// @solidity memory-safe-assembly assembly { // Prepare the lookup table (skip the first "length" byte) let tablePtr := add(table, 1) // Prepare result pointer, jump over length let resultPtr := add(result, 32) // Run over the input, 3 bytes at a time for { let dataPtr := data let endPtr := add(data, mload(data)) } lt(dataPtr, endPtr) { } { // Advance 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // To write each character, shift the 3 bytes (18 bits) chunk // 4 times in blocks of 6 bits for each character (18, 12, 6, 0) // and apply logical AND with 0x3F which is the number of // the previous character in the ASCII table prior to the Base64 Table // The result is then added to the table to get the character to write, // and finally write it in the result pointer but with a left shift // of 256 (1 byte) - 8 (1 ASCII char) = 248 bits mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F)))) resultPtr := add(resultPtr, 1) // Advance mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F)))) resultPtr := add(resultPtr, 1) // Advance } // When data `bytes` is not exactly 3 bytes long // it is padded with `=` characters at the end switch mod(mload(data), 3) case 1 { mstore8(sub(resultPtr, 1), 0x3d) mstore8(sub(resultPtr, 2), 0x3d) } case 2 { mstore8(sub(resultPtr, 1), 0x3d) } } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"CONSUMER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"growerPunk","type":"string"},{"internalType":"string","name":"attrs","type":"string"},{"internalType":"uint256","name":"length","type":"uint256"},{"internalType":"uint256","name":"maxLength","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"json","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"punk","type":"string"},{"internalType":"string","name":"attrs","type":"string"},{"internalType":"uint256","name":"length","type":"uint256"}],"name":"svg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50620000276000801b336200002d60201b60201c565b620001a6565b6200003f82826200004360201b60201c565b5050565b6200005582826200013460201b60201c565b6200013057600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550620000d56200019e60201b60201c565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600033905090565b6149ca80620001b66000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80634bc02da6116100665780634bc02da61461016b5780636ce0e3451461018957806391d14854146101b9578063a217fddf146101e9578063d547741f146102075761009e565b806301ffc9a7146100a35780631a06bb31146100d3578063248a9ca3146101035780632f2ff15d1461013357806336568abe1461014f575b600080fd5b6100bd60048036038101906100b8919061286c565b610223565b6040516100ca91906128b4565b60405180910390f35b6100ed60048036038101906100e89190612a4b565b61029d565b6040516100fa9190612b86565b60405180910390f35b61011d60048036038101906101189190612bde565b6105ae565b60405161012a9190612c1a565b60405180910390f35b61014d60048036038101906101489190612c93565b6105cd565b005b61016960048036038101906101649190612c93565b6105ee565b005b610173610671565b6040516101809190612c1a565b60405180910390f35b6101a3600480360381019061019e9190612cd3565b610695565b6040516101b09190612b86565b60405180910390f35b6101d360048036038101906101ce9190612c93565b6115c3565b6040516101e091906128b4565b60405180910390f35b6101f161162d565b6040516101fe9190612c1a565b60405180910390f35b610221600480360381019061021c9190612c93565b611634565b005b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610296575061029582611655565b5b9050919050565b60607f9d56108290ea0bc9c5c59c3ad357dca9d1b29ed7f3ae1443bef2fa2159bdf5e86102c9816116bf565b60006102d4876116d3565b905060006103166040518060400160405280600281526020017f2c200000000000000000000000000000000000000000000000000000000000008152506116d3565b90506000600161032f838561170190919063ffffffff16565b6103399190612d8d565b67ffffffffffffffff811115610352576103516128ea565b5b60405190808252806020026020018201604052801561038557816020015b60608152602001906001900390816103705790505b50905060005b81518110156103e0576103af6103aa84866117a990919063ffffffff16565b6117c3565b8282815181106103c2576103c1612de3565b5b602002602001018190525080806103d890612e12565b91505061038b565b506000816000815181106103f7576103f6612de3565b5b602002602001015160405160200161040f9190612f2f565b60405160208183030381529060405290506000600190505b8251811015610481578183828151811061044457610443612de3565b5b602002602001015160405160200161045d929190612fd2565b6040516020818303038152906040529150808061047990612e12565b915050610427565b508789106104b0578060405160200161049a9190613082565b6040516020818303038152906040529050610562565b60006040518060400160405280600181526020017f4f0000000000000000000000000000000000000000000000000000000000000081525090506000600190505b600a8b6104fe91906130d3565b81101561053b5781604051602001610516919061312a565b60405160208183030381529060405291506002816105349190612d8d565b90506104f1565b828260405160200161054e9291906131e8565b604051602081830303815290604052925050505b61059e61056e8861183f565b826105788e6119a0565b60405160200161058a939291906132e4565b6040516020818303038152906040526119a0565b9550505050505095945050505050565b6000806000838152602001908152602001600020600101549050919050565b6105d6826105ae565b6105df816116bf565b6105e98383611b04565b505050565b6105f6611be4565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a906133b0565b60405180910390fd5b61066d8282611bec565b5050565b7f9d56108290ea0bc9c5c59c3ad357dca9d1b29ed7f3ae1443bef2fa2159bdf5e881565b60607f9d56108290ea0bc9c5c59c3ad357dca9d1b29ed7f3ae1443bef2fa2159bdf5e86106c1816116bf565b60006106cc866116d3565b905061075061070f6040518060400160405280600681526020017f3c2f7376673e00000000000000000000000000000000000000000000000000008152506116d3565b6107426107336040518060a0016040528060628152602001614845606291396116d3565b84611ccd90919063ffffffff16565b611d6790919063ffffffff16565b5060006107926040518060400160405280600681526020017f46656d616c65000000000000000000000000000000000000000000000000000081525087611e02565b159050600061084d83836107db576040518060400160405280600181526020017f3900000000000000000000000000000000000000000000000000000000000000815250610812565b6040518060400160405280600181526020017f37000000000000000000000000000000000000000000000000000000000000008152505b6040518060400160405280600281526020017f3233000000000000000000000000000000000000000000000000000000000000815250611e3d565b90508115610f885760006108cc846040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3500000000000000000000000000000000000000000000000000000000000000815250611e3d565b90506000610945856040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3600000000000000000000000000000000000000000000000000000000000000815250611e3d565b905061096a610953846116d3565b61095c846116d3565b611fae90919063ffffffff16565b156109ad576109aa6109a561099660405180608001604052806057815260200161468e605791396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b6109d06109b9846116d3565b6109c2836116d3565b611fae90919063ffffffff16565b15610a1357610a10610a0b6109fc60405180608001604052806057815260200161493e605791396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b610a526040518060400160405280600981526020017f42696720426561726400000000000000000000000000000000000000000000008152508a611e02565b610a9b57610a98610a93610a8485604051602001610a70919061348e565b6040516020818303038152906040526116d3565b87611fc490919063ffffffff16565b6116d3565b94505b610ada6040518060400160405280600681526020017f486f6f64696500000000000000000000000000000000000000000000000000008152508a611e02565b15610b7157610b6a610b65610b56610afd60058c610af89190612d8d565b61183f565b610b1260058d610b0d9190612d8d565b61183f565b604051602001610b2291906134e5565b604051602081830303815290604052604051602001610b42929190613708565b6040516020818303038152906040526116d3565b87611fc490919063ffffffff16565b6116d3565b9450610f81565b610bfe610bf986610beb610b9060058d610b8b9190612d8d565b61183f565b87610ba660058f610ba19190612d8d565b61183f565b604051602001610bb7929190613799565b604051602081830303815290604052604051602001610bd7929190613940565b6040516020818303038152906040526116d3565b611fc490919063ffffffff16565b6116d3565b9450610c3f6040518060400160405280600a81526020017f476f6c6420436861696e000000000000000000000000000000000000000000008152508a611e02565b15610d1457610c836040518060400160405280600f81526020017f4c75787572696f757320426561726400000000000000000000000000000000008152508a611e02565b158015610ccc5750610cca6040518060400160405280600981526020017f42696720426561726400000000000000000000000000000000000000000000008152508a611e02565b155b15610d0f57610d0c610d07610cf86040518060800160405280605881526020016146e5605891396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b610f80565b610d536040518060400160405280600981526020017f4368696e737472617000000000000000000000000000000000000000000000008152508a611e02565b80610d995750610d986040518060400160405280600b81526020017f46726f6e742042656172640000000000000000000000000000000000000000008152508a611e02565b5b80610ddf5750610dde6040518060400160405280600481526020017f476f6174000000000000000000000000000000000000000000000000000000008152508a611e02565b5b15610eb457610e236040518060400160405280600c81526020017f53696c76657220436861696e00000000000000000000000000000000000000008152508a611e02565b15610e6a57610e63610e5e610e4f6040518060e0016040528060b0815260200161473d60b091396116d3565b87611fc490919063ffffffff16565b6116d3565b9450610eaf565b610eac610ea7610e9885604051602001610e849190613a1d565b6040516020818303038152906040526116d3565b87611fc490919063ffffffff16565b6116d3565b94505b610f7f565b610ef36040518060400160405280600981526020017f42696720426561726400000000000000000000000000000000000000000000008152508a611e02565b158015610f3b5750610f3a6040518060400160405280600c81526020017f53696c76657220436861696e00000000000000000000000000000000000000008152508a611e02565b5b15610f7e57610f7b610f76610f676040518060800160405280605881526020016147ed605891396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b5b5b5b5050611578565b610fc76040518060400160405280600681526020017f4d6f6861776b000000000000000000000000000000000000000000000000000081525088611e02565b61118c576000611042846040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3800000000000000000000000000000000000000000000000000000000000000815250611e3d565b905060006110bb856040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3900000000000000000000000000000000000000000000000000000000000000815250611e3d565b90506110e06110c9846116d3565b6110d2846116d3565b611fae90919063ffffffff16565b156111235761112061111b61110c604051806080016040528060578152602001614637605791396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b61114661112f846116d3565b611138836116d3565b611fae90919063ffffffff16565b15611189576111866111816111726040518060800160405280605781526020016148e7605791396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b50505b611219611214846112066111ab60058b6111a69190612d8d565b61183f565b856111c160058d6111bc9190612d8d565b61183f565b6040516020016111d2929190613799565b6040516020818303038152906040526040516020016111f2929190613b32565b6040516020818303038152906040526116d3565b611fc490919063ffffffff16565b6116d3565b925061125a6040518060400160405280600681526020017f43686f6b6572000000000000000000000000000000000000000000000000000081525088611e02565b156114215761129e6040518060400160405280600d81526020017f537472616967687420486169720000000000000000000000000000000000000081525088611e02565b1561130b576113046112ff6112f0836040516020016112bd9190613b77565b6040516020818303038152906040526040516020016112dc9190613c44565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b925061141c565b61134a6040518060400160405280600b81526020017f4f72616e6765205369646500000000000000000000000000000000000000000081525088611e02565b156113b7576113b06113ab61139c836040516020016113699190613b77565b6040516020818303038152906040526040516020016113889190613cfe565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b925061141b565b611418611413611404836040516020016113d19190613b77565b6040516020818303038152906040526040516020016113f09190613e35565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b92505b5b611577565b6114606040518060400160405280600c81526020017f53696c76657220436861696e000000000000000000000000000000000000000081525088611e02565b156114cd576114c66114c16114b28360405160200161147f9190613b77565b60405160208183030381529060405260405160200161149e9190613efa565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b9250611576565b61150c6040518060400160405280600a81526020017f476f6c6420436861696e0000000000000000000000000000000000000000000081525088611e02565b156115755761157261156d61155e8360405160200161152b9190613b77565b60405160208183030381529060405260405160200161154a9190613fbf565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b92505b5b5b5b61158d6018876115889190612d8d565b61183f565b611596846117c3565b6040516020016115a792919061411c565b6040516020818303038152906040529450505050509392505050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000801b81565b61163d826105ae565b611646816116bf565b6116508383611bec565b505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6116d0816116cb611be4565b612072565b50565b6116db6127e6565b600060208301905060405180604001604052808451815260200182815250915050919050565b6000808260000151611725856000015186602001518660000151876020015161210f565b61172f9190612d8d565b90505b836000015184602001516117469190612d8d565b81116117a257818061175790612e12565b92505082600001516117918560200151836117729190614165565b86600001516117819190614165565b838660000151876020015161210f565b61179b9190612d8d565b9050611732565b5092915050565b6117b16127e6565b6117bc838383612259565b5092915050565b60606000826000015167ffffffffffffffff8111156117e5576117e46128ea565b5b6040519080825280601f01601f1916602001820160405280156118175781602001600182028036833780820191505090505b50905060006020820190506118358185602001518660000151612324565b8192505050919050565b60606000821415611887576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061199b565b600082905060005b600082146118b95780806118a290612e12565b915050600a826118b291906130d3565b915061188f565b60008167ffffffffffffffff8111156118d5576118d46128ea565b5b6040519080825280601f01601f1916602001820160405280156119075781602001600182028036833780820191505090505b5090505b60008514611994576001826119209190614165565b9150600a8561192f9190614199565b603061193b9190612d8d565b60f81b81838151811061195157611950612de3565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561198d91906130d3565b945061190b565b8093505050505b919050565b60606000825114156119c357604051806020016040528060008152509050611aff565b60006040518060600160405280604081526020016148a760409139905060006003600285516119f29190612d8d565b6119fc91906130d3565b6004611a0891906141ca565b67ffffffffffffffff811115611a2157611a206128ea565b5b6040519080825280601f01601f191660200182016040528015611a535781602001600182028036833780820191505090505b509050600182016020820185865187015b80821015611abf576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845360018401935050611a64565b5050600386510660018114611adb5760028114611aee57611af6565b603d6001830353603d6002830353611af6565b603d60018303535b50505080925050505b919050565b611b0e82826115c3565b611be057600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611b85611be4565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b600033905090565b611bf682826115c3565b15611cc957600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611c6e611be4565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b611cd56127e6565b816000015183600001511015611ced57829050611d61565b6000600190508260200151846020015114611d1b578251602085015160208501518281208383201493505050505b8015611d5c57826000015184600001818151611d379190614165565b91508181525050826000015184602001818151611d549190612d8d565b915081815250505b839150505b92915050565b611d6f6127e6565b816000015183600001511015611d8757829050611dfc565b6000826000015184600001518560200151611da29190612d8d565b611dac9190614165565b905060006001905083602001518214611dd2578351602085015181812082852014925050505b8015611df657836000015185600001818151611dee9190614165565b915081815250505b84925050505b92915050565b600080611e28611e11856116d3565b611e1a856116d3565b6123d090919063ffffffff16565b9050611e3381612434565b1591505092915050565b6060611e476127e6565b6000611e8d611e768686604051602001611e62929190614270565b6040516020818303038152906040526116d3565b611e7f88612444565b6123d090919063ffffffff16565b9050611ee1611ed06040518060400160405280600681526020017f66696c6c3d2200000000000000000000000000000000000000000000000000008152506116d3565b83836122599092919063ffffffff16565b50611fa3611f9e611f8f611f296040518060400160405280600281526020017f66660000000000000000000000000000000000000000000000000000000000008152506116d3565b611f81611f6a6040518060400160405280600281526020017f66660000000000000000000000000000000000000000000000000000000000008152506116d3565b611f7387612444565b6123d090919063ffffffff16565b611ccd90919063ffffffff16565b83611d6790919063ffffffff16565b6117c3565b925050509392505050565b600080611fbb8484612470565b14905092915050565b6060600082600001518460000151611fdc9190612d8d565b67ffffffffffffffff811115611ff557611ff46128ea565b5b6040519080825280601f01601f1916602001820160405280156120275781602001600182028036833780820191505090505b50905060006020820190506120458186602001518760000151612324565b6120678560000151826120589190612d8d565b85602001518660000151612324565b819250505092915050565b61207c82826115c3565b61210b576120a18173ffffffffffffffffffffffffffffffffffffffff1660146125aa565b6120af8360001c60206125aa565b6040516020016120c092919061434a565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121029190612b86565b60405180910390fd5b5050565b600080849050600086851161224057602085116121e25760008086111561216857600186602061213f9190614165565b600861214b91906141ca565b600261215791906144b7565b6121619190614165565b1960001b90505b60008186511690506000878a8a61217f9190612d8d565b6121899190614165565b905060008386511690505b8281146121d4578186106121bb578a8a6121ae9190612d8d565b9650505050505050612251565b85806121c690612e12565b965050838651169050612194565b859650505050505050612251565b60008585209050600091505b85886121fa9190614165565b821161223e57600086842090508082141561221b5783945050505050612251565b6001846122289190612d8d565b935050818061223690612e12565b9250506121ee565b505b868661224c9190612d8d565b925050505b949350505050565b6122616127e6565b600061227f856000015186602001518660000151876020015161210f565b9050846020015183602001818152505084602001518161229f9190614165565b836000018181525050846000015185602001516122bc9190612d8d565b8114156122d3576000856000018181525050612319565b836000015183600001516122e79190612d8d565b856000018181516122f89190614165565b9150818152505083600001518161230f9190612d8d565b8560200181815250505b829150509392505050565b5b60208110612363578151835260208361233e9190612d8d565b925060208261234d9190612d8d565b915060208161235c9190614165565b9050612325565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060008211156123ba5760018260206123a09190614165565b6101006123ad91906144b7565b6123b79190614165565b90505b8019835116818551168181178652505050505050565b6123d86127e6565b60006123f6846000015185602001518560000151866020015161210f565b90508360200151816124089190614165565b846000018181516124199190614165565b91508181525050808460200181815250508391505092915050565b6000808260000151149050919050565b61244c6127e6565b60405180604001604052808360000151815260200183602001518152509050919050565b6000808360000151905083600001518360000151101561249257826000015190505b60008460200151905060008460200151905060005b838110156125895760008084519150835190508082146125555760007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9050602087101561252f576001848860206124ff9190614165565b6125099190612d8d565b600861251591906141ca565b600261252191906144b7565b61252b9190614165565b1990505b6000818316828516039050600081146125525780985050505050505050506125a4565b50505b6020856125629190612d8d565b94506020846125719190612d8d565b935050506020816125829190612d8d565b90506124a7565b508460000151866000015161259e919061450c565b93505050505b92915050565b6060600060028360026125bd91906141ca565b6125c79190612d8d565b67ffffffffffffffff8111156125e0576125df6128ea565b5b6040519080825280601f01601f1916602001820160405280156126125781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061264a57612649612de3565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106126ae576126ad612de3565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026126ee91906141ca565b6126f89190612d8d565b90505b6001811115612798577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061273a57612739612de3565b5b1a60f81b82828151811061275157612750612de3565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c945080612791906145a0565b90506126fb565b50600084146127dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d390614616565b60405180910390fd5b8091505092915050565b604051806040016040528060008152602001600081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61284981612814565b811461285457600080fd5b50565b60008135905061286681612840565b92915050565b6000602082840312156128825761288161280a565b5b600061289084828501612857565b91505092915050565b60008115159050919050565b6128ae81612899565b82525050565b60006020820190506128c960008301846128a5565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612922826128d9565b810181811067ffffffffffffffff82111715612941576129406128ea565b5b80604052505050565b6000612954612800565b90506129608282612919565b919050565b600067ffffffffffffffff8211156129805761297f6128ea565b5b612989826128d9565b9050602081019050919050565b82818337600083830152505050565b60006129b86129b384612965565b61294a565b9050828152602081018484840111156129d4576129d36128d4565b5b6129df848285612996565b509392505050565b600082601f8301126129fc576129fb6128cf565b5b8135612a0c8482602086016129a5565b91505092915050565b6000819050919050565b612a2881612a15565b8114612a3357600080fd5b50565b600081359050612a4581612a1f565b92915050565b600080600080600060a08688031215612a6757612a6661280a565b5b600086013567ffffffffffffffff811115612a8557612a8461280f565b5b612a91888289016129e7565b955050602086013567ffffffffffffffff811115612ab257612ab161280f565b5b612abe888289016129e7565b9450506040612acf88828901612a36565b9350506060612ae088828901612a36565b9250506080612af188828901612a36565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b38578082015181840152602081019050612b1d565b83811115612b47576000848401525b50505050565b6000612b5882612afe565b612b628185612b09565b9350612b72818560208601612b1a565b612b7b816128d9565b840191505092915050565b60006020820190508181036000830152612ba08184612b4d565b905092915050565b6000819050919050565b612bbb81612ba8565b8114612bc657600080fd5b50565b600081359050612bd881612bb2565b92915050565b600060208284031215612bf457612bf361280a565b5b6000612c0284828501612bc9565b91505092915050565b612c1481612ba8565b82525050565b6000602082019050612c2f6000830184612c0b565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612c6082612c35565b9050919050565b612c7081612c55565b8114612c7b57600080fd5b50565b600081359050612c8d81612c67565b92915050565b60008060408385031215612caa57612ca961280a565b5b6000612cb885828601612bc9565b9250506020612cc985828601612c7e565b9150509250929050565b600080600060608486031215612cec57612ceb61280a565b5b600084013567ffffffffffffffff811115612d0a57612d0961280f565b5b612d16868287016129e7565b935050602084013567ffffffffffffffff811115612d3757612d3661280f565b5b612d43868287016129e7565b9250506040612d5486828701612a36565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612d9882612a15565b9150612da383612a15565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612dd857612dd7612d5e565b5b828201905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000612e1d82612a15565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612e5057612e4f612d5e565b5b600182019050919050565b600081905092915050565b7f222c2261747472696275746573223a5b7b2274726169745f74797065223a224860008201527f656164222c2276616c7565223a22000000000000000000000000000000000000602082015250565b6000612ec2602e83612e5b565b9150612ecd82612e66565b602e82019050919050565b6000612ee382612afe565b612eed8185612e5b565b9350612efd818560208601612b1a565b80840191505092915050565b7f227d000000000000000000000000000000000000000000000000000000000000815250565b6000612f3a82612eb5565b9150612f468284612ed8565b9150612f5182612f09565b60028201915081905092915050565b7f2c7b2274726169745f74797065223a224665617475726573222c2276616c756560008201527f223a220000000000000000000000000000000000000000000000000000000000602082015250565b6000612fbc602383612e5b565b9150612fc782612f60565b602382019050919050565b6000612fde8285612ed8565b9150612fe982612faf565b9150612ff58284612ed8565b915061300082612f09565b6002820191508190509392505050565b7f2c7b2274726169745f74797065223a2247726f777468222c2276616c7565223a60008201527f2247524f574e227d000000000000000000000000000000000000000000000000602082015250565b600061306c602883612e5b565b915061307782613010565b602882019050919050565b600061308e8284612ed8565b91506130998261305f565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006130de82612a15565b91506130e983612a15565b9250826130f9576130f86130a4565b5b828204905092915050565b7f4f00000000000000000000000000000000000000000000000000000000000000815250565b60006131368284612ed8565b915061314182613104565b60018201915081905092915050565b7f2c7b2274726169745f74797065223a2247726f777468222c2276616c7565223a60008201527f2247520000000000000000000000000000000000000000000000000000000000602082015250565b60006131ac602383612e5b565b91506131b782613150565b602382019050919050565b7f57494e47227d0000000000000000000000000000000000000000000000000000815250565b60006131f48285612ed8565b91506131ff8261319f565b915061320b8284612ed8565b9150613216826131c2565b6006820191508190509392505050565b7f7b226e616d65223a2247726f77657250756e6b20230000000000000000000000815250565b7f5d2c226465736372697074696f6e223a2247726f77657250756e6b73222c226960008201527f6d616765223a22646174613a696d6167652f7376672b786d6c3b62617365363460208201527f2c00000000000000000000000000000000000000000000000000000000000000604082015250565b60006132ce604183612e5b565b91506132d98261324c565b604182019050919050565b60006132ef82613226565b6015820191506132ff8286612ed8565b915061330b8285612ed8565b9150613316826132c1565b91506133228284612ed8565b915061332d82612f09565b600282019150819050949350505050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b600061339a602f83612b09565b91506133a58261333e565b604082019050919050565b600060208201905081810360008301526133c98161338d565b9050919050565b7f3c7265637420783d2231302220793d223233222077696474683d22312220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d220000000000000000000000000000000000000000604082015250565b6000613452604c83612e5b565b915061345d826133d0565b604c82019050919050565b7f222f3e0000000000000000000000000000000000000000000000000000000000815250565b600061349982613445565b91506134a58284612ed8565b91506134b082613468565b60038201915081905092915050565b7f206865696768743d220000000000000000000000000000000000000000000000815250565b60006134f0826134bf565b6009820191506135008284612ed8565b915061350b82613468565b60038201915081905092915050565b7f3c7265637420783d22342220793d223234222077696474683d2231322220686560008201527f696768743d220000000000000000000000000000000000000000000000000000602082015250565b6000613576602683612e5b565b91506135818261351a565b602682019050919050565b7f222073686170652d72656e646572696e673d226372697370456467657322206660008201527f696c6c3d22233030303030306666222f3e3c7265637420783d22372220793d2260208201527f3234222077696474683d223422206865696768743d2231222073686170652d7260408201527f656e646572696e673d2263726973704564676573222066696c6c3d222330303060608201527f3030306666222f3e000000000000000000000000000000000000000000000000608082015250565b600061365a608883612e5b565b91506136658261358c565b608882019050919050565b7f3c7265637420783d22352220793d223234222077696474683d2238222073686160008201527f70652d72656e646572696e673d2263726973704564676573222066696c6c3d2260208201527f2335353535353566662200000000000000000000000000000000000000000000604082015250565b60006136f2604a83612e5b565b91506136fd82613670565b604a82019050919050565b600061371382613569565b915061371f8285612ed8565b915061372a8261364d565b9150613735826136e5565b91506137418284612ed8565b91508190509392505050565b7f2066696c6c3d2200000000000000000000000000000000000000000000000000815250565b7f22206865696768743d2200000000000000000000000000000000000000000000815250565b60006137a48261374d565b6007820191506137b48285612ed8565b91506137bf82613773565b600a820191506137cf8284612ed8565b91506137da82613468565b6003820191508190509392505050565b7f3c7265637420783d22362220793d223139222077696474683d2231302220686560008201527f696768743d220000000000000000000000000000000000000000000000000000602082015250565b6000613846602683612e5b565b9150613851826137ea565b602682019050919050565b7f222073686170652d72656e646572696e673d226372697370456467657322206660008201527f696c6c3d22233030303030306666222f3e000000000000000000000000000000602082015250565b60006138b8603183612e5b565b91506138c38261385c565b603182019050919050565b7f3c7265637420783d22372220793d223139222077696474683d2238222073686160008201527f70652d72656e646572696e673d22637269737045646765732200000000000000602082015250565b600061392a603983612e5b565b9150613935826138ce565b603982019050919050565b600061394b82613839565b91506139578285612ed8565b9150613962826138ab565b915061396d8261391d565b91506139798284612ed8565b91508190509392505050565b7f3c7265637420783d2231302220793d223232222077696474683d22312220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d220000000000000000000000000000000000000000604082015250565b6000613a07604c83612e5b565b9150613a1282613985565b604c82019050919050565b6000613a28826139fa565b9150613a348284612ed8565b9150613a3f82613468565b60038201915081905092915050565b7f3c7265637420783d22382220793d223139222077696474683d2238222068656960008201527f6768743d22000000000000000000000000000000000000000000000000000000602082015250565b6000613aaa602583612e5b565b9150613ab582613a4e565b602582019050919050565b7f3c7265637420783d22392220793d223139222077696474683d2236222073686160008201527f70652d72656e646572696e673d22637269737045646765732200000000000000602082015250565b6000613b1c603983612e5b565b9150613b2782613ac0565b603982019050919050565b6000613b3d82613a9d565b9150613b498285612ed8565b9150613b54826138ab565b9150613b5f82613b0f565b9150613b6b8284612ed8565b91508190509392505050565b6000613b828261374d565b600782019150613b928284612ed8565b9150613b9d82613468565b60038201915081905092915050565b7f3c7265637420783d2231322220793d223233222077696474683d22312220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f6467657322000000000000000000000000000000000000000000000000000000604082015250565b6000613c2e604583612e5b565b9150613c3982613bac565b604582019050919050565b6000613c4f82613c21565b9150613c5b8284612ed8565b915081905092915050565b7f3c7265637420783d2231332220793d223232222077696474683d22312220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d22233030303030306666222f3e0000000000000000604082015250565b6000613ce8605883612e5b565b9150613cf382613c66565b605882019050919050565b6000613d0982613c21565b9150613d158284612ed8565b9150613d2082613cdb565b915081905092915050565b7f3c7265637420783d2231342220793d223230222077696474683d22322220686560008201527f696768743d2232222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d22233030303030306666222f3e3c7265637420783d60408201527f2231332220793d223231222077696474683d223222206865696768743d22322260608201527f2073686170652d72656e646572696e673d22637269737045646765732220666960808201527f6c6c3d22233030303030306666222f3e0000000000000000000000000000000060a082015250565b6000613e1f60b083612e5b565b9150613e2a82613d2b565b60b082019050919050565b6000613e4082613c21565b9150613e4c8284612ed8565b9150613e5782613e12565b915081905092915050565b7f3c7265637420783d2231322220793d223232222077696474683d22332220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d22236466646664666666222f3e0000000000000000604082015250565b6000613ee4605883612e5b565b9150613eef82613e62565b605882019050919050565b6000613f0582613c21565b9150613f118284612ed8565b9150613f1c82613ed7565b915081905092915050565b7f3c7265637420783d2231322220793d223232222077696474683d22332220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d22236666633932366666222f3e0000000000000000604082015250565b6000613fa9605883612e5b565b9150613fb482613f27565b605882019050919050565b6000613fca82613c21565b9150613fd68284612ed8565b9150613fe182613f9c565b915081905092915050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323060008201527f30302f737667222076657273696f6e3d22312e32222076696577426f783d223060208201527f2030203234200000000000000000000000000000000000000000000000000000604082015250565b600061406e604683612e5b565b915061407982613fec565b604682019050919050565b7f223e3c726563742077696474683d223130302522206865696768743d2231303060008201527f25222066696c6c3d2223366138343934222f3e00000000000000000000000000602082015250565b60006140e0603383612e5b565b91506140eb82614084565b603382019050919050565b7f3c2f7376673e0000000000000000000000000000000000000000000000000000815250565b600061412782614061565b91506141338285612ed8565b915061413e826140d3565b915061414a8284612ed8565b9150614155826140f6565b6006820191508190509392505050565b600061417082612a15565b915061417b83612a15565b92508282101561418e5761418d612d5e565b5b828203905092915050565b60006141a482612a15565b91506141af83612a15565b9250826141bf576141be6130a4565b5b828206905092915050565b60006141d582612a15565b91506141e083612a15565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561421957614218612d5e565b5b828202905092915050565b7f3c7265637420783d220000000000000000000000000000000000000000000000815250565b7f2220793d22000000000000000000000000000000000000000000000000000000815250565b600061427b82614224565b60098201915061428b8285612ed8565b91506142968261424a565b6005820191506142a68284612ed8565b91508190509392505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006142e8601783612e5b565b91506142f3826142b2565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b6000614334601183612e5b565b915061433f826142fe565b601182019050919050565b6000614355826142db565b91506143618285612ed8565b915061436c82614327565b91506143788284612ed8565b91508190509392505050565b60008160011c9050919050565b6000808291508390505b60018511156143db578086048111156143b7576143b6612d5e565b5b60018516156143c65780820291505b80810290506143d485614384565b945061439b565b94509492505050565b6000826143f457600190506144b0565b8161440257600090506144b0565b8160018114614418576002811461442257614451565b60019150506144b0565b60ff84111561443457614433612d5e565b5b8360020a91508482111561444b5761444a612d5e565b5b506144b0565b5060208310610133831016604e8410600b84101617156144865782820a90508381111561448157614480612d5e565b5b6144b0565b6144938484846001614391565b925090508184048111156144aa576144a9612d5e565b5b81810290505b9392505050565b60006144c282612a15565b91506144cd83612a15565b92506144fa7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846143e4565b905092915050565b6000819050919050565b600061451782614502565b915061452283614502565b9250827f80000000000000000000000000000000000000000000000000000000000000000182126000841215161561455d5761455c612d5e565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01821360008412161561459557614594612d5e565b5b828203905092915050565b60006145ab82612a15565b915060008214156145bf576145be612d5e565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b6000614600602083612b09565b915061460b826145ca565b602082019050919050565b6000602082019050818103600083015261462f816145f3565b905091905056fe3c7265637420783d2231322220793d2238222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22233030303030306666222f3e3c7265637420783d2231322220793d2235222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22233030303030306666222f3e3c7265637420783d2231302220793d223232222077696474683d223522206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22236666633932366666222f3e3c7265637420783d2231302220793d223232222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22236466646664666666222f3e3c7265637420783d2231342220793d223232222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22236466646664666666222f3e3c7265637420783d2231302220793d223232222077696474683d223522206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22236466646664666666222f3e646174613a696d6167652f7376672b786d6c3b757466382c3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737667222076657273696f6e3d22312e32222076696577426f783d22302030203234203234223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f3c7265637420783d2231322220793d2239222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22233030303030306666222f3e3c7265637420783d2231322220793d2236222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22233030303030306666222f3ea2646970667358221220eec8e09d6a03713fdc8de5eb89475572ca7c5c7313c60af5379d64cb9237d50f64736f6c634300080c0033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061009e5760003560e01c80634bc02da6116100665780634bc02da61461016b5780636ce0e3451461018957806391d14854146101b9578063a217fddf146101e9578063d547741f146102075761009e565b806301ffc9a7146100a35780631a06bb31146100d3578063248a9ca3146101035780632f2ff15d1461013357806336568abe1461014f575b600080fd5b6100bd60048036038101906100b8919061286c565b610223565b6040516100ca91906128b4565b60405180910390f35b6100ed60048036038101906100e89190612a4b565b61029d565b6040516100fa9190612b86565b60405180910390f35b61011d60048036038101906101189190612bde565b6105ae565b60405161012a9190612c1a565b60405180910390f35b61014d60048036038101906101489190612c93565b6105cd565b005b61016960048036038101906101649190612c93565b6105ee565b005b610173610671565b6040516101809190612c1a565b60405180910390f35b6101a3600480360381019061019e9190612cd3565b610695565b6040516101b09190612b86565b60405180910390f35b6101d360048036038101906101ce9190612c93565b6115c3565b6040516101e091906128b4565b60405180910390f35b6101f161162d565b6040516101fe9190612c1a565b60405180910390f35b610221600480360381019061021c9190612c93565b611634565b005b60007f7965db0b000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480610296575061029582611655565b5b9050919050565b60607f9d56108290ea0bc9c5c59c3ad357dca9d1b29ed7f3ae1443bef2fa2159bdf5e86102c9816116bf565b60006102d4876116d3565b905060006103166040518060400160405280600281526020017f2c200000000000000000000000000000000000000000000000000000000000008152506116d3565b90506000600161032f838561170190919063ffffffff16565b6103399190612d8d565b67ffffffffffffffff811115610352576103516128ea565b5b60405190808252806020026020018201604052801561038557816020015b60608152602001906001900390816103705790505b50905060005b81518110156103e0576103af6103aa84866117a990919063ffffffff16565b6117c3565b8282815181106103c2576103c1612de3565b5b602002602001018190525080806103d890612e12565b91505061038b565b506000816000815181106103f7576103f6612de3565b5b602002602001015160405160200161040f9190612f2f565b60405160208183030381529060405290506000600190505b8251811015610481578183828151811061044457610443612de3565b5b602002602001015160405160200161045d929190612fd2565b6040516020818303038152906040529150808061047990612e12565b915050610427565b508789106104b0578060405160200161049a9190613082565b6040516020818303038152906040529050610562565b60006040518060400160405280600181526020017f4f0000000000000000000000000000000000000000000000000000000000000081525090506000600190505b600a8b6104fe91906130d3565b81101561053b5781604051602001610516919061312a565b60405160208183030381529060405291506002816105349190612d8d565b90506104f1565b828260405160200161054e9291906131e8565b604051602081830303815290604052925050505b61059e61056e8861183f565b826105788e6119a0565b60405160200161058a939291906132e4565b6040516020818303038152906040526119a0565b9550505050505095945050505050565b6000806000838152602001908152602001600020600101549050919050565b6105d6826105ae565b6105df816116bf565b6105e98383611b04565b505050565b6105f6611be4565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a906133b0565b60405180910390fd5b61066d8282611bec565b5050565b7f9d56108290ea0bc9c5c59c3ad357dca9d1b29ed7f3ae1443bef2fa2159bdf5e881565b60607f9d56108290ea0bc9c5c59c3ad357dca9d1b29ed7f3ae1443bef2fa2159bdf5e86106c1816116bf565b60006106cc866116d3565b905061075061070f6040518060400160405280600681526020017f3c2f7376673e00000000000000000000000000000000000000000000000000008152506116d3565b6107426107336040518060a0016040528060628152602001614845606291396116d3565b84611ccd90919063ffffffff16565b611d6790919063ffffffff16565b5060006107926040518060400160405280600681526020017f46656d616c65000000000000000000000000000000000000000000000000000081525087611e02565b159050600061084d83836107db576040518060400160405280600181526020017f3900000000000000000000000000000000000000000000000000000000000000815250610812565b6040518060400160405280600181526020017f37000000000000000000000000000000000000000000000000000000000000008152505b6040518060400160405280600281526020017f3233000000000000000000000000000000000000000000000000000000000000815250611e3d565b90508115610f885760006108cc846040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3500000000000000000000000000000000000000000000000000000000000000815250611e3d565b90506000610945856040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3600000000000000000000000000000000000000000000000000000000000000815250611e3d565b905061096a610953846116d3565b61095c846116d3565b611fae90919063ffffffff16565b156109ad576109aa6109a561099660405180608001604052806057815260200161468e605791396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b6109d06109b9846116d3565b6109c2836116d3565b611fae90919063ffffffff16565b15610a1357610a10610a0b6109fc60405180608001604052806057815260200161493e605791396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b610a526040518060400160405280600981526020017f42696720426561726400000000000000000000000000000000000000000000008152508a611e02565b610a9b57610a98610a93610a8485604051602001610a70919061348e565b6040516020818303038152906040526116d3565b87611fc490919063ffffffff16565b6116d3565b94505b610ada6040518060400160405280600681526020017f486f6f64696500000000000000000000000000000000000000000000000000008152508a611e02565b15610b7157610b6a610b65610b56610afd60058c610af89190612d8d565b61183f565b610b1260058d610b0d9190612d8d565b61183f565b604051602001610b2291906134e5565b604051602081830303815290604052604051602001610b42929190613708565b6040516020818303038152906040526116d3565b87611fc490919063ffffffff16565b6116d3565b9450610f81565b610bfe610bf986610beb610b9060058d610b8b9190612d8d565b61183f565b87610ba660058f610ba19190612d8d565b61183f565b604051602001610bb7929190613799565b604051602081830303815290604052604051602001610bd7929190613940565b6040516020818303038152906040526116d3565b611fc490919063ffffffff16565b6116d3565b9450610c3f6040518060400160405280600a81526020017f476f6c6420436861696e000000000000000000000000000000000000000000008152508a611e02565b15610d1457610c836040518060400160405280600f81526020017f4c75787572696f757320426561726400000000000000000000000000000000008152508a611e02565b158015610ccc5750610cca6040518060400160405280600981526020017f42696720426561726400000000000000000000000000000000000000000000008152508a611e02565b155b15610d0f57610d0c610d07610cf86040518060800160405280605881526020016146e5605891396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b610f80565b610d536040518060400160405280600981526020017f4368696e737472617000000000000000000000000000000000000000000000008152508a611e02565b80610d995750610d986040518060400160405280600b81526020017f46726f6e742042656172640000000000000000000000000000000000000000008152508a611e02565b5b80610ddf5750610dde6040518060400160405280600481526020017f476f6174000000000000000000000000000000000000000000000000000000008152508a611e02565b5b15610eb457610e236040518060400160405280600c81526020017f53696c76657220436861696e00000000000000000000000000000000000000008152508a611e02565b15610e6a57610e63610e5e610e4f6040518060e0016040528060b0815260200161473d60b091396116d3565b87611fc490919063ffffffff16565b6116d3565b9450610eaf565b610eac610ea7610e9885604051602001610e849190613a1d565b6040516020818303038152906040526116d3565b87611fc490919063ffffffff16565b6116d3565b94505b610f7f565b610ef36040518060400160405280600981526020017f42696720426561726400000000000000000000000000000000000000000000008152508a611e02565b158015610f3b5750610f3a6040518060400160405280600c81526020017f53696c76657220436861696e00000000000000000000000000000000000000008152508a611e02565b5b15610f7e57610f7b610f76610f676040518060800160405280605881526020016147ed605891396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b5b5b5b5050611578565b610fc76040518060400160405280600681526020017f4d6f6861776b000000000000000000000000000000000000000000000000000081525088611e02565b61118c576000611042846040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3800000000000000000000000000000000000000000000000000000000000000815250611e3d565b905060006110bb856040518060400160405280600281526020017f31320000000000000000000000000000000000000000000000000000000000008152506040518060400160405280600181526020017f3900000000000000000000000000000000000000000000000000000000000000815250611e3d565b90506110e06110c9846116d3565b6110d2846116d3565b611fae90919063ffffffff16565b156111235761112061111b61110c604051806080016040528060578152602001614637605791396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b61114661112f846116d3565b611138836116d3565b611fae90919063ffffffff16565b15611189576111866111816111726040518060800160405280605781526020016148e7605791396116d3565b87611fc490919063ffffffff16565b6116d3565b94505b50505b611219611214846112066111ab60058b6111a69190612d8d565b61183f565b856111c160058d6111bc9190612d8d565b61183f565b6040516020016111d2929190613799565b6040516020818303038152906040526040516020016111f2929190613b32565b6040516020818303038152906040526116d3565b611fc490919063ffffffff16565b6116d3565b925061125a6040518060400160405280600681526020017f43686f6b6572000000000000000000000000000000000000000000000000000081525088611e02565b156114215761129e6040518060400160405280600d81526020017f537472616967687420486169720000000000000000000000000000000000000081525088611e02565b1561130b576113046112ff6112f0836040516020016112bd9190613b77565b6040516020818303038152906040526040516020016112dc9190613c44565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b925061141c565b61134a6040518060400160405280600b81526020017f4f72616e6765205369646500000000000000000000000000000000000000000081525088611e02565b156113b7576113b06113ab61139c836040516020016113699190613b77565b6040516020818303038152906040526040516020016113889190613cfe565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b925061141b565b611418611413611404836040516020016113d19190613b77565b6040516020818303038152906040526040516020016113f09190613e35565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b92505b5b611577565b6114606040518060400160405280600c81526020017f53696c76657220436861696e000000000000000000000000000000000000000081525088611e02565b156114cd576114c66114c16114b28360405160200161147f9190613b77565b60405160208183030381529060405260405160200161149e9190613efa565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b9250611576565b61150c6040518060400160405280600a81526020017f476f6c6420436861696e0000000000000000000000000000000000000000000081525088611e02565b156115755761157261156d61155e8360405160200161152b9190613b77565b60405160208183030381529060405260405160200161154a9190613fbf565b6040516020818303038152906040526116d3565b85611fc490919063ffffffff16565b6116d3565b92505b5b5b5b61158d6018876115889190612d8d565b61183f565b611596846117c3565b6040516020016115a792919061411c565b6040516020818303038152906040529450505050509392505050565b600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000801b81565b61163d826105ae565b611646816116bf565b6116508383611bec565b505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b6116d0816116cb611be4565b612072565b50565b6116db6127e6565b600060208301905060405180604001604052808451815260200182815250915050919050565b6000808260000151611725856000015186602001518660000151876020015161210f565b61172f9190612d8d565b90505b836000015184602001516117469190612d8d565b81116117a257818061175790612e12565b92505082600001516117918560200151836117729190614165565b86600001516117819190614165565b838660000151876020015161210f565b61179b9190612d8d565b9050611732565b5092915050565b6117b16127e6565b6117bc838383612259565b5092915050565b60606000826000015167ffffffffffffffff8111156117e5576117e46128ea565b5b6040519080825280601f01601f1916602001820160405280156118175781602001600182028036833780820191505090505b50905060006020820190506118358185602001518660000151612324565b8192505050919050565b60606000821415611887576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061199b565b600082905060005b600082146118b95780806118a290612e12565b915050600a826118b291906130d3565b915061188f565b60008167ffffffffffffffff8111156118d5576118d46128ea565b5b6040519080825280601f01601f1916602001820160405280156119075781602001600182028036833780820191505090505b5090505b60008514611994576001826119209190614165565b9150600a8561192f9190614199565b603061193b9190612d8d565b60f81b81838151811061195157611950612de3565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8561198d91906130d3565b945061190b565b8093505050505b919050565b60606000825114156119c357604051806020016040528060008152509050611aff565b60006040518060600160405280604081526020016148a760409139905060006003600285516119f29190612d8d565b6119fc91906130d3565b6004611a0891906141ca565b67ffffffffffffffff811115611a2157611a206128ea565b5b6040519080825280601f01601f191660200182016040528015611a535781602001600182028036833780820191505090505b509050600182016020820185865187015b80821015611abf576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f8116850151845360018401935050611a64565b5050600386510660018114611adb5760028114611aee57611af6565b603d6001830353603d6002830353611af6565b603d60018303535b50505080925050505b919050565b611b0e82826115c3565b611be057600160008084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611b85611be4565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b600033905090565b611bf682826115c3565b15611cc957600080600084815260200190815260200160002060000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550611c6e611be4565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45b5050565b611cd56127e6565b816000015183600001511015611ced57829050611d61565b6000600190508260200151846020015114611d1b578251602085015160208501518281208383201493505050505b8015611d5c57826000015184600001818151611d379190614165565b91508181525050826000015184602001818151611d549190612d8d565b915081815250505b839150505b92915050565b611d6f6127e6565b816000015183600001511015611d8757829050611dfc565b6000826000015184600001518560200151611da29190612d8d565b611dac9190614165565b905060006001905083602001518214611dd2578351602085015181812082852014925050505b8015611df657836000015185600001818151611dee9190614165565b915081815250505b84925050505b92915050565b600080611e28611e11856116d3565b611e1a856116d3565b6123d090919063ffffffff16565b9050611e3381612434565b1591505092915050565b6060611e476127e6565b6000611e8d611e768686604051602001611e62929190614270565b6040516020818303038152906040526116d3565b611e7f88612444565b6123d090919063ffffffff16565b9050611ee1611ed06040518060400160405280600681526020017f66696c6c3d2200000000000000000000000000000000000000000000000000008152506116d3565b83836122599092919063ffffffff16565b50611fa3611f9e611f8f611f296040518060400160405280600281526020017f66660000000000000000000000000000000000000000000000000000000000008152506116d3565b611f81611f6a6040518060400160405280600281526020017f66660000000000000000000000000000000000000000000000000000000000008152506116d3565b611f7387612444565b6123d090919063ffffffff16565b611ccd90919063ffffffff16565b83611d6790919063ffffffff16565b6117c3565b925050509392505050565b600080611fbb8484612470565b14905092915050565b6060600082600001518460000151611fdc9190612d8d565b67ffffffffffffffff811115611ff557611ff46128ea565b5b6040519080825280601f01601f1916602001820160405280156120275781602001600182028036833780820191505090505b50905060006020820190506120458186602001518760000151612324565b6120678560000151826120589190612d8d565b85602001518660000151612324565b819250505092915050565b61207c82826115c3565b61210b576120a18173ffffffffffffffffffffffffffffffffffffffff1660146125aa565b6120af8360001c60206125aa565b6040516020016120c092919061434a565b6040516020818303038152906040526040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121029190612b86565b60405180910390fd5b5050565b600080849050600086851161224057602085116121e25760008086111561216857600186602061213f9190614165565b600861214b91906141ca565b600261215791906144b7565b6121619190614165565b1960001b90505b60008186511690506000878a8a61217f9190612d8d565b6121899190614165565b905060008386511690505b8281146121d4578186106121bb578a8a6121ae9190612d8d565b9650505050505050612251565b85806121c690612e12565b965050838651169050612194565b859650505050505050612251565b60008585209050600091505b85886121fa9190614165565b821161223e57600086842090508082141561221b5783945050505050612251565b6001846122289190612d8d565b935050818061223690612e12565b9250506121ee565b505b868661224c9190612d8d565b925050505b949350505050565b6122616127e6565b600061227f856000015186602001518660000151876020015161210f565b9050846020015183602001818152505084602001518161229f9190614165565b836000018181525050846000015185602001516122bc9190612d8d565b8114156122d3576000856000018181525050612319565b836000015183600001516122e79190612d8d565b856000018181516122f89190614165565b9150818152505083600001518161230f9190612d8d565b8560200181815250505b829150509392505050565b5b60208110612363578151835260208361233e9190612d8d565b925060208261234d9190612d8d565b915060208161235c9190614165565b9050612325565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905060008211156123ba5760018260206123a09190614165565b6101006123ad91906144b7565b6123b79190614165565b90505b8019835116818551168181178652505050505050565b6123d86127e6565b60006123f6846000015185602001518560000151866020015161210f565b90508360200151816124089190614165565b846000018181516124199190614165565b91508181525050808460200181815250508391505092915050565b6000808260000151149050919050565b61244c6127e6565b60405180604001604052808360000151815260200183602001518152509050919050565b6000808360000151905083600001518360000151101561249257826000015190505b60008460200151905060008460200151905060005b838110156125895760008084519150835190508082146125555760007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9050602087101561252f576001848860206124ff9190614165565b6125099190612d8d565b600861251591906141ca565b600261252191906144b7565b61252b9190614165565b1990505b6000818316828516039050600081146125525780985050505050505050506125a4565b50505b6020856125629190612d8d565b94506020846125719190612d8d565b935050506020816125829190612d8d565b90506124a7565b508460000151866000015161259e919061450c565b93505050505b92915050565b6060600060028360026125bd91906141ca565b6125c79190612d8d565b67ffffffffffffffff8111156125e0576125df6128ea565b5b6040519080825280601f01601f1916602001820160405280156126125781602001600182028036833780820191505090505b5090507f30000000000000000000000000000000000000000000000000000000000000008160008151811061264a57612649612de3565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106126ae576126ad612de3565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600060018460026126ee91906141ca565b6126f89190612d8d565b90505b6001811115612798577f3031323334353637383961626364656600000000000000000000000000000000600f86166010811061273a57612739612de3565b5b1a60f81b82828151811061275157612750612de3565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600485901c945080612791906145a0565b90506126fb565b50600084146127dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d390614616565b60405180910390fd5b8091505092915050565b604051806040016040528060008152602001600081525090565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b61284981612814565b811461285457600080fd5b50565b60008135905061286681612840565b92915050565b6000602082840312156128825761288161280a565b5b600061289084828501612857565b91505092915050565b60008115159050919050565b6128ae81612899565b82525050565b60006020820190506128c960008301846128a5565b92915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b612922826128d9565b810181811067ffffffffffffffff82111715612941576129406128ea565b5b80604052505050565b6000612954612800565b90506129608282612919565b919050565b600067ffffffffffffffff8211156129805761297f6128ea565b5b612989826128d9565b9050602081019050919050565b82818337600083830152505050565b60006129b86129b384612965565b61294a565b9050828152602081018484840111156129d4576129d36128d4565b5b6129df848285612996565b509392505050565b600082601f8301126129fc576129fb6128cf565b5b8135612a0c8482602086016129a5565b91505092915050565b6000819050919050565b612a2881612a15565b8114612a3357600080fd5b50565b600081359050612a4581612a1f565b92915050565b600080600080600060a08688031215612a6757612a6661280a565b5b600086013567ffffffffffffffff811115612a8557612a8461280f565b5b612a91888289016129e7565b955050602086013567ffffffffffffffff811115612ab257612ab161280f565b5b612abe888289016129e7565b9450506040612acf88828901612a36565b9350506060612ae088828901612a36565b9250506080612af188828901612a36565b9150509295509295909350565b600081519050919050565b600082825260208201905092915050565b60005b83811015612b38578082015181840152602081019050612b1d565b83811115612b47576000848401525b50505050565b6000612b5882612afe565b612b628185612b09565b9350612b72818560208601612b1a565b612b7b816128d9565b840191505092915050565b60006020820190508181036000830152612ba08184612b4d565b905092915050565b6000819050919050565b612bbb81612ba8565b8114612bc657600080fd5b50565b600081359050612bd881612bb2565b92915050565b600060208284031215612bf457612bf361280a565b5b6000612c0284828501612bc9565b91505092915050565b612c1481612ba8565b82525050565b6000602082019050612c2f6000830184612c0b565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612c6082612c35565b9050919050565b612c7081612c55565b8114612c7b57600080fd5b50565b600081359050612c8d81612c67565b92915050565b60008060408385031215612caa57612ca961280a565b5b6000612cb885828601612bc9565b9250506020612cc985828601612c7e565b9150509250929050565b600080600060608486031215612cec57612ceb61280a565b5b600084013567ffffffffffffffff811115612d0a57612d0961280f565b5b612d16868287016129e7565b935050602084013567ffffffffffffffff811115612d3757612d3661280f565b5b612d43868287016129e7565b9250506040612d5486828701612a36565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000612d9882612a15565b9150612da383612a15565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612dd857612dd7612d5e565b5b828201905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000612e1d82612a15565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612e5057612e4f612d5e565b5b600182019050919050565b600081905092915050565b7f222c2261747472696275746573223a5b7b2274726169745f74797065223a224860008201527f656164222c2276616c7565223a22000000000000000000000000000000000000602082015250565b6000612ec2602e83612e5b565b9150612ecd82612e66565b602e82019050919050565b6000612ee382612afe565b612eed8185612e5b565b9350612efd818560208601612b1a565b80840191505092915050565b7f227d000000000000000000000000000000000000000000000000000000000000815250565b6000612f3a82612eb5565b9150612f468284612ed8565b9150612f5182612f09565b60028201915081905092915050565b7f2c7b2274726169745f74797065223a224665617475726573222c2276616c756560008201527f223a220000000000000000000000000000000000000000000000000000000000602082015250565b6000612fbc602383612e5b565b9150612fc782612f60565b602382019050919050565b6000612fde8285612ed8565b9150612fe982612faf565b9150612ff58284612ed8565b915061300082612f09565b6002820191508190509392505050565b7f2c7b2274726169745f74797065223a2247726f777468222c2276616c7565223a60008201527f2247524f574e227d000000000000000000000000000000000000000000000000602082015250565b600061306c602883612e5b565b915061307782613010565b602882019050919050565b600061308e8284612ed8565b91506130998261305f565b915081905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006130de82612a15565b91506130e983612a15565b9250826130f9576130f86130a4565b5b828204905092915050565b7f4f00000000000000000000000000000000000000000000000000000000000000815250565b60006131368284612ed8565b915061314182613104565b60018201915081905092915050565b7f2c7b2274726169745f74797065223a2247726f777468222c2276616c7565223a60008201527f2247520000000000000000000000000000000000000000000000000000000000602082015250565b60006131ac602383612e5b565b91506131b782613150565b602382019050919050565b7f57494e47227d0000000000000000000000000000000000000000000000000000815250565b60006131f48285612ed8565b91506131ff8261319f565b915061320b8284612ed8565b9150613216826131c2565b6006820191508190509392505050565b7f7b226e616d65223a2247726f77657250756e6b20230000000000000000000000815250565b7f5d2c226465736372697074696f6e223a2247726f77657250756e6b73222c226960008201527f6d616765223a22646174613a696d6167652f7376672b786d6c3b62617365363460208201527f2c00000000000000000000000000000000000000000000000000000000000000604082015250565b60006132ce604183612e5b565b91506132d98261324c565b604182019050919050565b60006132ef82613226565b6015820191506132ff8286612ed8565b915061330b8285612ed8565b9150613316826132c1565b91506133228284612ed8565b915061332d82612f09565b600282019150819050949350505050565b7f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560008201527f20726f6c657320666f722073656c660000000000000000000000000000000000602082015250565b600061339a602f83612b09565b91506133a58261333e565b604082019050919050565b600060208201905081810360008301526133c98161338d565b9050919050565b7f3c7265637420783d2231302220793d223233222077696474683d22312220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d220000000000000000000000000000000000000000604082015250565b6000613452604c83612e5b565b915061345d826133d0565b604c82019050919050565b7f222f3e0000000000000000000000000000000000000000000000000000000000815250565b600061349982613445565b91506134a58284612ed8565b91506134b082613468565b60038201915081905092915050565b7f206865696768743d220000000000000000000000000000000000000000000000815250565b60006134f0826134bf565b6009820191506135008284612ed8565b915061350b82613468565b60038201915081905092915050565b7f3c7265637420783d22342220793d223234222077696474683d2231322220686560008201527f696768743d220000000000000000000000000000000000000000000000000000602082015250565b6000613576602683612e5b565b91506135818261351a565b602682019050919050565b7f222073686170652d72656e646572696e673d226372697370456467657322206660008201527f696c6c3d22233030303030306666222f3e3c7265637420783d22372220793d2260208201527f3234222077696474683d223422206865696768743d2231222073686170652d7260408201527f656e646572696e673d2263726973704564676573222066696c6c3d222330303060608201527f3030306666222f3e000000000000000000000000000000000000000000000000608082015250565b600061365a608883612e5b565b91506136658261358c565b608882019050919050565b7f3c7265637420783d22352220793d223234222077696474683d2238222073686160008201527f70652d72656e646572696e673d2263726973704564676573222066696c6c3d2260208201527f2335353535353566662200000000000000000000000000000000000000000000604082015250565b60006136f2604a83612e5b565b91506136fd82613670565b604a82019050919050565b600061371382613569565b915061371f8285612ed8565b915061372a8261364d565b9150613735826136e5565b91506137418284612ed8565b91508190509392505050565b7f2066696c6c3d2200000000000000000000000000000000000000000000000000815250565b7f22206865696768743d2200000000000000000000000000000000000000000000815250565b60006137a48261374d565b6007820191506137b48285612ed8565b91506137bf82613773565b600a820191506137cf8284612ed8565b91506137da82613468565b6003820191508190509392505050565b7f3c7265637420783d22362220793d223139222077696474683d2231302220686560008201527f696768743d220000000000000000000000000000000000000000000000000000602082015250565b6000613846602683612e5b565b9150613851826137ea565b602682019050919050565b7f222073686170652d72656e646572696e673d226372697370456467657322206660008201527f696c6c3d22233030303030306666222f3e000000000000000000000000000000602082015250565b60006138b8603183612e5b565b91506138c38261385c565b603182019050919050565b7f3c7265637420783d22372220793d223139222077696474683d2238222073686160008201527f70652d72656e646572696e673d22637269737045646765732200000000000000602082015250565b600061392a603983612e5b565b9150613935826138ce565b603982019050919050565b600061394b82613839565b91506139578285612ed8565b9150613962826138ab565b915061396d8261391d565b91506139798284612ed8565b91508190509392505050565b7f3c7265637420783d2231302220793d223232222077696474683d22312220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d220000000000000000000000000000000000000000604082015250565b6000613a07604c83612e5b565b9150613a1282613985565b604c82019050919050565b6000613a28826139fa565b9150613a348284612ed8565b9150613a3f82613468565b60038201915081905092915050565b7f3c7265637420783d22382220793d223139222077696474683d2238222068656960008201527f6768743d22000000000000000000000000000000000000000000000000000000602082015250565b6000613aaa602583612e5b565b9150613ab582613a4e565b602582019050919050565b7f3c7265637420783d22392220793d223139222077696474683d2236222073686160008201527f70652d72656e646572696e673d22637269737045646765732200000000000000602082015250565b6000613b1c603983612e5b565b9150613b2782613ac0565b603982019050919050565b6000613b3d82613a9d565b9150613b498285612ed8565b9150613b54826138ab565b9150613b5f82613b0f565b9150613b6b8284612ed8565b91508190509392505050565b6000613b828261374d565b600782019150613b928284612ed8565b9150613b9d82613468565b60038201915081905092915050565b7f3c7265637420783d2231322220793d223233222077696474683d22312220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f6467657322000000000000000000000000000000000000000000000000000000604082015250565b6000613c2e604583612e5b565b9150613c3982613bac565b604582019050919050565b6000613c4f82613c21565b9150613c5b8284612ed8565b915081905092915050565b7f3c7265637420783d2231332220793d223232222077696474683d22312220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d22233030303030306666222f3e0000000000000000604082015250565b6000613ce8605883612e5b565b9150613cf382613c66565b605882019050919050565b6000613d0982613c21565b9150613d158284612ed8565b9150613d2082613cdb565b915081905092915050565b7f3c7265637420783d2231342220793d223230222077696474683d22322220686560008201527f696768743d2232222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d22233030303030306666222f3e3c7265637420783d60408201527f2231332220793d223231222077696474683d223222206865696768743d22322260608201527f2073686170652d72656e646572696e673d22637269737045646765732220666960808201527f6c6c3d22233030303030306666222f3e0000000000000000000000000000000060a082015250565b6000613e1f60b083612e5b565b9150613e2a82613d2b565b60b082019050919050565b6000613e4082613c21565b9150613e4c8284612ed8565b9150613e5782613e12565b915081905092915050565b7f3c7265637420783d2231322220793d223232222077696474683d22332220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d22236466646664666666222f3e0000000000000000604082015250565b6000613ee4605883612e5b565b9150613eef82613e62565b605882019050919050565b6000613f0582613c21565b9150613f118284612ed8565b9150613f1c82613ed7565b915081905092915050565b7f3c7265637420783d2231322220793d223232222077696474683d22332220686560008201527f696768743d2231222073686170652d72656e646572696e673d2263726973704560208201527f64676573222066696c6c3d22236666633932366666222f3e0000000000000000604082015250565b6000613fa9605883612e5b565b9150613fb482613f27565b605882019050919050565b6000613fca82613c21565b9150613fd68284612ed8565b9150613fe182613f9c565b915081905092915050565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323060008201527f30302f737667222076657273696f6e3d22312e32222076696577426f783d223060208201527f2030203234200000000000000000000000000000000000000000000000000000604082015250565b600061406e604683612e5b565b915061407982613fec565b604682019050919050565b7f223e3c726563742077696474683d223130302522206865696768743d2231303060008201527f25222066696c6c3d2223366138343934222f3e00000000000000000000000000602082015250565b60006140e0603383612e5b565b91506140eb82614084565b603382019050919050565b7f3c2f7376673e0000000000000000000000000000000000000000000000000000815250565b600061412782614061565b91506141338285612ed8565b915061413e826140d3565b915061414a8284612ed8565b9150614155826140f6565b6006820191508190509392505050565b600061417082612a15565b915061417b83612a15565b92508282101561418e5761418d612d5e565b5b828203905092915050565b60006141a482612a15565b91506141af83612a15565b9250826141bf576141be6130a4565b5b828206905092915050565b60006141d582612a15565b91506141e083612a15565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561421957614218612d5e565b5b828202905092915050565b7f3c7265637420783d220000000000000000000000000000000000000000000000815250565b7f2220793d22000000000000000000000000000000000000000000000000000000815250565b600061427b82614224565b60098201915061428b8285612ed8565b91506142968261424a565b6005820191506142a68284612ed8565b91508190509392505050565b7f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000600082015250565b60006142e8601783612e5b565b91506142f3826142b2565b601782019050919050565b7f206973206d697373696e6720726f6c6520000000000000000000000000000000600082015250565b6000614334601183612e5b565b915061433f826142fe565b601182019050919050565b6000614355826142db565b91506143618285612ed8565b915061436c82614327565b91506143788284612ed8565b91508190509392505050565b60008160011c9050919050565b6000808291508390505b60018511156143db578086048111156143b7576143b6612d5e565b5b60018516156143c65780820291505b80810290506143d485614384565b945061439b565b94509492505050565b6000826143f457600190506144b0565b8161440257600090506144b0565b8160018114614418576002811461442257614451565b60019150506144b0565b60ff84111561443457614433612d5e565b5b8360020a91508482111561444b5761444a612d5e565b5b506144b0565b5060208310610133831016604e8410600b84101617156144865782820a90508381111561448157614480612d5e565b5b6144b0565b6144938484846001614391565b925090508184048111156144aa576144a9612d5e565b5b81810290505b9392505050565b60006144c282612a15565b91506144cd83612a15565b92506144fa7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846143e4565b905092915050565b6000819050919050565b600061451782614502565b915061452283614502565b9250827f80000000000000000000000000000000000000000000000000000000000000000182126000841215161561455d5761455c612d5e565b5b827f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01821360008412161561459557614594612d5e565b5b828203905092915050565b60006145ab82612a15565b915060008214156145bf576145be612d5e565b5b600182039050919050565b7f537472696e67733a20686578206c656e67746820696e73756666696369656e74600082015250565b6000614600602083612b09565b915061460b826145ca565b602082019050919050565b6000602082019050818103600083015261462f816145f3565b905091905056fe3c7265637420783d2231322220793d2238222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22233030303030306666222f3e3c7265637420783d2231322220793d2235222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22233030303030306666222f3e3c7265637420783d2231302220793d223232222077696474683d223522206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22236666633932366666222f3e3c7265637420783d2231302220793d223232222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22236466646664666666222f3e3c7265637420783d2231342220793d223232222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22236466646664666666222f3e3c7265637420783d2231302220793d223232222077696474683d223522206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22236466646664666666222f3e646174613a696d6167652f7376672b786d6c3b757466382c3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f737667222076657273696f6e3d22312e32222076696577426f783d22302030203234203234223e4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2f3c7265637420783d2231322220793d2239222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22233030303030306666222f3e3c7265637420783d2231322220793d2236222077696474683d223122206865696768743d2231222073686170652d72656e646572696e673d2263726973704564676573222066696c6c3d22233030303030306666222f3ea2646970667358221220eec8e09d6a03713fdc8de5eb89475572ca7c5c7313c60af5379d64cb9237d50f64736f6c634300080c0033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.