Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Overview
Max Total Supply
375 EET
Holders
160
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
3 EETLoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
EET
Compiler Version
v0.8.14+commit.80d49f37
Optimization Enabled:
No with 100 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./GIF89a.sol"; import "./BytesLib.sol"; import "./iGUA.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface iBondingCurve { function getFee(uint256 _amount, address _currency) external view returns (uint256 fee); function burnTo(uint256 _tokenId, address _owner, address payable _msgSender, address _currency, bytes memory _burnPayload) external returns (bool rewarded); function pay(address _payee, uint256 _amount, uint256 _tokenCount, address _currency, bytes memory _mintPayload) external payable returns(bool success); } interface iEETRenderEngine { function render(uint256 _tokenId, address _guaContract, bytes3[] memory _colors, bytes memory _packedHeader) external view returns (string memory); function api(uint256 _tokenId, address _guaContract, bytes3[] memory _colors, bytes memory _packedHeader, address _scoreBoardAddress) external view returns (string memory json); } interface iScoreBoard { function addMintPayload(uint256 _eetTokenId, address _msgSender, bytes memory _mintPayload) external; function addBurnPayload(uint256 _eetTokenId, address _msgSender, bytes memory _burnPayload) external; } /** @title EET Contract * @author @0xAnimist * @notice A collaboration between Cai Guo-Qiang and Kanon */ contract EET is ERC721Enumerable, ReentrancyGuard { address public _artist; address public _manager; bytes3[] public _colors; bool public _colorsFrozen = false; uint256 private _ww = 9; uint256 private _hh = 15; address public _guaContract; bytes1 private _transIndex = 0x00; bytes1 private _disposalMethod = 0x04; bytes2 private _delay = 0x6400; address public _BondingCurveAddress; address public _EETRenderEngineAddress; address public _scoreBoardAddress; bool public _depsFrozen = false; struct GIFparts { bytes packedHeader; bytes header; bytes gce; bytes trailer; } GIFparts private _gifParts; modifier onlyAuth(){ require(msg.sender == _manager || msg.sender == _artist, "a"); _; } /** * @dev Constructor * @param manager_ Address Address of manager */ constructor(address manager_, bytes3[] memory colors_) ERC721("EET", "EET"){ _artist = msg.sender; _manager = manager_; _updateColors(colors_); } /** * @dev Updates colors * @param colors_ Array of colors by hex value */ function _updateColors(bytes3[] memory colors_) internal onlyAuth { _colors = colors_; //Generate GIF parts bytes1 packedLSD = GIF89a.formatLSDPackedField(_colors); bytes memory header = BytesLib.concat(BytesLib.concat(GIF89a.formatHeader(), GIF89a.formatLSD(_ww, _hh, packedLSD)), GIF89a.formatGCT(_colors)); bytes memory aeb = GIF89a.formatAEB(uint16(1)); bytes memory gce = GIF89a.formatGCE(true, _disposalMethod, _delay, true, _transIndex); bytes memory trailer = GIF89a.formatTrailer(); bytes memory packedHeader = BytesLib.concat(header, BytesLib.concat(aeb, gce)); _gifParts = GIFparts(packedHeader, header, gce, trailer); } /** * @dev Sets contract manager * @param manager_ Address Address of manager */ function setManager(address manager_) public { require(msg.sender == _manager, "m"); _manager = manager_; } /** * @dev Sets contract dependencies * @param guaContract_ Address of GUA contract * @param BondingCurveAddress_ Address of BondingCurve contract * @param EETRenderEngineAddress_ Address of EETRenderEngine contract * @param ScoreBoardAddress_ Address of ScoreBoard contract * @param _freeze Blocks any future changes if true */ function setDependencies(address guaContract_, address BondingCurveAddress_, address EETRenderEngineAddress_, address ScoreBoardAddress_, bool _freeze) external onlyAuth { require(!_depsFrozen, "f"); _guaContract = guaContract_; _BondingCurveAddress = BondingCurveAddress_; _EETRenderEngineAddress = EETRenderEngineAddress_; _scoreBoardAddress = ScoreBoardAddress_; _depsFrozen = _freeze; } /** * @dev Returns the URI of the token * @param _tokenId the token */ function tokenURI(uint256 _tokenId) public view override returns(string memory) { return iEETRenderEngine(_EETRenderEngineAddress).render(_tokenId, _guaContract, _colors, _gifParts.packedHeader); } /** * @dev Returns the URI of the token * @param _tokenId the token */ function tokenAPI(uint256 _tokenId) public view returns(string memory) { return iEETRenderEngine(_EETRenderEngineAddress).api(_tokenId, _guaContract, _colors, _gifParts.packedHeader, _scoreBoardAddress); } /** * @dev Mints one or more EET NFTs and corresponding GUA NFTs * @param _owners array of addresses to which the tokens will be minted * @param _queryhash keccak256 hash of the query * @param _rand Random number representing context/intent */ function mint(address[] memory _owners, bytes32[] memory _queryhash, uint256[] memory _rand, address _currency, string[] memory _encrypteds, bytes memory _mintPayload) public payable nonReentrant returns (uint256[] memory tokenIds){ //Pay fee uint256 fee = iBondingCurve(_BondingCurveAddress).getFee(_queryhash.length, _currency); require(iBondingCurve(_BondingCurveAddress).pay{value:msg.value, gas: gasleft()}(msg.sender, fee, _queryhash.length, _currency, _mintPayload), "u"); //Mint tokens tokenIds = new uint256[](_queryhash.length); for(uint256 i = 0; i < _queryhash.length; i++){ //mint GUA nft (tokenIds[i],) = iGUA(_guaContract).mint(_BondingCurveAddress, _queryhash[i], _rand[i], _encrypteds[i]); //store payload iScoreBoard(_scoreBoardAddress).addMintPayload(tokenIds[i], msg.sender, _mintPayload); //mint eet nft _safeMint(_owners[i], tokenIds[i]);//starts at token 1 bc seed starts at token 1 } } /** * @dev Burns EET NFT and unlocks GUA NFT for a reward from the Bonding Curve * @param _tokenIds Tokens to burn * @param _currency Currency of the reward * @param _burnPayload data */ function burnToCurve(uint256[] memory _tokenIds, address _currency, bytes memory _burnPayload) public nonReentrant { for(uint256 i = 0; i < _tokenIds.length; i++){ address owner = ownerOf(_tokenIds[i]); _burnToken(_tokenIds[i], msg.sender, _burnPayload); require(iBondingCurve(_BondingCurveAddress).burnTo(_tokenIds[i], owner, payable(msg.sender), _currency, _burnPayload), "f"); } } /** * @dev Burns EET NFT and updates ScoreBoard * @param _tokenId Token to burn * @param _msgSender sender * @param _burnPayload data */ function _burnToken(uint256 _tokenId, address _msgSender, bytes memory _burnPayload) internal { require(_isApprovedOrOwner(_msgSender, _tokenId), "a"); _burn(_tokenId); iScoreBoard(_scoreBoardAddress).addBurnPayload(_tokenId, msg.sender, _burnPayload); } }//end
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** @title GUA Interface * @author @0xAnimist * @notice A collaboration between Cai Guo-Qiang and Kanon */ interface iGUA { function getData(uint256 _tokenId) external view returns(bytes memory, bytes32 seed, bool queried, string memory encrypted); //function getGifs() external view returns(bytes[] memory); function tokenAPI(uint256 _tokenId) external view returns(string memory); function mint(address _owner, bytes32 _queryhash, uint256 _rand, string memory _encrypted) external returns(uint256 tokenId, bytes32 seed); function publishQuery(uint256 _tokenId, string memory _query) external returns (bool published); function redeemFortune(uint256 _tokenId, bytes32 _queryhash, uint256 _rand, string memory _encrypted) external returns(bool success); }//end
// SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; import "./BytesLib.sol"; /** @title GIF89a Contract * @author @0xAnimist * @notice First Onchain GIF, collaboration between Cai Guo-Qiang and Kanon */ library GIF89a { bytes1 public constant IMAGE_SEPARATOR = 0x2c; function buildStaticGIF(bytes3[] memory _colors, uint256 _ww, uint256 _hh, bool _trans, bytes1 _transIndex, uint8[][] memory _frame, bytes1 _packedLSD, uint16 _minCodeSize) public pure returns (bytes memory gif) { gif = formatHeader(); gif = bytes.concat(gif, formatLSD(_ww, _hh, _packedLSD)); gif = bytes.concat(gif, formatGCT(_colors)); gif = bytes.concat(gif, formatGCE(false, 0x00, 0x0000, _trans, _transIndex)); bytes1 packedImgDesc = 0x00;//no local color tables used gif = bytes.concat(gif, formatImageDescriptor(0, 0, _ww, _hh, packedImgDesc)); gif = bytes.concat( gif, formatImageLZW( _frame, _minCodeSize ) ); gif = bytes.concat(gif, formatTrailer()); } function buildAnimatedGifByPixel(bytes memory _buffer, uint8 _i, uint8 _y, bytes memory _packedHeader, bytes memory _gce, bytes memory _pixel) public pure returns (bytes memory buffer){ //image descriptor bytes memory imgDesc = formatImageDescriptor(_i, _y, 3, 3, 0x0000); //pixel-specific metadata if(_i == 0){//if first iteration buffer = BytesLib.concat(_packedHeader, imgDesc); }else{ buffer = BytesLib.concat(_buffer, BytesLib.concat(_gce, imgDesc)); } //lzw image data buffer = BytesLib.concat(buffer, _pixel); } function assembleGIFStack(bytes[] memory _parts) public pure returns (bytes memory gif) { for(uint256 i = 0; i < _parts.length; i++){ gif = BytesLib.concat(gif, _parts[i]); } } function assembleHeader(bytes3[] memory _colors, uint256 _ww, uint256 _hh) public pure returns (bytes[] memory header) { header = new bytes[](3); //format Header header[0] = formatHeader(); //format LSD bytes1 packedLSD = formatLSDPackedField(_colors); header[1] = formatLSD(_ww, _hh, packedLSD); //format GCT header[2] = formatGCT(_colors); } function assembleGIF(bytes memory _header, bytes memory _lsd, bytes memory _gct, bytes memory _gce, bytes memory _imgDesc, bytes memory _img, bytes memory _trailer) public pure returns (bytes memory) { bytes memory buffer; assembly { buffer := mload(0x40)//buffer == 0x80 //total length let len := add(mload(_gce),add(mload(_trailer),add(mload(_img),add(mload(_imgDesc),add(mload(_gct),add(mload(_lsd),mload(_header))))))) mstore(buffer, len) //header let pointer := add(buffer,0x20)//store the data after the length word let headerData := mload(add(_header,0x20)) mstore(pointer, headerData) //lsd pointer := add(pointer,mload(_header))//offset by header length let lsdData := mload(add(_lsd,0x20)) mstore(pointer, lsdData) pointer := add(pointer,mload(_lsd)) let gctData := mload(add(_gct,0x20)) mstore(pointer, gctData) pointer := add(pointer,mload(_gct)) let gceData := mload(add(_gce,0x20)) mstore(pointer, gceData) pointer := add(pointer,mload(_gce)) let imgDescData := mload(add(_imgDesc,0x20)) mstore(pointer, imgDescData) pointer := add(pointer,mload(_imgDesc)) let datawords := div(mload(_img),0x20)//number of 32-byte words of img data for { let i := 1 } lt(i, add(datawords,1)) { i := add(i, 1) } { mstore(pointer,mload(add(_img,mul(i,0x20)))) pointer := add(pointer,0x20) } //store remainder of _img let rem := mod(mload(_img),32)//3 for { let i := 0 } lt(i, rem) { i := add(i, 1) } { mstore8(pointer, byte(i,mload(add(_img,mul(add(datawords,1),0x20))))) pointer := add(pointer,1) } let trailerData := mload(add(_trailer,0x20)) mstore(pointer, trailerData) //determine how many 32-byte words are used in total let words := div(len,0x20)//total 32-byte words if gt(mod(len,32), 0) { words := add(words,1) } //update free memory pointer let nextmem := add(add(buffer,0x20),mul(words,0x20)) mstore(0x40, nextmem) } return buffer; } //Global Color Table function formatGCT(bytes3[] memory _colors) public pure returns (bytes memory) { require(_colors.length <= 256, "GIF89a: exceeds max colors"); uint256 len = fullColorTableSize(_colors.length); bytes memory buffer; bytes3 empty = 0x000000; //fill gct with all colors for(uint256 i = 0; i < _colors.length; i++){ buffer = bytes.concat(buffer, _colors[i]); }//end for i //pad gct so size is 2^n for(uint256 i = _colors.length; i < len; i++){ buffer = bytes.concat(buffer, empty); } return buffer; } //GIF89a function formatHeader() public pure returns (bytes memory) { bytes memory buffer = new bytes(6); buffer[0] = 0x47;//G buffer[1] = 0x49;//I buffer[2] = 0x46;//F buffer[3] = 0x38;//8 buffer[4] = 0x39;//9 buffer[5] = 0x61;//a return buffer; } //Logical Screen Display Packed Field function formatLSDPackedField(bytes3[] memory _colors) public pure returns(bytes1) { bytes memory packedField; uint256 gctSize = fullColorTableSize(_colors.length); uint8 colorResolution = uint8(root2(gctSize) - 1); require(colorResolution >= 0 && colorResolution < 8, "GIF89a: color resolution out of bounds"); assembly { packedField := mload(0x40) mstore(packedField, 1) let pointer := add(packedField, 0x20) mstore8(pointer, or(or(0x80, colorResolution), shl(4,colorResolution)))//0x80 for global color table flag mstore(0x40, 0x21)//TODO: should be add(packedField, 0x21) i think!? } return bytes1(packedField); } //Logical Screen Display function formatLSD(uint256 _ww, uint256 _hh, bytes1 _packedField) public pure returns (bytes memory) { bytes memory buffer;// = new bytes(6); assembly { buffer := mload(0x40)//buffer == 0x80 mstore(buffer, 0x07)//length == 0x06 == 6 let dataPointer := add(buffer, 0x20)//store the data after the length word //full image width mstore8(dataPointer, byte(31,_ww)) mstore8(add(dataPointer,1), byte(30,_ww)) //full image height mstore8(add(dataPointer,2), byte(31,_hh)) mstore8(add(dataPointer,3), byte(30,_hh)) //packed field mstore8(add(dataPointer,4), byte(0,_packedField)) //background color index mstore8(add(dataPointer,5), 0x00) //pixel aspect ratio (likely not implemented) mstore8(add(dataPointer,6), 0x00) mstore(0x40, add(buffer, 0x40))//0xc0 } return buffer; } //Application Extension Block (for infinite loop animation) function formatAEB(uint16 _loops) public pure returns (bytes memory) { bytes memory buffer = new bytes(19); bytes memory loops = abi.encodePacked(_loops); buffer[0] = 0x21;//GIF extension code buffer[1] = 0xFF;//Application extension label buffer[2] = 0x0B;//Length of Application Block buffer[3] = 0x4E;//"N" buffer[4] = 0x45;//"E" buffer[5] = 0x54;//"T" buffer[6] = 0x53;//"S" buffer[7] = 0x43;//"C" buffer[8] = 0x41;//"A" buffer[9] = 0x50;//"P" buffer[10] = 0x45;//"E" buffer[11] = 0x32;//"2" buffer[12] = 0x2E;//"." buffer[13] = 0x30;//"0" buffer[14] = 0x03;//Length of data sub-blocks buffer[15] = 0x01;//convention 0x01 buffer[16] = loops[0];//0x01;//Little endian # of loops: loop only 1x buffer[17] = loops[1];//0x00;//^^ buffer[18] = 0x00;//Data sub-block terminator return buffer; } /** * @dev Graphics Control Extension * @param _disposal 0x04 if you want to leave the last frame in place after the animation has finished; 0x08 if you want the last frame to be just the background color * @param _transIndex numerical gct index of the transparent color in bytes1 format */ function formatGCE(bool _animated, bytes1 _disposal, bytes2 _delay, bool _transparent, bytes1 _transIndex) public pure returns (bytes memory) { bytes memory buffer = new bytes(8); buffer[0] = 0x21; buffer[1] = 0xf9; buffer[2] = 0x04; buffer[3] = _animated ? _disposal : bytes1(0x00); if(_transparent){ buffer[3] = buffer[3] | bytes1(0x01); } buffer[4] = _animated ? _delay[0] : bytes1(0x00); buffer[5] = _animated ? _delay[1] : bytes1(0x00); buffer[6] = _transparent ? _transIndex : bytes1(0x00); buffer[7] = 0x00; return buffer; } /** * @dev Image Descriptor * @param _ll image left * _@param _tt image top */ function formatImageDescriptor(uint256 _ll, uint256 _tt, uint256 _ww, uint256 _hh, bytes1 _packedField) public pure returns (bytes memory) { bytes memory buffer; assembly { buffer := mload(0x40)//buffer == 0x80 mstore(buffer, 0x0a)//length == 0xa0 == 10 let dataPointer := add(buffer, 0x20)//store the data after the length word mstore8(dataPointer, 0x2c)//byte(0,IMAGE_SEPARATOR)) //image left mstore8(add(dataPointer,1), byte(31,_ll)) mstore8(add(dataPointer,2), byte(30,_ll)) //image top mstore8(add(dataPointer,3), byte(31,_tt)) mstore8(add(dataPointer,4), byte(30,_tt)) //full image width mstore8(add(dataPointer,5), byte(31,_ww)) mstore8(add(dataPointer,6), byte(30,_ww)) //full image height mstore8(add(dataPointer,7), byte(31,_hh)) mstore8(add(dataPointer,8), byte(30,_hh)) //packed field mstore8(add(dataPointer,9), byte(0,_packedField)) mstore(0x40, add(buffer, 0x40))//0xc0 } return buffer; } //Trailer function formatTrailer() public pure returns(bytes memory) { bytes memory trailer = new bytes(1); trailer[0] = 0x3b; return trailer; } //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////// IMAGE ////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////// /** * @dev Format Image in LZW Compression * @param _minimumCodeSize bits/pixel required (thus, size of gct == 2**_minimumCodeSize) */ function formatImageLZW(uint8[][] memory _indexMatrix, uint16 _minimumCodeSize) public pure returns (bytes memory) { //convert index matrix (im) to index stream (is) uint256 width = _indexMatrix[0].length; uint256 totalIndices = _indexMatrix.length * width;// assumes a rectangular index matrix bytes memory indexStream = new bytes(totalIndices);//each value is [0,0xff] == [0,255] because |gct| >= 256 for(uint256 i = 0; i < _indexMatrix.length; i++){ for(uint256 j = 0; j < width; j++){ indexStream[(i*width)+j] = bytes1(_indexMatrix[i][j]); } } //generate code stream (cs) bytes memory cs = encodeImage(indexStream, _minimumCodeSize); //break code stream down into chunks <= 0xff in length cs = chunkCodeStream(cs); //prepend minimum code size cs = bytes.concat(bytes1(uint8(_minimumCodeSize)), cs); return cs; } //this function chunks the code stream out into N 0xff-long blocks function chunkCodeStream(bytes memory _cs) public pure returns(bytes memory cs) { uint256 fullChunks = (_cs.length / 0xff); uint8 remainder = uint8(_cs.length % 0xff); uint256 chunks = (remainder > 0) ? fullChunks + 1 : fullChunks; cs = new bytes(_cs.length + 2*chunks); uint256 i = 0; uint256 j = 0; while(remainder > 0){ if(fullChunks > 0){ cs[i++] = 0xff; for(uint256 k = j; k < (j+256); k++){ cs[i++] = _cs[k]; } cs[i++] = 0x00; j += 256; fullChunks--; }else{ cs[i++] = bytes1(remainder); for(uint256 k = j; k < (j + uint256(remainder)); k++){ cs[i++] = _cs[k]; } cs[i] = 0x00; remainder = 0; } }//end while } function encodeImage(bytes memory _is, uint16 _minimumCodeSize) public pure returns(bytes memory) { uint16 codeSizeInBits = _minimumCodeSize + 1; (bytes memory cs, int256 isIndex) = packImage(_is, codeSizeInBits); while(isIndex < 0){ _is = removeFirstNBytes(_is, uint256(isIndex*(-1))); (cs, isIndex) = packImage(_is, codeSizeInBits); } return cs; } function removeFirstNBytes(bytes memory _is, uint256 _n) public pure returns(bytes memory is_) { is_ = new bytes(_is.length - _n); for(uint256 j = _n; j < is_.length; j++){ is_[j-_n] = _is[j]; } } /** * @param _codeSizeInBits initial code size, one greater than the minimum code size (ie. one bit greater than the amount needed to represent all the indices in the gct) */ function packImage(bytes memory _is, uint16 _codeSizeInBits) public pure returns(bytes memory cs, int isIndex) { uint256 csBitLen = 0; uint16 cc = uint16(2**(_codeSizeInBits-1)); bytes[] memory ct;//code table (cs, csBitLen) = addToCS(cs, csBitLen, cc, _codeSizeInBits);//send clear code (== total colors == 2**_minimumCodeSize == 2**(_codeSizeInBits-1)) bytes memory ib = new bytes(1);//index buffer ib[0] = _is[uint256(isIndex++)]; uint256 index; uint256 code; for(uint256 i = uint256(isIndex); i < _is.length; i++){ ib = pushToBytes(ib, _is[i]); //emit IB(i, ib); bool alreadyInCT; (alreadyInCT, index) = isInCodeTable(ct, ib, cc+1); if(!alreadyInCT){ if(ib.length == 2){ (cs, csBitLen) = addToCS(cs, csBitLen, uint256(uint8(ib[0])), _codeSizeInBits); }else{ (cs, csBitLen) = addToCS(cs, csBitLen, code, _codeSizeInBits); } //add ib to code table, increment codeSizeInBits if appropriate (ct, _codeSizeInBits) = addToCT(ct, ib, _codeSizeInBits, (cc+1)); ib = clearToLen1(ib); ib[0] = _is[i]; //push ib[0] to the code stream if this is the last index if(i == (_is.length-1)){ (cs, csBitLen) = addToCS(cs, csBitLen, uint256(uint8(ib[0])), _codeSizeInBits); } //must reset color table (ct) if if(ct.length == (4095 - cc - 1)){ isIndex = int(i+1)*(-1);//i has been added to the cs, so start again at i+1 break; } }else{ code = index; //push code to the code stream if this is the last index if(i == (_is.length-1)){ (cs, csBitLen) = addToCS(cs, csBitLen, code, _codeSizeInBits); } } }//end for //(cs, csBitLen) = addToCS(cs, csBitLen, index, _codeSizeInBits); (cs,) = addToCS(cs, csBitLen, cc+1, _codeSizeInBits);//_totalColors + 1 == end of information code } function invertByteOrder(bytes memory _cs) public pure returns(bytes memory cs) { cs = new bytes(_cs.length); for(uint256 i = 0; i < _cs.length; i++){ cs[i] = _cs[_cs.length - 1]; } } function addToCS(bytes memory _cs, uint256 _csBitLen, uint256 _code, uint256 _codeSizeInBits) public pure returns(bytes memory cs, uint256 csBitLen) { uint256 bitsUsedInLastByte = _csBitLen % 8;//how many used bits in the last byte uint256 bitsLeftInLastByte = 8 - bitsUsedInLastByte; uint256 bytesToChange = 0; uint256 bytesToAdd = 0; if(bitsUsedInLastByte == 0){ bytesToAdd = (_codeSizeInBits > 8) ? 2 : 1; }else{ bytesToChange = 1; if(_codeSizeInBits > bitsLeftInLastByte){ bytesToAdd++; if(_codeSizeInBits > (8 + bitsLeftInLastByte)){ bytesToAdd++; }//end if }//end if }//end ifelse if(bytesToChange == 1){ assembly { let lastByteOfCSPointer := add(_cs,add(0x20,sub(mload(_cs),1))) let lastByteOfCS := byte(0, mload(lastByteOfCSPointer)) let oredLastByte := or(lastByteOfCS, byte(31,shl(bitsUsedInLastByte, _code)))//0x0c mstore8(lastByteOfCSPointer, oredLastByte) }//end assembly }//end if cs = new bytes(_cs.length + bytesToAdd); for(uint256 i = 0; i < _cs.length; i++){ cs[i] = _cs[i]; }//end for if(bytesToAdd > 0){ assembly { let firstNewByteOfCSPointer := add(cs,add(0x20, mload(_cs))) mstore8(firstNewByteOfCSPointer, byte(sub(31,bytesToChange),shl(bitsUsedInLastByte, _code))) if eq(bytesToAdd, 2) { mstore8(add(firstNewByteOfCSPointer, 1), byte(sub(30,bytesToChange),shl(bitsUsedInLastByte, _code))) }//end if }//end assembly }//end if csBitLen = _csBitLen + _codeSizeInBits; } function clearToLen1(bytes memory _arr) public pure returns(bytes memory) { bytes memory arr = new bytes(1); for(uint256 i = 0; i < _arr.length-1; i++){ delete _arr[i]; } _arr = arr; return arr; } function push1DTo(uint256[] memory _pre, uint256[] memory _post) public pure returns(uint256[] memory arr) { uint256 len = _pre.length + _post.length; arr = new uint256[](len); for(uint256 i = 0; i < _pre.length; i++){ arr[i] = _pre[i]; } for(uint256 j = _pre.length; j < len; j++){ arr[j] = _post[j-_pre.length]; } } function pushTo(uint256[] memory _arr, uint256 _value) public pure returns(uint256[] memory arr) { arr = new uint256[](_arr.length+1); for(uint256 i = 0; i < _arr.length; i++){ arr[i] = _arr[i]; } arr[_arr.length] = _value; } function pushToBytes(bytes memory _arr, bytes1 _value) public pure returns(bytes memory arr) { arr = new bytes(_arr.length+1); arr = bytes.concat(_arr,_value); } function popFrom(uint256[] memory _arr) public pure returns(uint256[] memory arr) { arr = new uint256[](_arr.length-1); for(uint256 i = 0; i < _arr.length-1; i++){ arr[i] = _arr[i]; } } function addToCT(bytes[] memory _ct, bytes memory _arr, uint16 _codeSizeInBits, uint256 _eoi) public pure returns(bytes[] memory ct, uint16 codeSizeInBits) { uint256 len = _ct.length+1; //increment code size if latest code is == 2**codeSizeInBits - 1 if((_ct.length + _eoi) >= ((2**_codeSizeInBits) - 1)){ codeSizeInBits = _codeSizeInBits + 1; }else{ codeSizeInBits = _codeSizeInBits; } ct = new bytes[](len); for(uint256 i = 0; i < len-1; i++){ ct[i] = _ct[i]; } ct[len-1] = new bytes(_arr.length); for(uint256 j = 0; j < _arr.length; j++){ ct[len-1][j] = _arr[j]; } } function isInCodeTable(bytes[] memory _ct, bytes memory _ib, uint256 _eoi) public pure returns(bool contained, uint256 index) { //compare ib against every element of _ct for(uint256 i = 0; i < _ct.length; i++){ if(_ct[i].length == _ib.length){ bool matches = true; for(uint256 j = 0; j < _ct[i].length; j++){ if(_ct[i][j] != _ib[j]){ matches = false; break; } } if(matches){ return (true, i+_eoi+1); } }//end if }//end for return (false,0); } function root2(uint256 _val) public pure returns(uint256 n) { //require(_val%2 == 0, "GIF89a: root2"); while(_val > 1){ require(_val%2 == 0, "GIF89a: root2"); _val = _val/2; n++; } } function fullColorTableSize(uint256 _value) public pure returns(uint256 len) { len = 1; uint256 temp = _value - 1; while(temp > 1){ temp = temp/2; len++; } len = 2**len; } function getMinimumCodeSize(uint256 _totalColors) public pure returns(uint256 minCodeSize) { minCodeSize = root2(fullColorTableSize(_totalColors)); if(minCodeSize < 2){ return 2; } } }//end GIF89a
// SPDX-License-Identifier: Unlicense /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function concat( bytes memory _preBytes, bytes memory _postBytes ) internal pure returns (bytes memory) { bytes memory tempBytes; assembly { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // Store the length of the first bytes array at the beginning of // the memory for tempBytes. let length := mload(_preBytes) mstore(tempBytes, length) // Maintain a memory counter for the current write location in the // temp bytes array by adding the 32 bytes for the array length to // the starting location. let mc := add(tempBytes, 0x20) // Stop copying when the memory counter reaches the length of the // first bytes array. let end := add(mc, length) for { // Initialize a copy counter to the start of the _preBytes data, // 32 bytes into its memory. let cc := add(_preBytes, 0x20) } lt(mc, end) { // Increase both counters by 32 bytes each iteration. mc := add(mc, 0x20) cc := add(cc, 0x20) } { // Write the _preBytes data into the tempBytes memory 32 bytes // at a time. mstore(mc, mload(cc)) } // Add the length of _postBytes to the current length of tempBytes // and store it as the new length in the first 32 bytes of the // tempBytes memory. length := mload(_postBytes) mstore(tempBytes, add(length, mload(tempBytes))) // Move the memory counter back from a multiple of 0x20 to the // actual end of the _preBytes data. mc := end // Stop copying when the memory counter reaches the new combined // length of the arrays. end := add(mc, length) for { let cc := add(_postBytes, 0x20) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } // Update the free-memory pointer by padding our last write location // to 32 bytes: add 31 bytes to the end of tempBytes to move to the // next 32 byte block, then round down to the nearest multiple of // 32. If the sum of the length of the two arrays is zero then add // one before rounding down to leave a blank 32 bytes (the length block with 0). mstore(0x40, and( add(add(end, iszero(add(length, mload(_preBytes)))), 31), not(31) // Round down to the nearest 32 bytes. )) } return tempBytes; } function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal { assembly { // Read the first 32 bytes of _preBytes storage, which is the length // of the array. (We don't need to use the offset into the slot // because arrays use the entire slot.) let fslot := sload(_preBytes.slot) // Arrays of 31 bytes or less have an even value in their slot, // while longer arrays have an odd value. The actual length is // the slot divided by two for odd values, and the lowest order // byte divided by two for even values. // If the slot is even, bitwise and the slot with 255 and divide by // two to get the length. If the slot is odd, bitwise and the slot // with -1 and divide by two. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) let newlength := add(slength, mlength) // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage switch add(lt(slength, 32), lt(newlength, 32)) case 2 { // Since the new array still fits in the slot, we just need to // update the contents of the slot. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length sstore( _preBytes.slot, // all the modifications to the slot are inside this // next block add( // we can just add to the slot contents because the // bytes we want to change are the LSBs fslot, add( mul( div( // load the bytes from memory mload(add(_postBytes, 0x20)), // zero all bytes to the right exp(0x100, sub(32, mlength)) ), // and now shift left the number of bytes to // leave space for the length in the slot exp(0x100, sub(32, newlength)) ), // increase length by the double of the memory // bytes length mul(mlength, 2) ) ) ) } case 1 { // The stored value fits in the slot, but the combined value // will exceed it. // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // The contents of the _postBytes array start 32 bytes into // the structure. Our first read should obtain the `submod` // bytes that can fit into the unused space in the last word // of the stored array. To get this, we read 32 bytes starting // from `submod`, so the data we read overlaps with the array // contents by `submod` bytes. Masking the lowest-order // `submod` bytes allows us to add that value directly to the // stored value. let submod := sub(32, slength) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore( sc, add( and( fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00 ), and(mload(mc), mask) ) ) for { mc := add(mc, 0x20) sc := add(sc, 1) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } default { // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) // Start copying to the last used word of the stored array. let sc := add(keccak256(0x0, 0x20), div(slength, 32)) // save new length sstore(_preBytes.slot, add(mul(newlength, 2), 1)) // Copy over the first `submod` bytes of the new data as in // case 1 above. let slengthmod := mod(slength, 32) let mlengthmod := mod(mlength, 32) let submod := sub(32, slengthmod) let mc := add(_postBytes, submod) let end := add(_postBytes, mlength) let mask := sub(exp(0x100, submod), 1) sstore(sc, add(sload(sc), and(mload(mc), mask))) for { sc := add(sc, 1) mc := add(mc, 0x20) } lt(mc, end) { sc := add(sc, 1) mc := add(mc, 0x20) } { sstore(sc, mload(mc)) } mask := exp(0x100, sub(mc, end)) sstore(sc, mul(div(mload(mc), mask), mask)) } } } function slice( bytes memory _bytes, uint256 _start, uint256 _length ) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) { require(_bytes.length >= _start + 1 , "toUint8_outOfBounds"); uint8 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x1), _start)) } return tempUint; } function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) { require(_bytes.length >= _start + 2, "toUint16_outOfBounds"); uint16 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x2), _start)) } return tempUint; } function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) { require(_bytes.length >= _start + 4, "toUint32_outOfBounds"); uint32 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x4), _start)) } return tempUint; } function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) { require(_bytes.length >= _start + 8, "toUint64_outOfBounds"); uint64 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x8), _start)) } return tempUint; } function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) { require(_bytes.length >= _start + 12, "toUint96_outOfBounds"); uint96 tempUint; assembly { tempUint := mload(add(add(_bytes, 0xc), _start)) } return tempUint; } function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) { require(_bytes.length >= _start + 16, "toUint128_outOfBounds"); uint128 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x10), _start)) } return tempUint; } function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) { require(_bytes.length >= _start + 32, "toUint256_outOfBounds"); uint256 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x20), _start)) } return tempUint; } function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) { require(_bytes.length >= _start + 32, "toBytes32_outOfBounds"); bytes32 tempBytes32; assembly { tempBytes32 := mload(add(add(_bytes, 0x20), _start)) } return tempBytes32; } function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) { bool success = true; assembly { let length := mload(_preBytes) // if lengths don't match the arrays are not equal switch eq(length, mload(_postBytes)) case 1 { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 let mc := add(_preBytes, 0x20) let end := add(mc, length) for { let cc := add(_postBytes, 0x20) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) } eq(add(lt(mc, end), cb), 2) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { // if any of these checks fails then arrays are not equal if iszero(eq(mload(mc), mload(cc))) { // unsuccess: success := 0 cb := 0 } } } default { // unsuccess: success := 0 } } return success; } function equalStorage( bytes storage _preBytes, bytes memory _postBytes ) internal view returns (bool) { bool success = true; assembly { // we know _preBytes_offset is 0 let fslot := sload(_preBytes.slot) // Decode the length of the stored array like in concatStorage(). let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2) let mlength := mload(_postBytes) // if lengths don't match the arrays are not equal switch eq(slength, mlength) case 1 { // slength can contain both the length and contents of the array // if length < 32 bytes so let's prepare for that // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage if iszero(iszero(slength)) { switch lt(slength, 32) case 1 { // blank the last byte which is the length fslot := mul(div(fslot, 0x100), 0x100) if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) { // unsuccess: success := 0 } } default { // cb is a circuit breaker in the for loop since there's // no said feature for inline assembly loops // cb = 1 - don't breaker // cb = 0 - break let cb := 1 // get the keccak hash to get the contents of the array mstore(0x0, _preBytes.slot) let sc := keccak256(0x0, 0x20) let mc := add(_postBytes, 0x20) let end := add(mc, mlength) // the next line is the loop condition: // while(uint256(mc < end) + cb == 2) for {} eq(add(lt(mc, end), cb), 2) { sc := add(sc, 1) mc := add(mc, 0x20) } { if iszero(eq(sload(sc), mload(mc))) { // unsuccess: success := 0 cb := 0 } } } } } default { // unsuccess: success := 0 } } return success; } function toHex(bytes memory buffer) public pure returns (string memory) { // Fixed buffer size for hexadecimal convertion bytes memory converted = new bytes(buffer.length * 2); bytes memory _base = "0123456789abcdef"; for (uint256 i = 0; i < buffer.length; i++) { converted[i * 2] = _base[uint8(buffer[i]) / _base.length]; converted[i * 2 + 1] = _base[uint8(buffer[i]) % _base.length]; } return string(abi.encodePacked("0x", converted)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } }
// 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); }
// 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 (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _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) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @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] = _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 (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 (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev See {ERC721-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual override { super._beforeTokenTransfer(from, to, firstTokenId, batchSize); if (batchSize > 1) { // Will only trigger during construction. Batch transferring (minting) is not available afterwards. revert("ERC721Enumerable: consecutive transfers not supported"); } uint256 tokenId = firstTokenId; if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256, /* firstTokenId */ uint256 batchSize ) internal virtual { if (batchSize > 1) { if (from != address(0)) { _balances[from] -= batchSize; } if (to != address(0)) { _balances[to] += batchSize; } } } /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
{ "remappings": [], "optimizer": { "enabled": false, "runs": 100 }, "evmVersion": "london", "libraries": { "/contracts/GIF89a.sol": { "GIF89a": "0x83B9d161Ad0f2a54663FA579a2B5dd4799bbCd46" } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"manager_","type":"address"},{"internalType":"bytes3[]","name":"colors_","type":"bytes3[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"_BondingCurveAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_EETRenderEngineAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_artist","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"_colors","outputs":[{"internalType":"bytes3","name":"","type":"bytes3"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_colorsFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_depsFrozen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_guaContract","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_manager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_scoreBoardAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address","name":"_currency","type":"address"},{"internalType":"bytes","name":"_burnPayload","type":"bytes"}],"name":"burnToCurve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_owners","type":"address[]"},{"internalType":"bytes32[]","name":"_queryhash","type":"bytes32[]"},{"internalType":"uint256[]","name":"_rand","type":"uint256[]"},{"internalType":"address","name":"_currency","type":"address"},{"internalType":"string[]","name":"_encrypteds","type":"string[]"},{"internalType":"bytes","name":"_mintPayload","type":"bytes"}],"name":"mint","outputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guaContract_","type":"address"},{"internalType":"address","name":"BondingCurveAddress_","type":"address"},{"internalType":"address","name":"EETRenderEngineAddress_","type":"address"},{"internalType":"address","name":"ScoreBoardAddress_","type":"address"},{"internalType":"bool","name":"_freeze","type":"bool"}],"name":"setDependencies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"manager_","type":"address"}],"name":"setManager","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":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenAPI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526000600e60006101000a81548160ff0219169083151502179055506009600f55600f601055600060f81b601160146101000a81548160ff021916908360f81c0217905550600460f81b601160156101000a81548160ff021916908360f81c021790555061640060f01b601160166101000a81548161ffff021916908360f01c021790555060006014806101000a81548160ff021916908315150217905550348015620000af57600080fd5b506040516200688d3803806200688d8339818101604052810190620000d5919062000cb4565b6040518060400160405280600381526020017f45455400000000000000000000000000000000000000000000000000000000008152506040518060400160405280600381526020017f454554000000000000000000000000000000000000000000000000000000000081525081600090805190602001906200015992919062000876565b5080600190805190602001906200017292919062000876565b5050506001600a8190555033600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555062000210816200021860201b60201c565b5050620016a1565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480620002c25750600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b62000304576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002fb9062000d7b565b60405180910390fd5b80600d90805190602001906200031c92919062000907565b5060007383b9d161ad0f2a54663fa579a2b5dd4799bbcd4663cb3020a2600d6040518263ffffffff1660e01b8152600401620003599190620012ee565b602060405180830381865af415801562000377573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200039d91906200136f565b905060006200054d620004b97383b9d161ad0f2a54663fa579a2b5dd4799bbcd4663cc51ba376040518163ffffffff1660e01b8152600401600060405180830381865af4158015620003f3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906200041e919062001490565b7383b9d161ad0f2a54663fa579a2b5dd4799bbcd4663c421700f600f54601054886040518463ffffffff1660e01b81526004016200045f939291906200150d565b600060405180830381865af41580156200047d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620004a8919062001490565b620007e860201b62001a1e1760201c565b7383b9d161ad0f2a54663fa579a2b5dd4799bbcd466339348b86600d6040518263ffffffff1660e01b8152600401620004f39190620012ee565b600060405180830381865af415801562000511573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906200053c919062001490565b620007e860201b62001a1e1760201c565b905060007383b9d161ad0f2a54663fa579a2b5dd4799bbcd46637573346260016040518263ffffffff1660e01b81526004016200058b919062001569565b600060405180830381865af4158015620005a9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190620005d4919062001490565b905060007383b9d161ad0f2a54663fa579a2b5dd4799bbcd4663c9318ac16001601160159054906101000a900460f81b601160169054906101000a900460f01b6001601160149054906101000a900460f81b6040518663ffffffff1660e01b815260040162000648959493929190620015e0565b600060405180830381865af415801562000666573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019062000691919062001490565b905060007383b9d161ad0f2a54663fa579a2b5dd4799bbcd46639125c45c6040518163ffffffff1660e01b8152600401600060405180830381865af4158015620006df573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906200070a919062001490565b905060006200073b856200072a8686620007e860201b62001a1e1760201c565b620007e860201b62001a1e1760201c565b9050604051806080016040528082815260200186815260200184815260200183815250601560008201518160000190805190602001906200077e929190620009b9565b5060208201518160010190805190602001906200079d929190620009b9565b506040820151816002019080519060200190620007bc929190620009b9565b506060820151816003019080519060200190620007db929190620009b9565b5090505050505050505050565b6060806040519050835180825260208201818101602087015b8183101562000820578051835260208301925060208101905062000801565b50855192508351830184528091508282019050602086015b8183101562000857578051835260208301925060208101905062000838565b50601f19601f8851850115830101166040525050508091505092915050565b82805462000884906200166c565b90600052602060002090601f016020900481019282620008a85760008555620008f4565b82601f10620008c357805160ff1916838001178555620008f4565b82800160010185558215620008f4579182015b82811115620008f3578251825591602001919060010190620008d6565b5b50905062000903919062000a4a565b5090565b82805482825590600052602060002090600901600a90048101928215620009a65791602002820160005b838211156200097357835183826101000a81548162ffffff021916908360e81c0217905550926020019260030160208160020104928301926001030262000931565b8015620009a45782816101000a81549062ffffff021916905560030160208160020104928301926001030262000973565b505b509050620009b5919062000a4a565b5090565b828054620009c7906200166c565b90600052602060002090601f016020900481019282620009eb576000855562000a37565b82601f1062000a0657805160ff191683800117855562000a37565b8280016001018555821562000a37579182015b8281111562000a3657825182559160200191906001019062000a19565b5b50905062000a46919062000a4a565b5090565b5b8082111562000a6557600081600090555060010162000a4b565b5090565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600062000aaa8262000a7d565b9050919050565b62000abc8162000a9d565b811462000ac857600080fd5b50565b60008151905062000adc8162000ab1565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b62000b328262000ae7565b810181811067ffffffffffffffff8211171562000b545762000b5362000af8565b5b80604052505050565b600062000b6962000a69565b905062000b77828262000b27565b919050565b600067ffffffffffffffff82111562000b9a5762000b9962000af8565b5b602082029050602081019050919050565b600080fd5b60007fffffff000000000000000000000000000000000000000000000000000000000082169050919050565b62000be78162000bb0565b811462000bf357600080fd5b50565b60008151905062000c078162000bdc565b92915050565b600062000c2462000c1e8462000b7c565b62000b5d565b9050808382526020820190506020840283018581111562000c4a5762000c4962000bab565b5b835b8181101562000c77578062000c62888262000bf6565b84526020840193505060208101905062000c4c565b5050509392505050565b600082601f83011262000c995762000c9862000ae2565b5b815162000cab84826020860162000c0d565b91505092915050565b6000806040838503121562000cce5762000ccd62000a73565b5b600062000cde8582860162000acb565b925050602083015167ffffffffffffffff81111562000d025762000d0162000a78565b5b62000d108582860162000c81565b9150509250929050565b600082825260208201905092915050565b7f6100000000000000000000000000000000000000000000000000000000000000600082015250565b600062000d6360018362000d1a565b915062000d708262000d2b565b602082019050919050565b6000602082019050818103600083015262000d968162000d54565b9050919050565b600081549050919050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b62000dd98162000bb0565b82525050565b60008160001c9050919050565b60008160e81b9050919050565b600062000e068262000dec565b9050919050565b600062000e2462000e1e8362000ddf565b62000df9565b9050919050565b60008160181c9050919050565b600062000e4f62000e498362000e2b565b62000df9565b9050919050565b60008160301c9050919050565b600062000e7a62000e748362000e56565b62000df9565b9050919050565b60008160481c9050919050565b600062000ea562000e9f8362000e81565b62000df9565b9050919050565b60008160601c9050919050565b600062000ed062000eca8362000eac565b62000df9565b9050919050565b60008160781c9050919050565b600062000efb62000ef58362000ed7565b62000df9565b9050919050565b60008160901c9050919050565b600062000f2662000f208362000f02565b62000df9565b9050919050565b60008160a81c9050919050565b600062000f5162000f4b8362000f2d565b62000df9565b9050919050565b60008160c01c9050919050565b600062000f7c62000f768362000f58565b62000df9565b9050919050565b60008160d81c9050919050565b600062000fa762000fa18362000f83565b62000df9565b9050919050565b600062000fbb8262000d9d565b62000fc7818562000da8565b93508362000fd58462000db9565b60006001156200111d575b836001600a03820110156200111c5781546200100788620010018362000e0d565b62000dce565b60208801975062001023886200101d8362000e38565b62000dce565b6020880197506200103f88620010398362000e63565b62000dce565b6020880197506200105b88620010558362000e8e565b62000dce565b6020880197506200107788620010718362000eb9565b62000dce565b60208801975062001093886200108d8362000ee4565b62000dce565b602088019750620010af88620010a98362000f0f565b62000dce565b602088019750620010cb88620010c58362000f3a565b62000dce565b602088019750620010e788620010e18362000f65565b62000dce565b6020880197506200110388620010fd8362000f90565b62000dce565b60208801975060018301925050600a8101905062000fe0565b5b600115620012e15781548482101562001153576200114688620011408362000e0d565b62000dce565b6020880197506001820191505b848210156200117f5762001172886200116c8362000e38565b62000dce565b6020880197506001820191505b84821015620011ab576200119e88620011988362000e63565b62000dce565b6020880197506001820191505b84821015620011d757620011ca88620011c48362000e8e565b62000dce565b6020880197506001820191505b848210156200120357620011f688620011f08362000eb9565b62000dce565b6020880197506001820191505b848210156200122f5762001222886200121c8362000ee4565b62000dce565b6020880197506001820191505b848210156200125b576200124e88620012488362000f0f565b62000dce565b6020880197506001820191505b8482101562001287576200127a88620012748362000f3a565b62000dce565b6020880197506001820191505b84821015620012b357620012a688620012a08362000f65565b62000dce565b6020880197506001820191505b84821015620012df57620012d288620012cc8362000f90565b62000dce565b6020880197506001820191505b505b8694505050505092915050565b600060208201905081810360008301526200130a818462000fae565b905092915050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b620013498162001312565b81146200135557600080fd5b50565b60008151905062001369816200133e565b92915050565b60006020828403121562001388576200138762000a73565b5b6000620013988482850162001358565b91505092915050565b600080fd5b600067ffffffffffffffff821115620013c457620013c362000af8565b5b620013cf8262000ae7565b9050602081019050919050565b60005b83811015620013fc578082015181840152602081019050620013df565b838111156200140c576000848401525b50505050565b6000620014296200142384620013a6565b62000b5d565b905082815260208101848484011115620014485762001447620013a1565b5b62001455848285620013dc565b509392505050565b600082601f83011262001475576200147462000ae2565b5b81516200148784826020860162001412565b91505092915050565b600060208284031215620014a957620014a862000a73565b5b600082015167ffffffffffffffff811115620014ca57620014c962000a78565b5b620014d8848285016200145d565b91505092915050565b6000819050919050565b620014f681620014e1565b82525050565b620015078162001312565b82525050565b6000606082019050620015246000830186620014eb565b620015336020830185620014eb565b620015426040830184620014fc565b949350505050565b600061ffff82169050919050565b62001563816200154a565b82525050565b600060208201905062001580600083018462001558565b92915050565b60008115159050919050565b6200159d8162001586565b82525050565b60007fffff00000000000000000000000000000000000000000000000000000000000082169050919050565b620015da81620015a3565b82525050565b600060a082019050620015f7600083018862001592565b620016066020830187620014fc565b620016156040830186620015cf565b62001624606083018562001592565b620016336080830184620014fc565b9695505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200168557607f821691505b6020821081036200169b576200169a6200163d565b5b50919050565b6151dc80620016b16000396000f3fe60806040526004361061018d5760003560e01c806378a7ee6b116100d7578063b88d4fde11610085578063b88d4fde146105cf578063c6903b4d146105f8578063c87b56dd14610623578063d0ebdbe714610660578063e0347e1c14610689578063e8801de0146106b4578063e985e9c5146106dd578063f0329f6b1461071a5761018d565b806378a7ee6b1461048f5780637e114c0e146104cc578063899e42f9146104fc57806395d89b4114610527578063a22cb46514610552578063a2ac63351461057b578063aede32f4146105a65761018d565b80632f745c591161013f5780632f745c59146102df57806335c04b841461031c57806336e69514146103595780634046f91a1461038457806342842e0e146103af5780634f6ccce7146103d85780636352211e1461041557806370a08231146104525761018d565b806301ffc9a71461019257806306fdde03146101cf578063081812fc146101fa578063095ea7b31461023757806318160ddd1461026057806323b872dd1461028b57806325ba071b146102b4575b600080fd5b34801561019e57600080fd5b506101b960048036038101906101b49190612f9f565b610745565b6040516101c69190612fe7565b60405180910390f35b3480156101db57600080fd5b506101e46107bf565b6040516101f1919061309b565b60405180910390f35b34801561020657600080fd5b50610221600480360381019061021c91906130f3565b610851565b60405161022e9190613161565b60405180910390f35b34801561024357600080fd5b5061025e600480360381019061025991906131a8565b610897565b005b34801561026c57600080fd5b506102756109ae565b60405161028291906131f7565b60405180910390f35b34801561029757600080fd5b506102b260048036038101906102ad9190613212565b6109bb565b005b3480156102c057600080fd5b506102c9610a1b565b6040516102d69190612fe7565b60405180910390f35b3480156102eb57600080fd5b50610306600480360381019061030191906131a8565b610a2e565b60405161031391906131f7565b60405180910390f35b34801561032857600080fd5b50610343600480360381019061033e91906130f3565b610ad3565b604051610350919061309b565b60405180910390f35b34801561036557600080fd5b5061036e610bce565b60405161037b9190612fe7565b60405180910390f35b34801561039057600080fd5b50610399610bdf565b6040516103a69190613161565b60405180910390f35b3480156103bb57600080fd5b506103d660048036038101906103d19190613212565b610c05565b005b3480156103e457600080fd5b506103ff60048036038101906103fa91906130f3565b610c25565b60405161040c91906131f7565b60405180910390f35b34801561042157600080fd5b5061043c600480360381019061043791906130f3565b610c96565b6040516104499190613161565b60405180910390f35b34801561045e57600080fd5b5061047960048036038101906104749190613265565b610d1c565b60405161048691906131f7565b60405180910390f35b34801561049b57600080fd5b506104b660048036038101906104b191906130f3565b610dd3565b6040516104c391906132cd565b60405180910390f35b6104e660048036038101906104e19190613823565b610e0a565b6040516104f391906139fa565b60405180910390f35b34801561050857600080fd5b5061051161123c565b60405161051e9190613161565b60405180910390f35b34801561053357600080fd5b5061053c611262565b604051610549919061309b565b60405180910390f35b34801561055e57600080fd5b5061057960048036038101906105749190613a48565b6112f4565b005b34801561058757600080fd5b5061059061130a565b60405161059d9190613161565b60405180910390f35b3480156105b257600080fd5b506105cd60048036038101906105c89190613a88565b611330565b005b3480156105db57600080fd5b506105f660048036038101906105f19190613b13565b6114b1565b005b34801561060457600080fd5b5061060d611513565b60405161061a9190613161565b60405180910390f35b34801561062f57600080fd5b5061064a600480360381019061064591906130f3565b611539565b604051610657919061309b565b60405180910390f35b34801561066c57600080fd5b5061068760048036038101906106829190613265565b611610565b005b34801561069557600080fd5b5061069e6116e4565b6040516106ab9190613161565b60405180910390f35b3480156106c057600080fd5b506106db60048036038101906106d69190613b96565b61170a565b005b3480156106e957600080fd5b5061070460048036038101906106ff9190613c11565b611964565b6040516107119190612fe7565b60405180910390f35b34801561072657600080fd5b5061072f6119f8565b60405161073c9190613161565b60405180910390f35b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107b857506107b782611aa8565b5b9050919050565b6060600080546107ce90613c80565b80601f01602080910402602001604051908101604052809291908181526020018280546107fa90613c80565b80156108475780601f1061081c57610100808354040283529160200191610847565b820191906000526020600020905b81548152906001019060200180831161082a57829003601f168201915b5050505050905090565b600061085c82611b8a565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006108a282610c96565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610912576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090990613d23565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610931611bd5565b73ffffffffffffffffffffffffffffffffffffffff161480610960575061095f8161095a611bd5565b611964565b5b61099f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099690613db5565b60405180910390fd5b6109a98383611bdd565b505050565b6000600880549050905090565b6109cc6109c6611bd5565b82611c96565b610a0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0290613e47565b60405180910390fd5b610a16838383611d2b565b505050565b600e60009054906101000a900460ff1681565b6000610a3983610d1c565b8210610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613ed9565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b6060601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633fb1f67d83601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600d6015600001601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518663ffffffff1660e01b8152600401610b81959493929190614460565b600060405180830381865afa158015610b9e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610bc79190614531565b9050919050565b60148054906101000a900460ff1681565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c20838383604051806020016040528060008152506114b1565b505050565b6000610c2f6109ae565b8210610c70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c67906145ec565b60405180910390fd5b60088281548110610c8457610c8361460c565b5b90600052602060002001549050919050565b600080610ca283612024565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0a90614687565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8390614719565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600d8181548110610de357600080fd5b90600052602060002090600a9182820401919006600302915054906101000a900460e81b81565b6060610e14612061565b6000601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dfcf048d8851876040518363ffffffff1660e01b8152600401610e74929190614739565b602060405180830381865afa158015610e91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb59190614777565b9050601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d952411f345a9033858c518b8a6040518863ffffffff1660e01b8152600401610f1e9594939291906147e8565b602060405180830381858988f1158015610f3c573d6000803e3d6000fd5b5050505050506040513d601f19601f82011682018060405250810190610f629190614857565b610fa1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f98906148d0565b60405180910390fd5b865167ffffffffffffffff811115610fbc57610fbb6132ed565b5b604051908082528060200260200182016040528015610fea5781602001602082028036833780820191505090505b50915060005b875181101561122857601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663035868b4601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a848151811061106d5761106c61460c565b5b60200260200101518a85815181106110885761108761460c565b5b60200260200101518986815181106110a3576110a261460c565b5b60200260200101516040518563ffffffff1660e01b81526004016110ca94939291906148ff565b60408051808303816000875af11580156110e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110c9190614960565b508382815181106111205761111f61460c565b5b602002602001018181525050601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d7b1595c84838151811061117d5761117c61460c565b5b602002602001015133876040518463ffffffff1660e01b81526004016111a5939291906149a0565b600060405180830381600087803b1580156111bf57600080fd5b505af11580156111d3573d6000803e3d6000fd5b505050506112158982815181106111ed576111ec61460c565b5b60200260200101518483815181106112085761120761460c565b5b60200260200101516120b0565b808061122090614a0d565b915050610ff0565b50506112326120ce565b9695505050505050565b601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606001805461127190613c80565b80601f016020809104026020016040519081016040528092919081815260200182805461129d90613c80565b80156112ea5780601f106112bf576101008083540402835291602001916112ea565b820191906000526020600020905b8154815290600101906020018083116112cd57829003601f168201915b5050505050905090565b6113066112ff611bd5565b83836120d8565b5050565b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611338612061565b60005b83518110156114a357600061136985838151811061135c5761135b61460c565b5b6020026020010151610c96565b90506113908583815181106113815761138061460c565b5b60200260200101513385612244565b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340321e568684815181106113e1576113e061460c565b5b6020026020010151833388886040518663ffffffff1660e01b815260040161140d959493929190614a76565b6020604051808303816000875af115801561142c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114509190614857565b61148f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161148690614b1c565b60405180910390fd5b50808061149b90614a0d565b91505061133b565b506114ac6120ce565b505050565b6114c26114bc611bd5565b83611c96565b611501576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114f890613e47565b60405180910390fd5b61150d8484848461232c565b50505050565b601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c4e9d84e83601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600d60156000016040518563ffffffff1660e01b81526004016115c39493929190614b3c565b600060405180830381865afa1580156115e0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906116099190614531565b9050919050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169790614bdb565b60405180910390fd5b80600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806117b35750600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6117f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e990614c47565b60405180910390fd5b60148054906101000a900460ff1615611840576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161183790614b1c565b60405180910390fd5b84601160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081601460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806014806101000a81548160ff0219169083151502179055505050505050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060806040519050835180825260208201818101602087015b81831015611a545780518352602083019250602081019050611a37565b50855192508351830184528091508282019050602086015b81831015611a895780518352602083019250602081019050611a6c565b50601f19601f8851850115830101166040525050508091505092915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611b7357507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611b835750611b8282612388565b5b9050919050565b611b93816123f2565b611bd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc990614687565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611c5083610c96565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611ca283610c96565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611ce45750611ce38185611964565b5b80611d2257508373ffffffffffffffffffffffffffffffffffffffff16611d0a84610851565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611d4b82610c96565b73ffffffffffffffffffffffffffffffffffffffff1614611da1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d9890614cd9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e0790614d6b565b60405180910390fd5b611e1d8383836001612433565b8273ffffffffffffffffffffffffffffffffffffffff16611e3d82610c96565b73ffffffffffffffffffffffffffffffffffffffff1614611e93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8a90614cd9565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461201f8383836001612591565b505050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6002600a54036120a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209d90614dd7565b60405180910390fd5b6002600a81905550565b6120ca828260405180602001604052806000815250612597565b5050565b6001600a81905550565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612146576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213d90614e43565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516122379190612fe7565b60405180910390a3505050565b61224e8284611c96565b61228d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228490614c47565b60405180910390fd5b612296836125f2565b601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d1503d148433846040518463ffffffff1660e01b81526004016122f5939291906149a0565b600060405180830381600087803b15801561230f57600080fd5b505af1158015612323573d6000803e3d6000fd5b50505050505050565b612337848484611d2b565b61234384848484612740565b612382576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237990614ed5565b60405180910390fd5b50505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff1661241483612024565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b61243f848484846128c7565b6001811115612483576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161247a90614f67565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036124ca576124c5816129ed565b612509565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612508576125078582612a36565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361254b5761254681612ba3565b61258a565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612589576125888482612c74565b5b5b5050505050565b50505050565b6125a18383612cf3565b6125ae6000848484612740565b6125ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125e490614ed5565b60405180910390fd5b505050565b60006125fd82610c96565b905061260d816000846001612433565b61261682610c96565b90506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461273c816000846001612591565b5050565b60006127618473ffffffffffffffffffffffffffffffffffffffff16612f10565b156128ba578373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261278a611bd5565b8786866040518563ffffffff1660e01b81526004016127ac9493929190614f87565b6020604051808303816000875af19250505080156127e857506040513d601f19601f820116820180604052508101906127e59190614fe8565b60015b61286a573d8060008114612818576040519150601f19603f3d011682016040523d82523d6000602084013e61281d565b606091505b506000815103612862576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161285990614ed5565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150506128bf565b600190505b949350505050565b60018111156129e757600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461295b5780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546129539190615015565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146129e65780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546129de9190615049565b925050819055505b5b50505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001612a4384610d1c565b612a4d9190615015565b9050600060076000848152602001908152602001600020549050818114612b32576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600880549050612bb79190615015565b9050600060096000848152602001908152602001600020549050600060088381548110612be757612be661460c565b5b906000526020600020015490508060088381548110612c0957612c0861460c565b5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480612c5857612c5761509f565b5b6001900381819060005260206000200160009055905550505050565b6000612c7f83610d1c565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612d62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d599061511a565b60405180910390fd5b612d6b816123f2565b15612dab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612da290615186565b60405180910390fd5b612db9600083836001612433565b612dc2816123f2565b15612e02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612df990615186565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612f0c600083836001612591565b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612f7c81612f47565b8114612f8757600080fd5b50565b600081359050612f9981612f73565b92915050565b600060208284031215612fb557612fb4612f3d565b5b6000612fc384828501612f8a565b91505092915050565b60008115159050919050565b612fe181612fcc565b82525050565b6000602082019050612ffc6000830184612fd8565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561303c578082015181840152602081019050613021565b8381111561304b576000848401525b50505050565b6000601f19601f8301169050919050565b600061306d82613002565b613077818561300d565b935061308781856020860161301e565b61309081613051565b840191505092915050565b600060208201905081810360008301526130b58184613062565b905092915050565b6000819050919050565b6130d0816130bd565b81146130db57600080fd5b50565b6000813590506130ed816130c7565b92915050565b60006020828403121561310957613108612f3d565b5b6000613117848285016130de565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061314b82613120565b9050919050565b61315b81613140565b82525050565b60006020820190506131766000830184613152565b92915050565b61318581613140565b811461319057600080fd5b50565b6000813590506131a28161317c565b92915050565b600080604083850312156131bf576131be612f3d565b5b60006131cd85828601613193565b92505060206131de858286016130de565b9150509250929050565b6131f1816130bd565b82525050565b600060208201905061320c60008301846131e8565b92915050565b60008060006060848603121561322b5761322a612f3d565b5b600061323986828701613193565b935050602061324a86828701613193565b925050604061325b868287016130de565b9150509250925092565b60006020828403121561327b5761327a612f3d565b5b600061328984828501613193565b91505092915050565b60007fffffff000000000000000000000000000000000000000000000000000000000082169050919050565b6132c781613292565b82525050565b60006020820190506132e260008301846132be565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61332582613051565b810181811067ffffffffffffffff82111715613344576133436132ed565b5b80604052505050565b6000613357612f33565b9050613363828261331c565b919050565b600067ffffffffffffffff821115613383576133826132ed565b5b602082029050602081019050919050565b600080fd5b60006133ac6133a784613368565b61334d565b905080838252602082019050602084028301858111156133cf576133ce613394565b5b835b818110156133f857806133e48882613193565b8452602084019350506020810190506133d1565b5050509392505050565b600082601f830112613417576134166132e8565b5b8135613427848260208601613399565b91505092915050565b600067ffffffffffffffff82111561344b5761344a6132ed565b5b602082029050602081019050919050565b6000819050919050565b61346f8161345c565b811461347a57600080fd5b50565b60008135905061348c81613466565b92915050565b60006134a56134a084613430565b61334d565b905080838252602082019050602084028301858111156134c8576134c7613394565b5b835b818110156134f157806134dd888261347d565b8452602084019350506020810190506134ca565b5050509392505050565b600082601f8301126135105761350f6132e8565b5b8135613520848260208601613492565b91505092915050565b600067ffffffffffffffff821115613544576135436132ed565b5b602082029050602081019050919050565b600061356861356384613529565b61334d565b9050808382526020820190506020840283018581111561358b5761358a613394565b5b835b818110156135b457806135a088826130de565b84526020840193505060208101905061358d565b5050509392505050565b600082601f8301126135d3576135d26132e8565b5b81356135e3848260208601613555565b91505092915050565b600067ffffffffffffffff821115613607576136066132ed565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff821115613638576136376132ed565b5b61364182613051565b9050602081019050919050565b82818337600083830152505050565b600061367061366b8461361d565b61334d565b90508281526020810184848401111561368c5761368b613618565b5b61369784828561364e565b509392505050565b600082601f8301126136b4576136b36132e8565b5b81356136c484826020860161365d565b91505092915050565b60006136e06136db846135ec565b61334d565b9050808382526020820190506020840283018581111561370357613702613394565b5b835b8181101561374a57803567ffffffffffffffff811115613728576137276132e8565b5b808601613735898261369f565b85526020850194505050602081019050613705565b5050509392505050565b600082601f830112613769576137686132e8565b5b81356137798482602086016136cd565b91505092915050565b600067ffffffffffffffff82111561379d5761379c6132ed565b5b6137a682613051565b9050602081019050919050565b60006137c66137c184613782565b61334d565b9050828152602081018484840111156137e2576137e1613618565b5b6137ed84828561364e565b509392505050565b600082601f83011261380a576138096132e8565b5b813561381a8482602086016137b3565b91505092915050565b60008060008060008060c087890312156138405761383f612f3d565b5b600087013567ffffffffffffffff81111561385e5761385d612f42565b5b61386a89828a01613402565b965050602087013567ffffffffffffffff81111561388b5761388a612f42565b5b61389789828a016134fb565b955050604087013567ffffffffffffffff8111156138b8576138b7612f42565b5b6138c489828a016135be565b94505060606138d589828a01613193565b935050608087013567ffffffffffffffff8111156138f6576138f5612f42565b5b61390289828a01613754565b92505060a087013567ffffffffffffffff81111561392357613922612f42565b5b61392f89828a016137f5565b9150509295509295509295565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613971816130bd565b82525050565b60006139838383613968565b60208301905092915050565b6000602082019050919050565b60006139a78261393c565b6139b18185613947565b93506139bc83613958565b8060005b838110156139ed5781516139d48882613977565b97506139df8361398f565b9250506001810190506139c0565b5085935050505092915050565b60006020820190508181036000830152613a14818461399c565b905092915050565b613a2581612fcc565b8114613a3057600080fd5b50565b600081359050613a4281613a1c565b92915050565b60008060408385031215613a5f57613a5e612f3d565b5b6000613a6d85828601613193565b9250506020613a7e85828601613a33565b9150509250929050565b600080600060608486031215613aa157613aa0612f3d565b5b600084013567ffffffffffffffff811115613abf57613abe612f42565b5b613acb868287016135be565b9350506020613adc86828701613193565b925050604084013567ffffffffffffffff811115613afd57613afc612f42565b5b613b09868287016137f5565b9150509250925092565b60008060008060808587031215613b2d57613b2c612f3d565b5b6000613b3b87828801613193565b9450506020613b4c87828801613193565b9350506040613b5d878288016130de565b925050606085013567ffffffffffffffff811115613b7e57613b7d612f42565b5b613b8a878288016137f5565b91505092959194509250565b600080600080600060a08688031215613bb257613bb1612f3d565b5b6000613bc088828901613193565b9550506020613bd188828901613193565b9450506040613be288828901613193565b9350506060613bf388828901613193565b9250506080613c0488828901613a33565b9150509295509295909350565b60008060408385031215613c2857613c27612f3d565b5b6000613c3685828601613193565b9250506020613c4785828601613193565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613c9857607f821691505b602082108103613cab57613caa613c51565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613d0d60218361300d565b9150613d1882613cb1565b604082019050919050565b60006020820190508181036000830152613d3c81613d00565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613d9f603d8361300d565b9150613daa82613d43565b604082019050919050565b60006020820190508181036000830152613dce81613d92565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613e31602d8361300d565b9150613e3c82613dd5565b604082019050919050565b60006020820190508181036000830152613e6081613e24565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000613ec3602b8361300d565b9150613ece82613e67565b604082019050919050565b60006020820190508181036000830152613ef281613eb6565b9050919050565b600081549050919050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b613f3381613292565b82525050565b60008160001c9050919050565b60008160e81b9050919050565b6000613f5e82613f46565b9050919050565b6000613f78613f7383613f39565b613f53565b9050919050565b60008160181c9050919050565b6000613f9f613f9a83613f7f565b613f53565b9050919050565b60008160301c9050919050565b6000613fc6613fc183613fa6565b613f53565b9050919050565b60008160481c9050919050565b6000613fed613fe883613fcd565b613f53565b9050919050565b60008160601c9050919050565b600061401461400f83613ff4565b613f53565b9050919050565b60008160781c9050919050565b600061403b6140368361401b565b613f53565b9050919050565b60008160901c9050919050565b600061406261405d83614042565b613f53565b9050919050565b60008160a81c9050919050565b600061408961408483614069565b613f53565b9050919050565b60008160c01c9050919050565b60006140b06140ab83614090565b613f53565b9050919050565b60008160d81c9050919050565b60006140d76140d2836140b7565b613f53565b9050919050565b60006140e982613ef9565b6140f38185613f04565b9350836140ff84613f15565b600060011561421c575b836001600a038201101561421b57815461412b8861412683613f65565b613f2a565b6020880197506141438861413e83613f8c565b613f2a565b60208801975061415b8861415683613fb3565b613f2a565b6020880197506141738861416e83613fda565b613f2a565b60208801975061418b8861418683614001565b613f2a565b6020880197506141a38861419e83614028565b613f2a565b6020880197506141bb886141b68361404f565b613f2a565b6020880197506141d3886141ce83614076565b613f2a565b6020880197506141eb886141e68361409d565b613f2a565b602088019750614203886141fe836140c4565b613f2a565b60208801975060018301925050600a81019050614109565b5b6001156143ad5781548482101561424c5761423f8861423a83613f65565b613f2a565b6020880197506001820191505b84821015614273576142668861426183613f8c565b613f2a565b6020880197506001820191505b8482101561429a5761428d8861428883613fb3565b613f2a565b6020880197506001820191505b848210156142c1576142b4886142af83613fda565b613f2a565b6020880197506001820191505b848210156142e8576142db886142d683614001565b613f2a565b6020880197506001820191505b8482101561430f57614302886142fd83614028565b613f2a565b6020880197506001820191505b8482101561433657614329886143248361404f565b613f2a565b6020880197506001820191505b8482101561435d576143508861434b83614076565b613f2a565b6020880197506001820191505b8482101561438457614377886143728361409d565b613f2a565b6020880197506001820191505b848210156143ab5761439e88614399836140c4565b613f2a565b6020880197506001820191505b505b8694505050505092915050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b600081546143ed81613c80565b6143f781866143ba565b94506001821660008114614412576001811461442457614457565b60ff1983168652602086019350614457565b61442d856143cb565b60005b8381101561444f57815481890152600182019150602081019050614430565b808801955050505b50505092915050565b600060a08201905061447560008301886131e8565b6144826020830187613152565b818103604083015261449481866140de565b905081810360608301526144a881856143e0565b90506144b76080830184613152565b9695505050505050565b60006144d46144cf8461361d565b61334d565b9050828152602081018484840111156144f0576144ef613618565b5b6144fb84828561301e565b509392505050565b600082601f830112614518576145176132e8565b5b81516145288482602086016144c1565b91505092915050565b60006020828403121561454757614546612f3d565b5b600082015167ffffffffffffffff81111561456557614564612f42565b5b61457184828501614503565b91505092915050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b60006145d6602c8361300d565b91506145e18261457a565b604082019050919050565b60006020820190508181036000830152614605816145c9565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b600061467160188361300d565b915061467c8261463b565b602082019050919050565b600060208201905081810360008301526146a081614664565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b600061470360298361300d565b915061470e826146a7565b604082019050919050565b60006020820190508181036000830152614732816146f6565b9050919050565b600060408201905061474e60008301856131e8565b61475b6020830184613152565b9392505050565b600081519050614771816130c7565b92915050565b60006020828403121561478d5761478c612f3d565b5b600061479b84828501614762565b91505092915050565b600081519050919050565b60006147ba826147a4565b6147c481856143ba565b93506147d481856020860161301e565b6147dd81613051565b840191505092915050565b600060a0820190506147fd6000830188613152565b61480a60208301876131e8565b61481760408301866131e8565b6148246060830185613152565b818103608083015261483681846147af565b90509695505050505050565b60008151905061485181613a1c565b92915050565b60006020828403121561486d5761486c612f3d565b5b600061487b84828501614842565b91505092915050565b7f7500000000000000000000000000000000000000000000000000000000000000600082015250565b60006148ba60018361300d565b91506148c582614884565b602082019050919050565b600060208201905081810360008301526148e9816148ad565b9050919050565b6148f98161345c565b82525050565b60006080820190506149146000830187613152565b61492160208301866148f0565b61492e60408301856131e8565b81810360608301526149408184613062565b905095945050505050565b60008151905061495a81613466565b92915050565b6000806040838503121561497757614976612f3d565b5b600061498585828601614762565b92505060206149968582860161494b565b9150509250929050565b60006060820190506149b560008301866131e8565b6149c26020830185613152565b81810360408301526149d481846147af565b9050949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614a18826130bd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614a4a57614a496149de565b5b600182019050919050565b6000614a6082613120565b9050919050565b614a7081614a55565b82525050565b600060a082019050614a8b60008301886131e8565b614a986020830187613152565b614aa56040830186614a67565b614ab26060830185613152565b8181036080830152614ac481846147af565b90509695505050505050565b7f6600000000000000000000000000000000000000000000000000000000000000600082015250565b6000614b0660018361300d565b9150614b1182614ad0565b602082019050919050565b60006020820190508181036000830152614b3581614af9565b9050919050565b6000608082019050614b5160008301876131e8565b614b5e6020830186613152565b8181036040830152614b7081856140de565b90508181036060830152614b8481846143e0565b905095945050505050565b7f6d00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614bc560018361300d565b9150614bd082614b8f565b602082019050919050565b60006020820190508181036000830152614bf481614bb8565b9050919050565b7f6100000000000000000000000000000000000000000000000000000000000000600082015250565b6000614c3160018361300d565b9150614c3c82614bfb565b602082019050919050565b60006020820190508181036000830152614c6081614c24565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000614cc360258361300d565b9150614cce82614c67565b604082019050919050565b60006020820190508181036000830152614cf281614cb6565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000614d5560248361300d565b9150614d6082614cf9565b604082019050919050565b60006020820190508181036000830152614d8481614d48565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614dc1601f8361300d565b9150614dcc82614d8b565b602082019050919050565b60006020820190508181036000830152614df081614db4565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614e2d60198361300d565b9150614e3882614df7565b602082019050919050565b60006020820190508181036000830152614e5c81614e20565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614ebf60328361300d565b9150614eca82614e63565b604082019050919050565b60006020820190508181036000830152614eee81614eb2565b9050919050565b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b6000614f5160358361300d565b9150614f5c82614ef5565b604082019050919050565b60006020820190508181036000830152614f8081614f44565b9050919050565b6000608082019050614f9c6000830187613152565b614fa96020830186613152565b614fb660408301856131e8565b8181036060830152614fc881846147af565b905095945050505050565b600081519050614fe281612f73565b92915050565b600060208284031215614ffe57614ffd612f3d565b5b600061500c84828501614fd3565b91505092915050565b6000615020826130bd565b915061502b836130bd565b92508282101561503e5761503d6149de565b5b828203905092915050565b6000615054826130bd565b915061505f836130bd565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115615094576150936149de565b5b828201905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b600061510460208361300d565b915061510f826150ce565b602082019050919050565b60006020820190508181036000830152615133816150f7565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615170601c8361300d565b915061517b8261513a565b602082019050919050565b6000602082019050818103600083015261519f81615163565b905091905056fea2646970667358221220e60a118b265bffa0bee1156a3c15658b87605c5886ba72a04c6b3be6591e04c964736f6c634300080e0033000000000000000000000000074a8fa105bf658bde876c47d65999ea9622d1ee00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003ffffff000000000000000000000000000000000000000000000000000000000035a98e00000000000000000000000000000000000000000000000000000000005f5fbc0000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061018d5760003560e01c806378a7ee6b116100d7578063b88d4fde11610085578063b88d4fde146105cf578063c6903b4d146105f8578063c87b56dd14610623578063d0ebdbe714610660578063e0347e1c14610689578063e8801de0146106b4578063e985e9c5146106dd578063f0329f6b1461071a5761018d565b806378a7ee6b1461048f5780637e114c0e146104cc578063899e42f9146104fc57806395d89b4114610527578063a22cb46514610552578063a2ac63351461057b578063aede32f4146105a65761018d565b80632f745c591161013f5780632f745c59146102df57806335c04b841461031c57806336e69514146103595780634046f91a1461038457806342842e0e146103af5780634f6ccce7146103d85780636352211e1461041557806370a08231146104525761018d565b806301ffc9a71461019257806306fdde03146101cf578063081812fc146101fa578063095ea7b31461023757806318160ddd1461026057806323b872dd1461028b57806325ba071b146102b4575b600080fd5b34801561019e57600080fd5b506101b960048036038101906101b49190612f9f565b610745565b6040516101c69190612fe7565b60405180910390f35b3480156101db57600080fd5b506101e46107bf565b6040516101f1919061309b565b60405180910390f35b34801561020657600080fd5b50610221600480360381019061021c91906130f3565b610851565b60405161022e9190613161565b60405180910390f35b34801561024357600080fd5b5061025e600480360381019061025991906131a8565b610897565b005b34801561026c57600080fd5b506102756109ae565b60405161028291906131f7565b60405180910390f35b34801561029757600080fd5b506102b260048036038101906102ad9190613212565b6109bb565b005b3480156102c057600080fd5b506102c9610a1b565b6040516102d69190612fe7565b60405180910390f35b3480156102eb57600080fd5b50610306600480360381019061030191906131a8565b610a2e565b60405161031391906131f7565b60405180910390f35b34801561032857600080fd5b50610343600480360381019061033e91906130f3565b610ad3565b604051610350919061309b565b60405180910390f35b34801561036557600080fd5b5061036e610bce565b60405161037b9190612fe7565b60405180910390f35b34801561039057600080fd5b50610399610bdf565b6040516103a69190613161565b60405180910390f35b3480156103bb57600080fd5b506103d660048036038101906103d19190613212565b610c05565b005b3480156103e457600080fd5b506103ff60048036038101906103fa91906130f3565b610c25565b60405161040c91906131f7565b60405180910390f35b34801561042157600080fd5b5061043c600480360381019061043791906130f3565b610c96565b6040516104499190613161565b60405180910390f35b34801561045e57600080fd5b5061047960048036038101906104749190613265565b610d1c565b60405161048691906131f7565b60405180910390f35b34801561049b57600080fd5b506104b660048036038101906104b191906130f3565b610dd3565b6040516104c391906132cd565b60405180910390f35b6104e660048036038101906104e19190613823565b610e0a565b6040516104f391906139fa565b60405180910390f35b34801561050857600080fd5b5061051161123c565b60405161051e9190613161565b60405180910390f35b34801561053357600080fd5b5061053c611262565b604051610549919061309b565b60405180910390f35b34801561055e57600080fd5b5061057960048036038101906105749190613a48565b6112f4565b005b34801561058757600080fd5b5061059061130a565b60405161059d9190613161565b60405180910390f35b3480156105b257600080fd5b506105cd60048036038101906105c89190613a88565b611330565b005b3480156105db57600080fd5b506105f660048036038101906105f19190613b13565b6114b1565b005b34801561060457600080fd5b5061060d611513565b60405161061a9190613161565b60405180910390f35b34801561062f57600080fd5b5061064a600480360381019061064591906130f3565b611539565b604051610657919061309b565b60405180910390f35b34801561066c57600080fd5b5061068760048036038101906106829190613265565b611610565b005b34801561069557600080fd5b5061069e6116e4565b6040516106ab9190613161565b60405180910390f35b3480156106c057600080fd5b506106db60048036038101906106d69190613b96565b61170a565b005b3480156106e957600080fd5b5061070460048036038101906106ff9190613c11565b611964565b6040516107119190612fe7565b60405180910390f35b34801561072657600080fd5b5061072f6119f8565b60405161073c9190613161565b60405180910390f35b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614806107b857506107b782611aa8565b5b9050919050565b6060600080546107ce90613c80565b80601f01602080910402602001604051908101604052809291908181526020018280546107fa90613c80565b80156108475780601f1061081c57610100808354040283529160200191610847565b820191906000526020600020905b81548152906001019060200180831161082a57829003601f168201915b5050505050905090565b600061085c82611b8a565b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006108a282610c96565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610912576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090990613d23565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610931611bd5565b73ffffffffffffffffffffffffffffffffffffffff161480610960575061095f8161095a611bd5565b611964565b5b61099f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099690613db5565b60405180910390fd5b6109a98383611bdd565b505050565b6000600880549050905090565b6109cc6109c6611bd5565b82611c96565b610a0b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0290613e47565b60405180910390fd5b610a16838383611d2b565b505050565b600e60009054906101000a900460ff1681565b6000610a3983610d1c565b8210610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613ed9565b60405180910390fd5b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b6060601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16633fb1f67d83601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600d6015600001601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040518663ffffffff1660e01b8152600401610b81959493929190614460565b600060405180830381865afa158015610b9e573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190610bc79190614531565b9050919050565b60148054906101000a900460ff1681565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610c20838383604051806020016040528060008152506114b1565b505050565b6000610c2f6109ae565b8210610c70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c67906145ec565b60405180910390fd5b60088281548110610c8457610c8361460c565b5b90600052602060002001549050919050565b600080610ca283612024565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610d13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0a90614687565b60405180910390fd5b80915050919050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610d8c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d8390614719565b60405180910390fd5b600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b600d8181548110610de357600080fd5b90600052602060002090600a9182820401919006600302915054906101000a900460e81b81565b6060610e14612061565b6000601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663dfcf048d8851876040518363ffffffff1660e01b8152600401610e74929190614739565b602060405180830381865afa158015610e91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb59190614777565b9050601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d952411f345a9033858c518b8a6040518863ffffffff1660e01b8152600401610f1e9594939291906147e8565b602060405180830381858988f1158015610f3c573d6000803e3d6000fd5b5050505050506040513d601f19601f82011682018060405250810190610f629190614857565b610fa1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f98906148d0565b60405180910390fd5b865167ffffffffffffffff811115610fbc57610fbb6132ed565b5b604051908082528060200260200182016040528015610fea5781602001602082028036833780820191505090505b50915060005b875181101561122857601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663035868b4601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a848151811061106d5761106c61460c565b5b60200260200101518a85815181106110885761108761460c565b5b60200260200101518986815181106110a3576110a261460c565b5b60200260200101516040518563ffffffff1660e01b81526004016110ca94939291906148ff565b60408051808303816000875af11580156110e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061110c9190614960565b508382815181106111205761111f61460c565b5b602002602001018181525050601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d7b1595c84838151811061117d5761117c61460c565b5b602002602001015133876040518463ffffffff1660e01b81526004016111a5939291906149a0565b600060405180830381600087803b1580156111bf57600080fd5b505af11580156111d3573d6000803e3d6000fd5b505050506112158982815181106111ed576111ec61460c565b5b60200260200101518483815181106112085761120761460c565b5b60200260200101516120b0565b808061122090614a0d565b915050610ff0565b50506112326120ce565b9695505050505050565b601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606001805461127190613c80565b80601f016020809104026020016040519081016040528092919081815260200182805461129d90613c80565b80156112ea5780601f106112bf576101008083540402835291602001916112ea565b820191906000526020600020905b8154815290600101906020018083116112cd57829003601f168201915b5050505050905090565b6113066112ff611bd5565b83836120d8565b5050565b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b611338612061565b60005b83518110156114a357600061136985838151811061135c5761135b61460c565b5b6020026020010151610c96565b90506113908583815181106113815761138061460c565b5b60200260200101513385612244565b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166340321e568684815181106113e1576113e061460c565b5b6020026020010151833388886040518663ffffffff1660e01b815260040161140d959493929190614a76565b6020604051808303816000875af115801561142c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114509190614857565b61148f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161148690614b1c565b60405180910390fd5b50808061149b90614a0d565b91505061133b565b506114ac6120ce565b505050565b6114c26114bc611bd5565b83611c96565b611501576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114f890613e47565b60405180910390fd5b61150d8484848461232c565b50505050565b601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663c4e9d84e83601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600d60156000016040518563ffffffff1660e01b81526004016115c39493929190614b3c565b600060405180830381865afa1580156115e0573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906116099190614531565b9050919050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161169790614bdb565b60405180910390fd5b80600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b601160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806117b35750600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6117f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e990614c47565b60405180910390fd5b60148054906101000a900460ff1615611840576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161183790614b1c565b60405180910390fd5b84601160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083601260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081601460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806014806101000a81548160ff0219169083151502179055505050505050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060806040519050835180825260208201818101602087015b81831015611a545780518352602083019250602081019050611a37565b50855192508351830184528091508282019050602086015b81831015611a895780518352602083019250602081019050611a6c565b50601f19601f8851850115830101166040525050508091505092915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480611b7357507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80611b835750611b8282612388565b5b9050919050565b611b93816123f2565b611bd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bc990614687565b60405180910390fd5b50565b600033905090565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16611c5083610c96565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600080611ca283610c96565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480611ce45750611ce38185611964565b5b80611d2257508373ffffffffffffffffffffffffffffffffffffffff16611d0a84610851565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16611d4b82610c96565b73ffffffffffffffffffffffffffffffffffffffff1614611da1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d9890614cd9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611e10576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e0790614d6b565b60405180910390fd5b611e1d8383836001612433565b8273ffffffffffffffffffffffffffffffffffffffff16611e3d82610c96565b73ffffffffffffffffffffffffffffffffffffffff1614611e93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8a90614cd9565b60405180910390fd5b6004600082815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461201f8383836001612591565b505050565b60006002600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6002600a54036120a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209d90614dd7565b60405180910390fd5b6002600a81905550565b6120ca828260405180602001604052806000815250612597565b5050565b6001600a81905550565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603612146576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213d90614e43565b60405180910390fd5b80600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31836040516122379190612fe7565b60405180910390a3505050565b61224e8284611c96565b61228d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161228490614c47565b60405180910390fd5b612296836125f2565b601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663d1503d148433846040518463ffffffff1660e01b81526004016122f5939291906149a0565b600060405180830381600087803b15801561230f57600080fd5b505af1158015612323573d6000803e3d6000fd5b50505050505050565b612337848484611d2b565b61234384848484612740565b612382576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237990614ed5565b60405180910390fd5b50505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60008073ffffffffffffffffffffffffffffffffffffffff1661241483612024565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b61243f848484846128c7565b6001811115612483576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161247a90614f67565b60405180910390fd5b6000829050600073ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff16036124ca576124c5816129ed565b612509565b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1614612508576125078582612a36565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff160361254b5761254681612ba3565b61258a565b8473ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614612589576125888482612c74565b5b5b5050505050565b50505050565b6125a18383612cf3565b6125ae6000848484612740565b6125ed576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125e490614ed5565b60405180910390fd5b505050565b60006125fd82610c96565b905061260d816000846001612433565b61261682610c96565b90506004600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff02191690556001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055506002600083815260200190815260200160002060006101000a81549073ffffffffffffffffffffffffffffffffffffffff021916905581600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a461273c816000846001612591565b5050565b60006127618473ffffffffffffffffffffffffffffffffffffffff16612f10565b156128ba578373ffffffffffffffffffffffffffffffffffffffff1663150b7a0261278a611bd5565b8786866040518563ffffffff1660e01b81526004016127ac9493929190614f87565b6020604051808303816000875af19250505080156127e857506040513d601f19601f820116820180604052508101906127e59190614fe8565b60015b61286a573d8060008114612818576040519150601f19603f3d011682016040523d82523d6000602084013e61281d565b606091505b506000815103612862576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161285990614ed5565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149150506128bf565b600190505b949350505050565b60018111156129e757600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461295b5780600360008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546129539190615015565b925050819055505b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146129e65780600360008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546129de9190615049565b925050819055505b5b50505050565b6008805490506009600083815260200190815260200160002081905550600881908060018154018082558091505060019003906000526020600020016000909190919091505550565b60006001612a4384610d1c565b612a4d9190615015565b9050600060076000848152602001908152602001600020549050818114612b32576000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816007600083815260200190815260200160002081905550505b6007600084815260200190815260200160002060009055600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600880549050612bb79190615015565b9050600060096000848152602001908152602001600020549050600060088381548110612be757612be661460c565b5b906000526020600020015490508060088381548110612c0957612c0861460c565b5b906000526020600020018190555081600960008381526020019081526020016000208190555060096000858152602001908152602001600020600090556008805480612c5857612c5761509f565b5b6001900381819060005260206000200160009055905550505050565b6000612c7f83610d1c565b905081600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806007600084815260200190815260200160002081905550505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603612d62576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d599061511a565b60405180910390fd5b612d6b816123f2565b15612dab576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612da290615186565b60405180910390fd5b612db9600083836001612433565b612dc2816123f2565b15612e02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612df990615186565b60405180910390fd5b6001600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550816002600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4612f0c600083836001612591565b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b612f7c81612f47565b8114612f8757600080fd5b50565b600081359050612f9981612f73565b92915050565b600060208284031215612fb557612fb4612f3d565b5b6000612fc384828501612f8a565b91505092915050565b60008115159050919050565b612fe181612fcc565b82525050565b6000602082019050612ffc6000830184612fd8565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561303c578082015181840152602081019050613021565b8381111561304b576000848401525b50505050565b6000601f19601f8301169050919050565b600061306d82613002565b613077818561300d565b935061308781856020860161301e565b61309081613051565b840191505092915050565b600060208201905081810360008301526130b58184613062565b905092915050565b6000819050919050565b6130d0816130bd565b81146130db57600080fd5b50565b6000813590506130ed816130c7565b92915050565b60006020828403121561310957613108612f3d565b5b6000613117848285016130de565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061314b82613120565b9050919050565b61315b81613140565b82525050565b60006020820190506131766000830184613152565b92915050565b61318581613140565b811461319057600080fd5b50565b6000813590506131a28161317c565b92915050565b600080604083850312156131bf576131be612f3d565b5b60006131cd85828601613193565b92505060206131de858286016130de565b9150509250929050565b6131f1816130bd565b82525050565b600060208201905061320c60008301846131e8565b92915050565b60008060006060848603121561322b5761322a612f3d565b5b600061323986828701613193565b935050602061324a86828701613193565b925050604061325b868287016130de565b9150509250925092565b60006020828403121561327b5761327a612f3d565b5b600061328984828501613193565b91505092915050565b60007fffffff000000000000000000000000000000000000000000000000000000000082169050919050565b6132c781613292565b82525050565b60006020820190506132e260008301846132be565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61332582613051565b810181811067ffffffffffffffff82111715613344576133436132ed565b5b80604052505050565b6000613357612f33565b9050613363828261331c565b919050565b600067ffffffffffffffff821115613383576133826132ed565b5b602082029050602081019050919050565b600080fd5b60006133ac6133a784613368565b61334d565b905080838252602082019050602084028301858111156133cf576133ce613394565b5b835b818110156133f857806133e48882613193565b8452602084019350506020810190506133d1565b5050509392505050565b600082601f830112613417576134166132e8565b5b8135613427848260208601613399565b91505092915050565b600067ffffffffffffffff82111561344b5761344a6132ed565b5b602082029050602081019050919050565b6000819050919050565b61346f8161345c565b811461347a57600080fd5b50565b60008135905061348c81613466565b92915050565b60006134a56134a084613430565b61334d565b905080838252602082019050602084028301858111156134c8576134c7613394565b5b835b818110156134f157806134dd888261347d565b8452602084019350506020810190506134ca565b5050509392505050565b600082601f8301126135105761350f6132e8565b5b8135613520848260208601613492565b91505092915050565b600067ffffffffffffffff821115613544576135436132ed565b5b602082029050602081019050919050565b600061356861356384613529565b61334d565b9050808382526020820190506020840283018581111561358b5761358a613394565b5b835b818110156135b457806135a088826130de565b84526020840193505060208101905061358d565b5050509392505050565b600082601f8301126135d3576135d26132e8565b5b81356135e3848260208601613555565b91505092915050565b600067ffffffffffffffff821115613607576136066132ed565b5b602082029050602081019050919050565b600080fd5b600067ffffffffffffffff821115613638576136376132ed565b5b61364182613051565b9050602081019050919050565b82818337600083830152505050565b600061367061366b8461361d565b61334d565b90508281526020810184848401111561368c5761368b613618565b5b61369784828561364e565b509392505050565b600082601f8301126136b4576136b36132e8565b5b81356136c484826020860161365d565b91505092915050565b60006136e06136db846135ec565b61334d565b9050808382526020820190506020840283018581111561370357613702613394565b5b835b8181101561374a57803567ffffffffffffffff811115613728576137276132e8565b5b808601613735898261369f565b85526020850194505050602081019050613705565b5050509392505050565b600082601f830112613769576137686132e8565b5b81356137798482602086016136cd565b91505092915050565b600067ffffffffffffffff82111561379d5761379c6132ed565b5b6137a682613051565b9050602081019050919050565b60006137c66137c184613782565b61334d565b9050828152602081018484840111156137e2576137e1613618565b5b6137ed84828561364e565b509392505050565b600082601f83011261380a576138096132e8565b5b813561381a8482602086016137b3565b91505092915050565b60008060008060008060c087890312156138405761383f612f3d565b5b600087013567ffffffffffffffff81111561385e5761385d612f42565b5b61386a89828a01613402565b965050602087013567ffffffffffffffff81111561388b5761388a612f42565b5b61389789828a016134fb565b955050604087013567ffffffffffffffff8111156138b8576138b7612f42565b5b6138c489828a016135be565b94505060606138d589828a01613193565b935050608087013567ffffffffffffffff8111156138f6576138f5612f42565b5b61390289828a01613754565b92505060a087013567ffffffffffffffff81111561392357613922612f42565b5b61392f89828a016137f5565b9150509295509295509295565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b613971816130bd565b82525050565b60006139838383613968565b60208301905092915050565b6000602082019050919050565b60006139a78261393c565b6139b18185613947565b93506139bc83613958565b8060005b838110156139ed5781516139d48882613977565b97506139df8361398f565b9250506001810190506139c0565b5085935050505092915050565b60006020820190508181036000830152613a14818461399c565b905092915050565b613a2581612fcc565b8114613a3057600080fd5b50565b600081359050613a4281613a1c565b92915050565b60008060408385031215613a5f57613a5e612f3d565b5b6000613a6d85828601613193565b9250506020613a7e85828601613a33565b9150509250929050565b600080600060608486031215613aa157613aa0612f3d565b5b600084013567ffffffffffffffff811115613abf57613abe612f42565b5b613acb868287016135be565b9350506020613adc86828701613193565b925050604084013567ffffffffffffffff811115613afd57613afc612f42565b5b613b09868287016137f5565b9150509250925092565b60008060008060808587031215613b2d57613b2c612f3d565b5b6000613b3b87828801613193565b9450506020613b4c87828801613193565b9350506040613b5d878288016130de565b925050606085013567ffffffffffffffff811115613b7e57613b7d612f42565b5b613b8a878288016137f5565b91505092959194509250565b600080600080600060a08688031215613bb257613bb1612f3d565b5b6000613bc088828901613193565b9550506020613bd188828901613193565b9450506040613be288828901613193565b9350506060613bf388828901613193565b9250506080613c0488828901613a33565b9150509295509295909350565b60008060408385031215613c2857613c27612f3d565b5b6000613c3685828601613193565b9250506020613c4785828601613193565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680613c9857607f821691505b602082108103613cab57613caa613c51565b5b50919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b6000613d0d60218361300d565b9150613d1882613cb1565b604082019050919050565b60006020820190508181036000830152613d3c81613d00565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60008201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000602082015250565b6000613d9f603d8361300d565b9150613daa82613d43565b604082019050919050565b60006020820190508181036000830152613dce81613d92565b9050919050565b7f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560008201527f72206f7220617070726f76656400000000000000000000000000000000000000602082015250565b6000613e31602d8361300d565b9150613e3c82613dd5565b604082019050919050565b60006020820190508181036000830152613e6081613e24565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b6000613ec3602b8361300d565b9150613ece82613e67565b604082019050919050565b60006020820190508181036000830152613ef281613eb6565b9050919050565b600081549050919050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b613f3381613292565b82525050565b60008160001c9050919050565b60008160e81b9050919050565b6000613f5e82613f46565b9050919050565b6000613f78613f7383613f39565b613f53565b9050919050565b60008160181c9050919050565b6000613f9f613f9a83613f7f565b613f53565b9050919050565b60008160301c9050919050565b6000613fc6613fc183613fa6565b613f53565b9050919050565b60008160481c9050919050565b6000613fed613fe883613fcd565b613f53565b9050919050565b60008160601c9050919050565b600061401461400f83613ff4565b613f53565b9050919050565b60008160781c9050919050565b600061403b6140368361401b565b613f53565b9050919050565b60008160901c9050919050565b600061406261405d83614042565b613f53565b9050919050565b60008160a81c9050919050565b600061408961408483614069565b613f53565b9050919050565b60008160c01c9050919050565b60006140b06140ab83614090565b613f53565b9050919050565b60008160d81c9050919050565b60006140d76140d2836140b7565b613f53565b9050919050565b60006140e982613ef9565b6140f38185613f04565b9350836140ff84613f15565b600060011561421c575b836001600a038201101561421b57815461412b8861412683613f65565b613f2a565b6020880197506141438861413e83613f8c565b613f2a565b60208801975061415b8861415683613fb3565b613f2a565b6020880197506141738861416e83613fda565b613f2a565b60208801975061418b8861418683614001565b613f2a565b6020880197506141a38861419e83614028565b613f2a565b6020880197506141bb886141b68361404f565b613f2a565b6020880197506141d3886141ce83614076565b613f2a565b6020880197506141eb886141e68361409d565b613f2a565b602088019750614203886141fe836140c4565b613f2a565b60208801975060018301925050600a81019050614109565b5b6001156143ad5781548482101561424c5761423f8861423a83613f65565b613f2a565b6020880197506001820191505b84821015614273576142668861426183613f8c565b613f2a565b6020880197506001820191505b8482101561429a5761428d8861428883613fb3565b613f2a565b6020880197506001820191505b848210156142c1576142b4886142af83613fda565b613f2a565b6020880197506001820191505b848210156142e8576142db886142d683614001565b613f2a565b6020880197506001820191505b8482101561430f57614302886142fd83614028565b613f2a565b6020880197506001820191505b8482101561433657614329886143248361404f565b613f2a565b6020880197506001820191505b8482101561435d576143508861434b83614076565b613f2a565b6020880197506001820191505b8482101561438457614377886143728361409d565b613f2a565b6020880197506001820191505b848210156143ab5761439e88614399836140c4565b613f2a565b6020880197506001820191505b505b8694505050505092915050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b600081546143ed81613c80565b6143f781866143ba565b94506001821660008114614412576001811461442457614457565b60ff1983168652602086019350614457565b61442d856143cb565b60005b8381101561444f57815481890152600182019150602081019050614430565b808801955050505b50505092915050565b600060a08201905061447560008301886131e8565b6144826020830187613152565b818103604083015261449481866140de565b905081810360608301526144a881856143e0565b90506144b76080830184613152565b9695505050505050565b60006144d46144cf8461361d565b61334d565b9050828152602081018484840111156144f0576144ef613618565b5b6144fb84828561301e565b509392505050565b600082601f830112614518576145176132e8565b5b81516145288482602086016144c1565b91505092915050565b60006020828403121561454757614546612f3d565b5b600082015167ffffffffffffffff81111561456557614564612f42565b5b61457184828501614503565b91505092915050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b60006145d6602c8361300d565b91506145e18261457a565b604082019050919050565b60006020820190508181036000830152614605816145c9565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4552433732313a20696e76616c696420746f6b656e2049440000000000000000600082015250565b600061467160188361300d565b915061467c8261463b565b602082019050919050565b600060208201905081810360008301526146a081614664565b9050919050565b7f4552433732313a2061646472657373207a65726f206973206e6f74206120766160008201527f6c6964206f776e65720000000000000000000000000000000000000000000000602082015250565b600061470360298361300d565b915061470e826146a7565b604082019050919050565b60006020820190508181036000830152614732816146f6565b9050919050565b600060408201905061474e60008301856131e8565b61475b6020830184613152565b9392505050565b600081519050614771816130c7565b92915050565b60006020828403121561478d5761478c612f3d565b5b600061479b84828501614762565b91505092915050565b600081519050919050565b60006147ba826147a4565b6147c481856143ba565b93506147d481856020860161301e565b6147dd81613051565b840191505092915050565b600060a0820190506147fd6000830188613152565b61480a60208301876131e8565b61481760408301866131e8565b6148246060830185613152565b818103608083015261483681846147af565b90509695505050505050565b60008151905061485181613a1c565b92915050565b60006020828403121561486d5761486c612f3d565b5b600061487b84828501614842565b91505092915050565b7f7500000000000000000000000000000000000000000000000000000000000000600082015250565b60006148ba60018361300d565b91506148c582614884565b602082019050919050565b600060208201905081810360008301526148e9816148ad565b9050919050565b6148f98161345c565b82525050565b60006080820190506149146000830187613152565b61492160208301866148f0565b61492e60408301856131e8565b81810360608301526149408184613062565b905095945050505050565b60008151905061495a81613466565b92915050565b6000806040838503121561497757614976612f3d565b5b600061498585828601614762565b92505060206149968582860161494b565b9150509250929050565b60006060820190506149b560008301866131e8565b6149c26020830185613152565b81810360408301526149d481846147af565b9050949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000614a18826130bd565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614a4a57614a496149de565b5b600182019050919050565b6000614a6082613120565b9050919050565b614a7081614a55565b82525050565b600060a082019050614a8b60008301886131e8565b614a986020830187613152565b614aa56040830186614a67565b614ab26060830185613152565b8181036080830152614ac481846147af565b90509695505050505050565b7f6600000000000000000000000000000000000000000000000000000000000000600082015250565b6000614b0660018361300d565b9150614b1182614ad0565b602082019050919050565b60006020820190508181036000830152614b3581614af9565b9050919050565b6000608082019050614b5160008301876131e8565b614b5e6020830186613152565b8181036040830152614b7081856140de565b90508181036060830152614b8481846143e0565b905095945050505050565b7f6d00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614bc560018361300d565b9150614bd082614b8f565b602082019050919050565b60006020820190508181036000830152614bf481614bb8565b9050919050565b7f6100000000000000000000000000000000000000000000000000000000000000600082015250565b6000614c3160018361300d565b9150614c3c82614bfb565b602082019050919050565b60006020820190508181036000830152614c6081614c24565b9050919050565b7f4552433732313a207472616e736665722066726f6d20696e636f72726563742060008201527f6f776e6572000000000000000000000000000000000000000000000000000000602082015250565b6000614cc360258361300d565b9150614cce82614c67565b604082019050919050565b60006020820190508181036000830152614cf281614cb6565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b6000614d5560248361300d565b9150614d6082614cf9565b604082019050919050565b60006020820190508181036000830152614d8481614d48565b9050919050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614dc1601f8361300d565b9150614dcc82614d8b565b602082019050919050565b60006020820190508181036000830152614df081614db4565b9050919050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614e2d60198361300d565b9150614e3882614df7565b602082019050919050565b60006020820190508181036000830152614e5c81614e20565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000614ebf60328361300d565b9150614eca82614e63565b604082019050919050565b60006020820190508181036000830152614eee81614eb2565b9050919050565b7f455243373231456e756d657261626c653a20636f6e736563757469766520747260008201527f616e7366657273206e6f7420737570706f727465640000000000000000000000602082015250565b6000614f5160358361300d565b9150614f5c82614ef5565b604082019050919050565b60006020820190508181036000830152614f8081614f44565b9050919050565b6000608082019050614f9c6000830187613152565b614fa96020830186613152565b614fb660408301856131e8565b8181036060830152614fc881846147af565b905095945050505050565b600081519050614fe281612f73565b92915050565b600060208284031215614ffe57614ffd612f3d565b5b600061500c84828501614fd3565b91505092915050565b6000615020826130bd565b915061502b836130bd565b92508282101561503e5761503d6149de565b5b828203905092915050565b6000615054826130bd565b915061505f836130bd565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115615094576150936149de565b5b828201905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b600061510460208361300d565b915061510f826150ce565b602082019050919050565b60006020820190508181036000830152615133816150f7565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615170601c8361300d565b915061517b8261513a565b602082019050919050565b6000602082019050818103600083015261519f81615163565b905091905056fea2646970667358221220e60a118b265bffa0bee1156a3c15658b87605c5886ba72a04c6b3be6591e04c964736f6c634300080e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000074a8fa105bf658bde876c47d65999ea9622d1ee00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000003ffffff000000000000000000000000000000000000000000000000000000000035a98e00000000000000000000000000000000000000000000000000000000005f5fbc0000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : manager_ (address): 0x074a8fa105Bf658BDE876C47D65999ea9622d1ee
Arg [1] : colors_ (bytes3[]): System.Byte[],System.Byte[],System.Byte[]
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000074a8fa105bf658bde876c47d65999ea9622d1ee
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [3] : ffffff0000000000000000000000000000000000000000000000000000000000
Arg [4] : 35a98e0000000000000000000000000000000000000000000000000000000000
Arg [5] : 5f5fbc0000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.