ERC-721
Overview
Max Total Supply
31 8==D~
Holders
22
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
2 8==D~Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
ChainPhallus
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-01-23 */ // File: contracts/ChainPhallusErrors.sol pragma solidity 0.8.7; // Sale error SaleNotOpen(); error NotPreSaleStage(); error NotMainSaleStage(); error SaleNotComplete(); error MainSaleNotComplete(); error AlreadyClaimed(); error InvalidClaimValue(); error InvalidClaimAmount(); error InvalidProof(); error InvalidMintValue(); // NFT error NonExistentToken(); // Reveal error InvalidReveal(); error BalanceNotWithdrawn(); error BalanceAlreadyWithdrawn(); // Arena error LeavingProhibited(); error ArenaIsActive(); error ArenaNotActive(); error ArenaEntryClosed(); error WienersNotFluffy(); error WienersAreFluffy(); error LastErectWiener(); error GameOver(); error InvalidJoinCount(); error NotYourWiener(); // File: @openzeppelin/[email protected]/utils/cryptography/MerkleProof.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.0; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The proofs can be generated using the JavaScript library * https://github.com/miguelmota/merkletreejs[merkletreejs]. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled. * * See `test/utils/cryptography/MerkleProof.test.js` for some examples. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify( bytes32[] memory proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata( bytes32[] calldata proof, bytes32 root, bytes32 leaf ) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be proved to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and the sibling nodes in `proof`, * consuming from one or the other at each step according to the instructions given by * `proofFlags`. * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof} * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuild the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value for the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { return hashes[totalHashes - 1]; } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } } // File: @openzeppelin/[email protected]/utils/Strings.sol // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { // Inspired by OraclizeAPI's implementation - MIT licence // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol if (value == 0) { return "0"; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return "0x00"; } uint256 temp = value; uint256 length = 0; while (temp != 0) { length++; temp >>= 8; } return toHexString(value, length); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _HEX_SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } } // File: contracts/ChainPhallusRenderer.sol pragma solidity 0.8.7; contract ChainPhallusRenderer { using Strings for uint256; // Rendering constants string[13] public ballsArray = [unicode"8", unicode"ō", unicode"B", unicode"₿", unicode"β", unicode"З", unicode"$", unicode"𑂈", unicode"𐋀", unicode"Ӡ", unicode"θ", unicode"Ƀ", unicode"Ѯ"]; string[21] public shaft1Array = [unicode"=", unicode"Ξ", unicode"⇔", unicode"⁐", unicode"÷", unicode"—", unicode"+", unicode"‡", unicode"∺", unicode"ǂ", unicode"―", unicode"–", unicode"∷", unicode"⋍", unicode"⇌", unicode"⎓", unicode"⟾", unicode"⏔", unicode"⏕", unicode"≂", unicode"≃"]; string[21] public shaft2Array = [unicode"=", unicode"Ξ", unicode"⇔", unicode"⁐", unicode"÷", unicode"—", unicode"+", unicode"‡", unicode"∺", unicode"ǂ", unicode"―", unicode"–", unicode"∷", unicode"⋍", unicode"⇌", unicode"⎓", unicode"⟾", unicode"⏔", unicode"⏕", unicode"≂", unicode"≃"]; string[19] public headArray = [unicode"D", unicode"Ͽ", unicode"Ͻ", unicode"Đ", unicode"Э", unicode">", unicode"Ӭ", unicode"O", unicode"∋", unicode"Ӛ", unicode"Ә", unicode"»", unicode"Ѳ", unicode"Ӫ", unicode"Θ", unicode"Ɗ", unicode"Ø", unicode"Þ", unicode"⊃"]; string[11] public jizzArray = [unicode"~", unicode"—", unicode"–", unicode"―", unicode"¬", unicode"⌐", unicode"⁊", unicode"√", unicode"ᜯ", unicode"ᜰ", unicode"∖"]; uint256[21] rarityArray = [0, 2, 5, 9, 14, 20, 27, 35, 44, 54, 65, 77, 90, 104, 119, 135, 152, 170, 189, 209, 230]; // , 252]; uint256[10][] ancients; // Mapping to determine pulledOut status for the metadata mapping(uint256 => bool) public pulledOut; // Mapping to determine champion status for the metadata mapping(uint256 => bool) public wienerOfWieners; constructor() { ancients.push([0, 0, 0, 0, 0]); ancients.push([1, 1, 1, 1, 1]); ancients.push([2, 2, 2, 2, 2]); ancients.push([3, 3, 3, 3, 3]); ancients.push([4, 4, 4, 4, 4]); ancients.push([5, 5, 5, 5, 5]); ancients.push([6, 6, 6, 6, 6]); ancients.push([7, 7, 7, 7, 7]); ancients.push([8, 8, 8, 8, 8]); ancients.push([9, 9, 9, 9, 9]); } // Get ChainPhallus address address _chainPhallusAddress; function receiveChainPhallusAddress(address chainPhallusAddress) public { _chainPhallusAddress = chainPhallusAddress; } // TODO: modify selectors and symmetry calculation function getBalls(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return ballsArray[ancients[id][0]]; } uint256 raritySelector = seed % 104; uint256 charSelector = 0; for (uint i = 0; i < 13; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return ballsArray[charSelector]; } function getShaft1(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return shaft1Array[ancients[id][1]]; } uint256 raritySelector = seed % 252; uint256 charSelector = 0; for (uint i = 0; i < 21; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return shaft1Array[charSelector]; } function getShaft2(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return shaft2Array[ancients[id][2]]; } uint256 raritySelector = uint256(keccak256(abi.encodePacked(seed))) % 252; uint256 charSelector = 0; for (uint i = 0; i < 21; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return shaft2Array[charSelector]; } function getHead(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return headArray[ancients[id][3]]; } uint256 raritySelector = seed % 209; uint256 charSelector = 0; for (uint i = 0; i < 19; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return headArray[charSelector]; } function getJizz(uint256 id, uint256 seed) public view returns (string memory) { if (id < ancients.length) { return jizzArray[ancients[id][4]]; } uint256 raritySelector = seed % 77; uint256 charSelector = 0; for (uint i = 0; i < 11; i++) { if (raritySelector >= rarityArray[i]) { charSelector = i; } } return jizzArray[charSelector]; } function setPulledOutStatus(uint256 id) external { pulledOut[id] = true; } function setWienerOfWienersStatus(uint256 id) external { wienerOfWieners[id] = true; } function getStatus(uint256 id, address owner) public view returns (string memory) { if (owner == _chainPhallusAddress) { return "Swingin\'"; } if (pulledOut[id]) { return "Pulled out"; } if (wienerOfWieners[id]) { return "Wiener"; } return "Virgin"; } function assemblePhallus(bool revealComplete, uint256 id, uint256 seed) public view returns (string memory phallus) { if (!revealComplete) { return '8==D~'; } return string(abi.encodePacked( getBalls(id, seed), getShaft1(id, seed), getShaft2(id, seed), getHead(id, seed), getJizz(id, seed) )); } function calculateGolfScore(uint256 id, uint256 seed) public view returns (uint256) { if (id < ancients.length) { return 0; } uint256 ballsRarity = seed % 104; uint256 shaft1Rarity = seed % 252; uint256 shaft2Rarity = uint256(keccak256(abi.encodePacked(seed))) % 252; uint256 headRarity = seed % 209; uint256 jizzRarity = seed % 77; uint256 ballsGolf = 0; uint256 shaft1Golf = 0; uint256 shaft2Golf = 0; uint256 headGolf = 0; uint256 jizzGolf = 0; uint256 i = 0; for (i = 0; i < 13; i++) { if (ballsRarity >= rarityArray[i]) { ballsGolf = i; } } for (i = 0; i < 21; i++) { if (shaft1Rarity >= rarityArray[i]) { shaft1Golf = i; } } for (i = 0; i < 21; i++) { if (shaft2Rarity >= rarityArray[i]) { shaft2Golf = i; } } for (i = 0; i < 19; i++) { if (headRarity >= rarityArray[i]) { headGolf = i; } } for (i = 0; i < 11; i++) { if (jizzRarity >= rarityArray[i]) { jizzGolf = i; } } return ballsGolf + shaft1Golf + shaft2Golf + headGolf + jizzGolf; } function calculateSymmetry(uint256 id, uint256 seed) public view returns (string memory) { uint256 symCount = 0; if (id < ancients.length) { symCount = 1; } else { uint256 shaft1Rarity = seed % 252; uint256 shaft2Rarity = uint256(keccak256(abi.encodePacked(seed))) % 252; uint256 shaft1Index = 0; uint256 shaft2Index = 0; uint256 i = 0; for (i = 0; i < 21; i++) { if (shaft1Rarity >= rarityArray[i]) { shaft1Index = i; } } for (i = 0; i < 21; i++) { if (shaft2Rarity >= rarityArray[i]) { shaft2Index = i; } } if (shaft1Index == shaft2Index) { symCount = 1; } } if (symCount == 1) { return "Perfect Shaft"; } else { return "Crooked Shaft"; } } function getTextColor(uint256 id) public view returns (string memory) { if (id < ancients.length) { return 'RGB(148,256,209)'; } else { return 'RGB(0,0,0)'; } } function getBackgroundColor(uint256 id, uint256 seed) public view returns (string memory){ if (id < ancients.length) { return 'RGB(128,128,128)'; } uint256 golf = calculateGolfScore(id, seed); uint256 red; uint256 green; uint256 blue; if (golf >= 56) { red = 255; green = 255; blue = 255 - (golf - 56) * 4; } else { red = 255 - (56 - golf) * 4; green = 255 - (56 - golf) * 4; blue = 255; } return string(abi.encodePacked("RGB(", red.toString(), ",", green.toString(), ",", blue.toString(), ")")); } string constant headerText = 'data:application/json;ascii,{"description": "ChainPhallus Arena; where you go sword to sword until you are crowned the wiener.","image":"data:image/svg+xml;base64,'; string constant attributesText = '","attributes":[{"trait_type":"Golf Score","value":'; string constant symmetryText = '},{"trait_type":"Shaft","value":"'; string constant ballsText = '"},{"trait_type":"Balls","value":"'; string constant shaft1Text = '"},{"trait_type":"Lower Shaft","value":"'; string constant shaft2Text = '"},{"trait_type":"Upper Shaft","value":"'; string constant headText = '"},{"trait_type":"Head","value":"'; string constant jizzText = '"},{"trait_type":"Jizz","value":"'; string constant statusText = '"},{"trait_type":"Status","value":"'; string constant arenaDurationText = '"},{"trait_type":"Arena Score","value":'; string constant ancientText = '},{"trait_type":"Ancient","value":"'; string constant footerText = '"}]}'; function renderMetadata(bool revealComplete, uint256 id, uint256 seed, uint256 arenaDuration, address owner) external view returns (string memory) { if (!revealComplete) { return preRevealMetadata(); } uint256 golfScore = calculateGolfScore(id, seed); string memory svg = b64Encode(bytes(renderSvg(true, id, seed, arenaDuration, owner))); string memory attributes = string(abi.encodePacked(attributesText, golfScore.toString())); attributes = string(abi.encodePacked(attributes, symmetryText, calculateSymmetry(id, seed))); attributes = string(abi.encodePacked(attributes, ballsText, getBalls(id, seed))); attributes = string(abi.encodePacked(attributes, shaft1Text, getShaft1(id, seed))); attributes = string(abi.encodePacked(attributes, shaft2Text, getShaft2(id, seed))); attributes = string(abi.encodePacked(attributes, headText, getHead(id, seed))); attributes = string(abi.encodePacked(attributes, jizzText, getJizz(id, seed))); attributes = string(abi.encodePacked(attributes, statusText, getStatus(id, owner))); attributes = string(abi.encodePacked(attributes, arenaDurationText, arenaDuration.toString())); if (id < ancients.length) { attributes = string(abi.encodePacked(attributes, ancientText, 'Ancient')); } else { attributes = string(abi.encodePacked(attributes, ancientText, 'Not Ancient')); } attributes = string(abi.encodePacked(attributes, footerText)); return string(abi.encodePacked(headerText, svg, attributes)); } string constant svg1 = "<svg xmlns='http://www.w3.org/2000/svg' width='400' height='400' style='background-color:"; string constant svg2 = "'> <filter id='noise'> <feTurbulence type='turbulence' baseFrequency='0.0024' numOctaves='8' result='turbulence' /> <feDisplacementMap in='SourceGraphic' scale='42' /> </filter>"; string constant svg3 = "<text style='filter: url(#noise)' x='50%' y='50%' dominant-baseline='middle' text-anchor='middle' font-size='75px' fill='"; string constant svg4 = "'>"; string constant svg5 = "</text></svg>"; function renderSvg(bool revealComplete, uint256 id, uint256 seed, uint256 arenaDuration, address owner) public view returns (string memory) { if (!revealComplete) { return preRevealSvg(); } string memory phallus = assemblePhallus(true, id, seed); string memory pubes; if (arenaDuration > 0) { pubes = generatePubes(arenaDuration, seed); } return string(abi.encodePacked(svg1, getBackgroundColor(id, seed), svg2, pubes, svg3, getTextColor(id), svg4, phallus, svg5)); } string constant pubeSymbol = "<symbol id='pube'><g stroke='RGBA(0,0,0,1)'><text x='40' y='40' dominant-baseline='middle' text-anchor='middle' font-weight='normal' font-size='36px' fill='RGBA(0,0,0,1)'>Ҩ</text></g></symbol>"; string constant pubePlacement1 = "<g transform='translate("; string constant pubePlacement2 = ") scale("; string constant pubePlacement3 = ") rotate("; string constant pubePlacement4 = ")'><use href='#pube'/></g>"; function generatePubes(uint256 arenaDuration, uint256 seed) internal pure returns (string memory) { string memory pubes; string memory pubesTemp; uint256 count = arenaDuration / 10; if (count > 500) { count = 500; } for (uint256 i = 0; i < count; i++) { string memory pube; uint256 pubeSeed = uint256(keccak256(abi.encodePacked(seed, i))); uint256 scale1 = pubeSeed % 2; uint256 scale2 = pubeSeed % 5; if (scale1 == 0) { scale2 += 5; } uint256 xShift = pubeSeed % 332; uint256 yShift = pubeSeed % 354; int256 rotate = int256(pubeSeed % 91) - 45; pube = string(abi.encodePacked(pube, pubePlacement1, xShift.toString(), " ", yShift.toString(), pubePlacement2, scale1.toString(), ".", scale2.toString())); if (rotate >= 0) { pube = string(abi.encodePacked(pube, pubePlacement3, uint256(rotate).toString(), pubePlacement4)); } else { pube = string(abi.encodePacked(pube, pubePlacement3, "-", uint256(0 - rotate).toString(), pubePlacement4)); } pubesTemp = string(abi.encodePacked(pubesTemp, pube)); if (i % 10 == 0) { pubes = string(abi.encodePacked(pubes, pubesTemp)); pubesTemp = ""; } } return string(abi.encodePacked(pubeSymbol, pubes, pubesTemp)); } function preRevealMetadata() internal pure returns (string memory) { string memory JSON; string memory svg = preRevealSvg(); JSON = string(abi.encodePacked('data:application/json;ascii,{"description": "ChainPhallus Arena; where you go sword to sword until you are crowned the wiener.","image":"data:image/svg+xml;base64,', b64Encode(bytes(svg)), '"}')); return JSON; } function preRevealSvg() internal pure returns (string memory) { return "<svg xmlns='http://www.w3.org/2000/svg' width='400' height='400' style='background-color:RGB(255,255,255);'><text x='50%' y='50%' dominant-baseline='middle' text-anchor='middle' font-size='75px'>?????</text></svg>"; } string constant private TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; function b64Encode(bytes memory _data) internal pure returns (string memory result) { if (_data.length == 0) return ''; string memory _table = TABLE; uint256 _encodedLen = 4 * ((_data.length + 2) / 3); result = new string(_encodedLen + 32); assembly { mstore(result, _encodedLen) let tablePtr := add(_table, 1) let dataPtr := _data let endPtr := add(dataPtr, mload(_data)) let resultPtr := add(result, 32) for {} lt(dataPtr, endPtr) {} { dataPtr := add(dataPtr, 3) let input := mload(dataPtr) mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(18, input), 0x3F))))) resultPtr := add(resultPtr, 1) mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(12, input), 0x3F))))) resultPtr := add(resultPtr, 1) mstore(resultPtr, shl(248, mload(add(tablePtr, and(shr(6, input), 0x3F))))) resultPtr := add(resultPtr, 1) mstore(resultPtr, shl(248, mload(add(tablePtr, and(input, 0x3F))))) resultPtr := add(resultPtr, 1) } switch mod(mload(_data), 3) case 1 {mstore(sub(resultPtr, 2), shl(240, 0x3d3d))} case 2 {mstore(sub(resultPtr, 1), shl(248, 0x3d))} } return result; } } // File: @openzeppelin/[email protected]/utils/Context.sol // 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; } } // File: @openzeppelin/[email protected]/access/Ownable.sol // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: @openzeppelin/[email protected]/utils/Address.sol // OpenZeppelin Contracts (last updated v4.7.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 functionCall(target, data, "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"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(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) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason 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 { // 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); } } } } // File: @openzeppelin/[email protected]/token/ERC721/IERC721Receiver.sol // 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); } // File: @openzeppelin/[email protected]/utils/introspection/IERC165.sol // 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); } // File: @openzeppelin/[email protected]/utils/introspection/ERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; /** * @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; } } // File: @openzeppelin/[email protected]/token/ERC721/IERC721.sol // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; /** * @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: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * 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); } // File: @openzeppelin/[email protected]/token/ERC721/extensions/IERC721Enumerable.sol // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; /** * @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); } // File: @openzeppelin/[email protected]/token/ERC721/extensions/IERC721Metadata.sol // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; /** * @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); } // File: @openzeppelin/[email protected]/token/ERC721/ERC721.sol // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; /** * @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 = _owners[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 nor 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 nor 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 nor 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 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 _owners[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); _balances[to] += 1; _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId); // Clear approvals _approve(address(0), tokenId); _balances[owner] -= 1; delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId); } /** * @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); // Clear approvals from the previous owner _approve(address(0), tokenId); _balances[from] -= 1; _balances[to] += 1; _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId); } /** * @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. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} /** * @dev Hook that is called after any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 tokenId ) internal virtual {} } // File: @openzeppelin/[email protected]/token/ERC721/extensions/ERC721Enumerable.sol // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; /** * @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 Hook that is called before any token transfer. This includes minting * and burning. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. * - When `to` is zero, ``from``'s `tokenId` will be burned. * - `from` cannot be the zero address. * - `to` cannot be the zero address. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); 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(); } } // File: contracts/ChainPhallus.sol pragma solidity 0.8.7; contract ChainPhallus is ERC721, ERC721Enumerable, Ownable { /************************* COMMON *************************/ // Sale stage enum enum Stage { STAGE_COMPLETE, // 0 STAGE_PRESALE, // 1 STAGE_MAIN_SALE // 2 } bool balanceNotWithdrawn; constructor(uint256 _secretCommit, address _renderer, bytes32 _merkleRoot) ERC721("ChainPhallus Arena", unicode"8==D~") { // tokenLimit = _tokenLimit; secret = _secretCommit; merkleRoot = _merkleRoot; balanceNotWithdrawn = true; // Start in presale stage stage = Stage.STAGE_PRESALE; renderer = ChainPhallusRenderer(_renderer); // Send address to renderer renderer.receiveChainPhallusAddress(address(this)); // Mint ancients for (uint256 i = 0; i < 10;) { _createPhallus(); unchecked{ i++; } } } fallback() external payable {} /************************* TOKEN SALE *************************/ Stage public stage; uint256 public saleEnds; // Merkle distributor values bytes32 immutable merkleRoot; mapping(uint256 => uint256) private claimedBitMap; uint256 public constant saleLength = 69 hours; uint256 public constant salePrice = 0.025 ether; uint256 secret; // Entropy supplied by owner (commit/reveal style) uint256 userSecret; // Pseudorandom entropy provided by minters // -- MODIFIERS -- modifier onlyMainSaleOpen() { if (stage != Stage.STAGE_MAIN_SALE || mainSaleComplete()) { revert SaleNotOpen(); } _; } modifier onlyPreSale() { if (stage != Stage.STAGE_PRESALE) { revert NotPreSaleStage(); } _; } modifier onlyMainSale() { if (stage != Stage.STAGE_MAIN_SALE) { revert NotMainSaleStage(); } _; } modifier onlySaleComplete() { if (stage != Stage.STAGE_COMPLETE) { revert SaleNotComplete(); } _; } // -- VIEW METHODS -- function mainSaleComplete() public view returns (bool) { return block.timestamp >= saleEnds; // || totalSupply() == tokenLimit; } function isClaimed(uint256 index) public view returns (bool) { uint256 claimedWordIndex = index / 256; uint256 claimedBitIndex = index % 256; uint256 claimedWord = claimedBitMap[claimedWordIndex]; uint256 mask = (1 << claimedBitIndex); return claimedWord & mask == mask; } // -- OWNER METHODS -- // Reveal the wieners function theGreatReveal(uint256 _secretReveal) external onlyOwner onlyMainSale { if (!mainSaleComplete()) { revert MainSaleNotComplete(); } if (uint256(keccak256(abi.encodePacked(_secretReveal))) != secret) { revert InvalidReveal(); } // Final secret is XOR between the pre-committed secret and the pseudo-random user contributed salt secret = _secretReveal ^ userSecret; // Won't be needing this anymore delete userSecret; stage = Stage.STAGE_COMPLETE; } // Start main sale function startMainSale() external onlyOwner onlyPreSale { stage = Stage.STAGE_MAIN_SALE; saleEnds = block.timestamp + saleLength; } // Withdraw sale proceeds function withdraw() external onlyOwner { // Owner can't reneg on bounty if (arenaActive()) { revert ArenaIsActive(); } // Can only withdraw once, and only a fixed percentage if (!balanceNotWithdrawn) { revert BalanceAlreadyWithdrawn(); } balanceNotWithdrawn = false; owner().call{value : address(this).balance * 3058 / 10000}(""); } // -- USER METHODS -- function claim(uint256 _index, uint256 _ogAmount, uint256 _wlAmount, bytes32[] calldata _merkleProof, uint256 _amount) external payable onlyPreSale { // Ensure not already claimed if (isClaimed(_index)) { revert AlreadyClaimed(); } // Prevent accidental claim of 0 if (_amount == 0) { revert InvalidClaimAmount(); } // Check claim amount uint256 total = _ogAmount + _wlAmount; if (_amount > total) { revert InvalidClaimAmount(); } // Check claim value uint256 paidClaims = 0; if (_amount > _ogAmount) { paidClaims = _amount - _ogAmount; } if (msg.value < paidClaims * salePrice) { revert InvalidClaimValue(); } // Verify the merkle proof bytes32 node = keccak256(abi.encodePacked(_index, msg.sender, _ogAmount, _wlAmount)); if (!MerkleProof.verify(_merkleProof, merkleRoot, node)) { revert InvalidProof(); } // Mark it claimed and mint _setClaimed(_index); for (uint256 i = 0; i < _amount; i++) { _createPhallus(); } _mix(); } // Mint wieners function createPhallus() external payable onlyMainSaleOpen { uint256 count = msg.value / salePrice; if (count == 0) { revert InvalidMintValue(); } else if (count > 20) { count = 20; } // Mint 'em for (uint256 i = 0; i < count;) { _createPhallus(); unchecked{ i++; } } _mix(); // Send any excess ETH back to the caller uint256 excess = msg.value - (salePrice * count); if (excess > 0) { (bool success,) = msg.sender.call{value : excess}(""); require(success); } } // -- INTERNAL METHODS -- function _setClaimed(uint256 index) internal { uint256 claimedWordIndex = index / 256; uint256 claimedBitIndex = index % 256; claimedBitMap[claimedWordIndex] = claimedBitMap[claimedWordIndex] | (1 << claimedBitIndex); } function _createPhallus() internal { uint256 tokenId = totalSupply(); _mint(msg.sender, tokenId); } function _mix() internal { // Add some pseudorandom value which will be mixed with the pre-committed secret unchecked { userSecret += uint256(blockhash(block.number - 1)); } } /************************* NFT *************************/ modifier onlyTokenExists(uint256 _id) { if (!_exists(_id)) { revert NonExistentToken(); } _; } ChainPhallusRenderer public renderer; // -- VIEW METHODS -- function assemblePhallus(uint256 _id) external view onlyTokenExists(_id) returns (string memory) { return renderer.assemblePhallus(stage == Stage.STAGE_COMPLETE, _id, getFinalizedSeed(_id)); } function tokenURI(uint256 _id) public view override onlyTokenExists(_id) returns (string memory) { return renderer.renderMetadata(stage == Stage.STAGE_COMPLETE, _id, getFinalizedSeed(_id), roundsSurvived[_id], ownerOf(_id)); } function renderSvg(uint256 _id) external view onlyTokenExists(_id) returns (string memory) { uint256 rounds; // If wiener is still in the arena, show them with correct amount of scars if (ownerOf(_id) == address(this)) { rounds = currentRound; } else { rounds = roundsSurvived[_id]; } return renderer.renderSvg(stage == Stage.STAGE_COMPLETE, _id, getFinalizedSeed(_id), rounds, ownerOf(_id)); } // -- INTERNAL METHODS -- function getFinalizedSeed(uint256 _tokenId) internal view returns (uint256) { return uint256(keccak256(abi.encodePacked(secret, _tokenId))); } /************************* ARENA *************************/ uint256 arenaOpenedBlock; uint256 wienersLastBust; uint256 champion; uint256 public currentRound = 0; uint256 public bustedNut = 0; uint256 public pulledOut = 0; uint256 public swingin = 0; uint256 public constant arenaWaitBlocks = 12600; uint256 public constant blocksPerRound = 42; mapping(uint256 => address) public wienerDepositor; mapping(uint256 => uint256) public roundsSurvived; // -- MODIFIERS -- modifier onlyOpenArena() { if (!entryOpen()) { revert ArenaEntryClosed(); } _; } // -- VIEW METHODS -- struct ArenaInfo { uint256 busted; uint256 swingin; uint256 pulledOut; uint256 currentRound; uint256 bounty; uint256 hardness; uint256 nextBust; uint256 champion; uint256 entryClosedBlock; bool horny; bool open; bool active; bool gameOver; } function arenaInfo() external view returns (ArenaInfo memory info) { info.busted = bustedNut; info.swingin = swingin; info.pulledOut = pulledOut; info.currentRound = currentRound; info.bounty = address(this).balance; info.hardness = howHornyAreTheWieners(); info.champion = champion; info.entryClosedBlock = entryClosedBlock(); if (!theWienersAreFluffy()) { info.nextBust = wienersLastBust + blocksPerRound - block.number; } info.horny = theWienersAreFluffy(); info.open = entryOpen(); info.active = arenaActive(); info.gameOver = block.number > info.entryClosedBlock && info.swingin <= 1; } // Return array of msg.senders remaining wieners function myWieners() external view returns (uint256[] memory) { return ownerWieners(msg.sender); } // Return array of owner's remaining wieners function ownerWieners(address _owner) public view returns (uint256[] memory) { address holdingAddress; holdingAddress = address(this); uint256 total = balanceOf(holdingAddress); uint256[] memory wieners = new uint256[](total); uint256 index = 0; for (uint256 i = 0; i < total; i++) { uint256 id = tokenOfOwnerByIndex(holdingAddress, i); if (wienerDepositor[id] == _owner) { wieners[index++] = id; } } assembly { mstore(wieners, index) } return wieners; } function arenaActive() public view returns (bool) { return arenaOpenedBlock > 0; } function entryOpen() public view returns (bool) { return arenaActive() && block.number < entryClosedBlock(); } function entryClosedBlock() public view returns (uint256) { return arenaOpenedBlock + arenaWaitBlocks; } function howHornyAreTheWieners() public view returns (uint256) { if (swingin == 0) { return 0; } uint256 hardness = 1; // Calculate how many wieners busted (0.2% of wieners > 1000) if (swingin >= 2000) { uint256 excess = swingin - 1000; hardness = excess / 500; } // The last wiener standing never busts if (hardness >= swingin) { hardness = swingin - 1; } // Generous upper bound to prevent gas overflow if (hardness > 50) { hardness = 50; } return hardness; } function theWienersAreFluffy() public view returns (bool) { return block.number >= wienersLastBust + blocksPerRound; } // -- OWNER METHODS -- function openArena() external payable onlyOwner onlySaleComplete { if (arenaActive()) { revert ArenaIsActive(); } if (balanceNotWithdrawn) { revert BalanceNotWithdrawn(); } // Open the arena arenaOpenedBlock = block.number; wienersLastBust = block.number + arenaWaitBlocks; } // -- USER METHODS -- // Can be called every `blocksPerRound` blocks to kill off some eager wieners function timeToBust() external { if (!arenaActive()) { revert ArenaNotActive(); } if (!theWienersAreFluffy()) { revert WienersNotFluffy(); } if (swingin == 1) { revert LastErectWiener(); } if (swingin == 0) { revert GameOver(); } // The blockhash of every `blocksPerRound` block is used to determine who busts uint256 entropyBlock; if (block.number - (wienersLastBust + blocksPerRound) > 255) { // If this method isn't called within 255 blocks of the period end, this is a fallback so we can still progress entropyBlock = (block.number / blocksPerRound) * blocksPerRound - 1; } else { // Use blockhash of every 42nd block entropyBlock = (wienersLastBust + blocksPerRound) - 1; } uint256 entropy = uint256(blockhash(entropyBlock)); assert(entropy != 0); // Update state wienersLastBust = block.number; currentRound++; // Kill off a percentage of wieners uint256 killCounter = howHornyAreTheWieners(); bytes memory buffer = new bytes(32); // i starts at 1 to prevent infinite loop for (uint256 i = 1; i <= killCounter;) { // Entropy must increase even if the kill doesn't count unchecked { entropy = entropy + i; } // Gas saving trick to avoid abi.encodePacked assembly { mstore(add(buffer, 32), entropy) } // Balance of contract in case tokens were transferred without joining uint256 whoDied = uint256(keccak256(buffer)) % balanceOf(address(this)); // Go to your happy place, loser uint256 wienerToBust = tokenOfOwnerByIndex(address(this), whoDied); _burn(wienerToBust); // Check to ensure that busted wiener was participating in the arena if (wienerDepositor[wienerToBust] == address(0)) { // If not participating, kill doesn't count unchecked{ --i; } } else { // If participating, update counts // Clear state delete wienerDepositor[wienerToBust]; bustedNut++; swingin--; } unchecked{ i++; } } // Record the champion if (swingin == 1) { // Check all tokens in contract until champion is found uint256 wienerToCheck; for (uint256 i = 0; i < balanceOf(address(this));) { wienerToCheck = tokenOfOwnerByIndex(address(this), i); if (wienerDepositor[wienerToCheck] != address(0)) { // If token was participating in arena it must the the champion champion = wienerToCheck; break; } unchecked{ i++; } } // Record the champion's achievement roundsSurvived[champion] = currentRound; // Set status renderer.setWienerOfWienersStatus(champion); // Pay the champion's owner and return wiener payable(wienerDepositor[champion]).transfer(address(this).balance); _transfer(address(this), wienerDepositor[champion], champion); } } function joinArena(uint256 _tokenId) external onlyOpenArena { _joinArena(_tokenId); } function multiJoinArena(uint256[] memory _tokenIds) external onlyOpenArena { if (_tokenIds.length > 20) { revert InvalidJoinCount(); } for (uint256 i; i < _tokenIds.length;) { _joinArena(_tokenIds[i]); unchecked{ i++; } } } function claimBounty(uint256 _tokenId) external { if (wienerDepositor[_tokenId] != msg.sender) { revert NotYourWiener(); } // Can't leave arena if wieners are horny (unless it's the champ and the game is over) if (swingin != 1 && theWienersAreFluffy()) { revert WienersAreFluffy(); } // Can't leave before a single round has passed uint256 round = currentRound; if (currentRound == 0) { revert LeavingProhibited(); } // Record the wiener's achievement roundsSurvived[_tokenId] = round; // Clear state delete wienerDepositor[_tokenId]; // Must burn NFT to claim bounty uint256 battleBounty = address(this).balance / swingin; _burn(_tokenId); bustedNut++; swingin--; payable(msg.sender).transfer(battleBounty); // If this was the second last wiener to leave, the last one left is the champ if (swingin == 1) { // Check all tokens in contract until champion is found uint256 wienerToCheck; for (uint256 i = 0; i < balanceOf(address(this));) { wienerToCheck = tokenOfOwnerByIndex(address(this), i); if (wienerDepositor[wienerToCheck] != address(0)) { // If token was participating in arena it must the the champion champion = wienerToCheck; break; } unchecked{ i++; } } // Record the champion's achievement roundsSurvived[champion] = round; // Set status renderer.setWienerOfWienersStatus(champion); // Pay the champion's owner and return wiener payable(wienerDepositor[champion]).transfer(address(this).balance); _transfer(address(this), wienerDepositor[champion], champion); } } function leaveArena(uint256 _tokenId) external { if (wienerDepositor[_tokenId] != msg.sender) { revert NotYourWiener(); } // Can't leave arena if wieners are horny (unless it's the champ and the game is over) if (swingin != 1 && theWienersAreFluffy()) { revert WienersAreFluffy(); } // Can't leave before a single round has passed uint256 round = currentRound; if (currentRound == 0) { revert LeavingProhibited(); } // Record the wiener's achievement roundsSurvived[_tokenId] = round; // Set status renderer.setPulledOutStatus(_tokenId); // Clear state delete wienerDepositor[_tokenId]; // Return wiener _transfer(address(this), msg.sender, _tokenId); pulledOut++; swingin--; // If this was the second last wiener to leave, the last one left is the champ if (swingin == 1) { // Check all tokens in contract until champion is found uint256 wienerToCheck; for (uint256 i = 0; i < balanceOf(address(this));) { wienerToCheck = tokenOfOwnerByIndex(address(this), i); if (wienerDepositor[wienerToCheck] != address(0)) { // If token was participating in arena it must the the champion champion = wienerToCheck; break; } unchecked{ i++; } } // Record the champion's achievement roundsSurvived[champion] = round; // Set status renderer.setWienerOfWienersStatus(champion); // Pay the champion's owner and return wiener payable(wienerDepositor[champion]).transfer(address(this).balance); _transfer(address(this), wienerDepositor[champion], champion); } } // -- INTERNAL METHODS -- function _joinArena(uint256 _tokenId) internal { // Send wiener to the arena transferFrom(msg.sender, address(this), _tokenId); wienerDepositor[_tokenId] = msg.sender; swingin++; } /************************* MISC *************************/ function onERC721Received(address, address, uint256, bytes memory) external pure returns (bytes4) { return this.onERC721Received.selector; } function _beforeTokenTransfer(address _from, address _to, uint256 _tokenId) internal override(ERC721, ERC721Enumerable) { super._beforeTokenTransfer(_from, _to, _tokenId); } function supportsInterface(bytes4 _interfaceId) public view virtual override(ERC721, ERC721Enumerable) returns (bool) { return super.supportsInterface(_interfaceId); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"uint256","name":"_secretCommit","type":"uint256"},{"internalType":"address","name":"_renderer","type":"address"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"ArenaEntryClosed","type":"error"},{"inputs":[],"name":"ArenaIsActive","type":"error"},{"inputs":[],"name":"ArenaNotActive","type":"error"},{"inputs":[],"name":"BalanceAlreadyWithdrawn","type":"error"},{"inputs":[],"name":"BalanceNotWithdrawn","type":"error"},{"inputs":[],"name":"GameOver","type":"error"},{"inputs":[],"name":"InvalidClaimAmount","type":"error"},{"inputs":[],"name":"InvalidClaimValue","type":"error"},{"inputs":[],"name":"InvalidJoinCount","type":"error"},{"inputs":[],"name":"InvalidMintValue","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidReveal","type":"error"},{"inputs":[],"name":"LastErectWiener","type":"error"},{"inputs":[],"name":"LeavingProhibited","type":"error"},{"inputs":[],"name":"MainSaleNotComplete","type":"error"},{"inputs":[],"name":"NonExistentToken","type":"error"},{"inputs":[],"name":"NotMainSaleStage","type":"error"},{"inputs":[],"name":"NotPreSaleStage","type":"error"},{"inputs":[],"name":"NotYourWiener","type":"error"},{"inputs":[],"name":"SaleNotComplete","type":"error"},{"inputs":[],"name":"SaleNotOpen","type":"error"},{"inputs":[],"name":"WienersAreFluffy","type":"error"},{"inputs":[],"name":"WienersNotFluffy","type":"error"},{"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":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"arenaActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"arenaInfo","outputs":[{"components":[{"internalType":"uint256","name":"busted","type":"uint256"},{"internalType":"uint256","name":"swingin","type":"uint256"},{"internalType":"uint256","name":"pulledOut","type":"uint256"},{"internalType":"uint256","name":"currentRound","type":"uint256"},{"internalType":"uint256","name":"bounty","type":"uint256"},{"internalType":"uint256","name":"hardness","type":"uint256"},{"internalType":"uint256","name":"nextBust","type":"uint256"},{"internalType":"uint256","name":"champion","type":"uint256"},{"internalType":"uint256","name":"entryClosedBlock","type":"uint256"},{"internalType":"bool","name":"horny","type":"bool"},{"internalType":"bool","name":"open","type":"bool"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bool","name":"gameOver","type":"bool"}],"internalType":"struct ChainPhallus.ArenaInfo","name":"info","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"arenaWaitBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"assemblePhallus","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blocksPerRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bustedNut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"uint256","name":"_ogAmount","type":"uint256"},{"internalType":"uint256","name":"_wlAmount","type":"uint256"},{"internalType":"bytes32[]","name":"_merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"claimBounty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createPhallus","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"currentRound","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"entryClosedBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"entryOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"howHornyAreTheWieners","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"uint256","name":"index","type":"uint256"}],"name":"isClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"joinArena","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"leaveArena","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mainSaleComplete","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"multiJoinArena","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"myWieners","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"openArena","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"_owner","type":"address"}],"name":"ownerWieners","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pulledOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"renderSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renderer","outputs":[{"internalType":"contract ChainPhallusRenderer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roundsSurvived","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":"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":[],"name":"saleEnds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"saleLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"salePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stage","outputs":[{"internalType":"enum ChainPhallus.Stage","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"startMainSale","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":"swingin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_secretReveal","type":"uint256"}],"name":"theGreatReveal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"theWienersAreFluffy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"timeToBust","outputs":[],"stateMutability":"nonpayable","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":"_id","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"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"wienerDepositor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60a060405260006013556000601455600060155560006016553480156200002557600080fd5b50604051620040ab380380620040ab833981016040819052620000489162000738565b6040805180820182526012815271436861696e5068616c6c7573204172656e6160701b6020808301918252835180850190945260058452641c1e9ea23f60d91b9084015281519192916200009f9160009162000692565b508051620000b590600190602084019062000692565b505050620000d2620000cc6200018c60201b60201c565b62000190565b600d8390556080819052600a805461010160a01b61ffff60a01b19909116179055600f80546001600160a01b0384166001600160a01b03199091168117909155604051631b45075f60e01b8152306004820152631b45075f90602401600060405180830381600087803b1580156200014957600080fd5b505af11580156200015e573d6000803e3d6000fd5b5050505060005b600a811015620001825762000179620001e2565b60010162000165565b5050505062000834565b3390565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000620001ee60085490565b9050620001fc3382620001ff565b50565b6001600160a01b0382166200025b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064015b60405180910390fd5b6000818152600260205260409020546001600160a01b031615620002c25760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640162000252565b620002d06000838362000359565b6001600160a01b0382166000908152600360205260408120805460019290620002fb90849062000780565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b620003718383836200037660201b620024561760201c565b505050565b6200038e8383836200037160201b62000bbd1760201c565b6001600160a01b038316620003ec57620003e681600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b62000412565b816001600160a01b0316836001600160a01b031614620004125762000412838262000452565b6001600160a01b0382166200042c576200037181620004ff565b826001600160a01b0316826001600160a01b0316146200037157620003718282620005b9565b600060016200046c846200060a60201b620015b21760201c565b6200047891906200079b565b600083815260076020526040902054909150808214620004cc576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b60085460009062000513906001906200079b565b600083815260096020526040812054600880549394509092849081106200053e576200053e6200081e565b9060005260206000200154905080600883815481106200056257620005626200081e565b60009182526020808320909101929092558281526009909152604080822084905585825281205560088054806200059d576200059d62000808565b6001900381819060005260206000200160009055905550505050565b6000620005d1836200060a60201b620015b21760201c565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b60006001600160a01b038216620006765760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840162000252565b506001600160a01b031660009081526003602052604090205490565b828054620006a090620007b5565b90600052602060002090601f016020900481019282620006c457600085556200070f565b82601f10620006df57805160ff19168380011785556200070f565b828001600101855582156200070f579182015b828111156200070f578251825591602001919060010190620006f2565b506200071d92915062000721565b5090565b5b808211156200071d576000815560010162000722565b6000806000606084860312156200074e57600080fd5b835160208501519093506001600160a01b03811681146200076e57600080fd5b80925050604084015190509250925092565b60008219821115620007965762000796620007f2565b500190565b600082821015620007b057620007b0620007f2565b500390565b600181811c90821680620007ca57607f821691505b60208210811415620007ec57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60805161385b620008506000396000611c48015261385b6000f3fe60806040526004361061033e5760003560e01c80638a19c8bc116101ae578063ccb9fe1d116100eb578063e97deabf1161008f578063f2fde38b1161006c578063f2fde38b14610962578063f51f96dd14610982578063f6b3a00a1461099d578063fd5ad319146109bd57005b8063e97deabf146108c1578063e985e9c5146108f7578063f2e45a4f1461094057005b8063dba7fd4a116100c8578063dba7fd4a1461086a578063dcafd0bc14610880578063e13cbe3814610895578063e23666de146108ac57005b8063ccb9fe1d14610807578063d0f9e2be14610827578063d660a7bd1461085457005b8063acedb5b411610152578063c040e6b81161012f578063c040e6b814610791578063c57540b9146107bf578063c87b56dd146107d4578063cb0274d5146107f457005b8063acedb5b41461073c578063b88d4fde1461075c578063bd978e8d1461077c57005b806395d89b411161018b57806395d89b41146106c75780639671219b146106dc5780639e34070f146106fc578063a22cb4651461071c57005b80638a19c8bc146106735780638ada6b0f146106895780638da5cb5b146106a957005b80633ccfd60b1161027c578063580e77d41161022057806370a08231116101fd57806370a0823114610620578063715018a61461064057806376c242461461065557806378aafea21461066b57005b8063580e77d4146105d65780636352211e146105eb5780636e4ed7961461060b57005b806346feb24a1161025957806346feb24a1461056b578063473e3ea41461058b5780634f6ccce7146105a05780635533f19a146105c057005b80633ccfd60b1461051657806342842e0e1461052b57806344021ad71461054b57005b8063150b7a02116102e35780632ae07c33116102c05780632ae07c33146104b85780632f745c59146104ce5780633364b0d2146104ee57806339af9afe146104f657005b8063150b7a021461044057806318160ddd1461047957806323b872dd1461049857005b8063095ea7b31161031c578063095ea7b3146103cf5780630a212469146103ef5780630bc634d914610407578063130eb2f61461042957005b806301ffc9a71461034057806306fdde0314610375578063081812fc14610397575b005b34801561034c57600080fd5b5061036061035b366004613283565b6109dd565b60405190151581526020015b60405180910390f35b34801561038157600080fd5b5061038a6109ee565b60405161036c91906134bd565b3480156103a357600080fd5b506103b76103b2366004613334565b610a80565b6040516001600160a01b03909116815260200161036c565b3480156103db57600080fd5b5061033e6103ea3660046131ac565b610aa7565b3480156103fb57600080fd5b50600b54421015610360565b34801561041357600080fd5b5061041c610bc2565b60405161036c9190613451565b34801561043557600080fd5b506010541515610360565b34801561044c57600080fd5b5061046061045b3660046130c5565b610bd2565b6040516001600160e01b0319909116815260200161036c565b34801561048557600080fd5b506008545b60405190815260200161036c565b3480156104a457600080fd5b5061033e6104b3366004613089565b610be3565b3480156104c457600080fd5b5061048a61313881565b3480156104da57600080fd5b5061048a6104e93660046131ac565b610c14565b61033e610caa565b34801561050257600080fd5b5061033e6105113660046131d6565b610de3565b34801561052257600080fd5b5061033e610e61565b34801561053757600080fd5b5061033e610546366004613089565b610f21565b34801561055757600080fd5b5061033e610566366004613334565b610f3c565b34801561057757600080fd5b5061033e610586366004613334565b6111ae565b34801561059757600080fd5b5061048a611442565b3480156105ac57600080fd5b5061048a6105bb366004613334565b611454565b3480156105cc57600080fd5b5061048a600b5481565b3480156105e257600080fd5b5061033e6114e7565b3480156105f757600080fd5b506103b7610606366004613334565b611552565b34801561061757600080fd5b5061048a602a81565b34801561062c57600080fd5b5061048a61063b36600461303b565b6115b2565b34801561064c57600080fd5b5061033e611638565b34801561066157600080fd5b5061048a60155481565b61033e61164c565b34801561067f57600080fd5b5061048a60135481565b34801561069557600080fd5b50600f546103b7906001600160a01b031681565b3480156106b557600080fd5b50600a546001600160a01b03166103b7565b3480156106d357600080fd5b5061038a6116f6565b3480156106e857600080fd5b5061038a6106f7366004613334565b611705565b34801561070857600080fd5b50610360610717366004613334565b61180c565b34801561072857600080fd5b5061033e610737366004613170565b61184d565b34801561074857600080fd5b5061033e610757366004613334565b611858565b34801561076857600080fd5b5061033e6107773660046130c5565b611925565b34801561078857600080fd5b5061048a611957565b34801561079d57600080fd5b50600a546107b290600160a81b900460ff1681565b60405161036c9190613495565b3480156107cb57600080fd5b506103606119c9565b3480156107e057600080fd5b5061038a6107ef366004613334565b6119ec565b61033e61080236600461334d565b611ac8565b34801561081357600080fd5b5061041c61082236600461303b565b611cdc565b34801561083357600080fd5b5061048a610842366004613334565b60186020526000908152604090205481565b34801561086057600080fd5b5061048a60145481565b34801561087657600080fd5b5061048a60165481565b34801561088c57600080fd5b5061033e611db9565b3480156108a157600080fd5b5061048a6203ca5081565b3480156108b857600080fd5b50610360612110565b3480156108cd57600080fd5b506103b76108dc366004613334565b6017602052600090815260409020546001600160a01b031681565b34801561090357600080fd5b50610360610912366004613056565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b34801561094c57600080fd5b50610955612129565b60405161036c9190613570565b34801561096e57600080fd5b5061033e61097d36600461303b565b61225d565b34801561098e57600080fd5b5061048a6658d15e1762800081565b3480156109a957600080fd5b5061033e6109b8366004613334565b6122d6565b3480156109c957600080fd5b5061038a6109d8366004613334565b612304565b60006109e88261250e565b92915050565b6060600080546109fd90613711565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2990613711565b8015610a765780601f10610a4b57610100808354040283529160200191610a76565b820191906000526020600020905b815481529060010190602001808311610a5957829003601f168201915b5050505050905090565b6000610a8b82612533565b506000908152600460205260409020546001600160a01b031690565b6000610ab282611552565b9050806001600160a01b0316836001600160a01b03161415610b255760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610b415750610b418133610912565b610bb35760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610b1c565b610bbd8383612592565b505050565b6060610bcd33611cdc565b905090565b630a85bd0160e11b5b949350505050565b610bed3382612600565b610c095760405162461bcd60e51b8152600401610b1c90613522565b610bbd83838361267e565b6000610c1f836115b2565b8210610c815760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610b1c565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6002600a54600160a81b900460ff166002811115610cca57610cca6137b7565b141580610cd95750600b544210155b15610cf757604051631117739360e21b815260040160405180910390fd5b6000610d0a6658d15e1762800034613684565b905080610d2a5760405163c755930f60e01b815260040160405180910390fd5b6014811115610d37575060145b60005b81811015610d5257610d4a612825565b600101610d3a565b50610d65600e8054600019430140019055565b6000610d78826658d15e17628000613698565b610d8290346136b7565b90508015610ddf57604051600090339083908381818185875af1925050503d8060008114610dcc576040519150601f19603f3d011682016040523d82523d6000602084013e610dd1565b606091505b5050905080610bbd57600080fd5b5050565b610deb6119c9565b610e085760405163fd270db760e01b815260040160405180910390fd5b601481511115610e2b576040516359a363c360e01b815260040160405180910390fd5b60005b8151811015610ddf57610e59828281518110610e4c57610e4c6137e3565b602002602001015161283c565b600101610e2e565b610e6961287b565b60105415610e8a57604051631f0f458560e31b815260040160405180910390fd5b600a54600160a01b900460ff16610eb457604051633b9aea6160e01b815260040160405180910390fd5b600a805460ff60a01b1981169091556001600160a01b0316612710610edb47610bf2613698565b610ee59190613684565b604051600081818185875af1925050503d8060008114610bbd576040519150601f19603f3d011682016040523d82523d6000602084013e505050565b610bbd83838360405180602001604052806000815250611925565b6000818152601760205260409020546001600160a01b03163314610f735760405163c625044360e01b815260040160405180910390fd5b601654600114158015610f895750610f89612110565b15610fa75760405163b1be465b60e01b815260040160405180910390fd5b60135480610fc8576040516329dfd3af60e21b815260040160405180910390fd5b60008281526018602090815260408083208490556017909152812080546001600160a01b0319169055601654610ffe9047613684565b9050611009836128d5565b6014805490600061101983613746565b90915550506016805490600061102e836136fa565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611060573d6000803e3d6000fd5b5060165460011415610bbd576000805b611079306115b2565b8110156110bc5761108a3082610c14565b6000818152601760205260409020549092506001600160a01b0316156110b45760128290556110bc565b600101611070565b506012805460009081526018602052604090819020859055600f5491549051638967562360e01b81526001600160a01b03909216916389675623916111079160040190815260200190565b600060405180830381600087803b15801561112157600080fd5b505af1158015611135573d6000803e3d6000fd5b50506012546000908152601760205260408082205490516001600160a01b0390911693504780156108fc02935091818181858888f19350505050158015611180573d6000803e3d6000fd5b506012546000818152601760205260409020546111a89130916001600160a01b03169061267e565b50505050565b6000818152601760205260409020546001600160a01b031633146111e55760405163c625044360e01b815260040160405180910390fd5b6016546001141580156111fb57506111fb612110565b156112195760405163b1be465b60e01b815260040160405180910390fd5b6013548061123a576040516329dfd3af60e21b815260040160405180910390fd5b60008281526018602052604090819020829055600f54905163907d870160e01b8152600481018490526001600160a01b039091169063907d870190602401600060405180830381600087803b15801561129257600080fd5b505af11580156112a6573d6000803e3d6000fd5b505050600083815260176020526040902080546001600160a01b0319169055506112d130338461267e565b601580549060006112e183613746565b9091555050601680549060006112f6836136fa565b919050555060165460011415610ddf576000805b611313306115b2565b811015611356576113243082610c14565b6000818152601760205260409020549092506001600160a01b03161561134e576012829055611356565b60010161130a565b506012805460009081526018602052604090819020849055600f5491549051638967562360e01b81526001600160a01b03909216916389675623916113a19160040190815260200190565b600060405180830381600087803b1580156113bb57600080fd5b505af11580156113cf573d6000803e3d6000fd5b50506012546000908152601760205260408082205490516001600160a01b0390911693504780156108fc02935091818181858888f1935050505015801561141a573d6000803e3d6000fd5b50601254600081815260176020526040902054610bbd9130916001600160a01b03169061267e565b6000613138601054610bcd919061366c565b600061145f60085490565b82106114c25760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610b1c565b600882815481106114d5576114d56137e3565b90600052602060002001549050919050565b6114ef61287b565b6001600a54600160a81b900460ff16600281111561150f5761150f6137b7565b1461152d576040516334e6c21f60e01b815260040160405180910390fd5b600a805460ff60a81b1916600160a91b17905561154d6203ca504261366c565b600b55565b6000818152600260205260408120546001600160a01b0316806109e85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610b1c565b60006001600160a01b03821661161c5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610b1c565b506001600160a01b031660009081526003602052604090205490565b61164061287b565b61164a600061297c565b565b61165461287b565b6000600a54600160a81b900460ff166002811115611674576116746137b7565b1461169257604051630da27c1960e11b815260040160405180910390fd5b601054156116b357604051631f0f458560e31b815260040160405180910390fd5b600a54600160a01b900460ff16156116de5760405163061865db60e41b815260040160405180910390fd5b4360108190556116f1906131389061366c565b601155565b6060600180546109fd90613711565b606081611729816000908152600260205260409020546001600160a01b0316151590565b61174657604051634a1850bf60e11b815260040160405180910390fd5b600f546001600160a01b0316636cfbaa746000600a54600160a81b900460ff166002811115611777576117776137b7565b1485611782876129ce565b6040516001600160e01b031960e086901b1681529215156004840152602483019190915260448201526064015b60006040518083038186803b1580156117c757600080fd5b505afa1580156117db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261180391908101906132bd565b91505b50919050565b60008061181b61010084613684565b9050600061182b61010085613761565b6000928352600c602052604090922054600190921b9182169091149392505050565b610ddf338383612a0c565b61186061287b565b6002600a54600160a81b900460ff166002811115611880576118806137b7565b1461189e5760405163634a054360e11b815260040160405180910390fd5b600b544210156118c15760405163f1da374560e01b815260040160405180910390fd5b600d546040805160208101849052016040516020818303038152906040528051906020012060001c1461190757604051639ea6d12760e01b815260040160405180910390fd5b600e805491909118600d5560009055600a805460ff60a81b19169055565b61192f3383612600565b61194b5760405162461bcd60e51b8152600401610b1c90613522565b6111a884848484612adb565b60006016546000141561196a5750600090565b6016546001906107d01161199c5760006103e860165461198a91906136b7565b90506119986101f482613684565b9150505b60165481106119b75760016016546119b491906136b7565b90505b60328111156119c4575060325b919050565b60006119d6601054151590565b8015610bcd57506119e5611442565b4310905090565b606081611a10816000908152600260205260409020546001600160a01b0316151590565b611a2d57604051634a1850bf60e11b815260040160405180910390fd5b600f546001600160a01b031663f7db218c6000600a54600160a81b900460ff166002811115611a5e57611a5e6137b7565b1485611a69876129ce565b600088815260186020526040902054611a8189611552565b6040516001600160e01b031960e088901b16815294151560048601526024850193909352604484019190915260648301526001600160a01b0316608482015260a4016117af565b6001600a54600160a81b900460ff166002811115611ae857611ae86137b7565b14611b06576040516334e6c21f60e01b815260040160405180910390fd5b611b0f8661180c565b15611b2d57604051630c8d9eab60e31b815260040160405180910390fd5b80611b4b5760405163843ce46b60e01b815260040160405180910390fd5b6000611b57858761366c565b905080821115611b7a5760405163843ce46b60e01b815260040160405180910390fd5b600086831115611b9157611b8e87846136b7565b90505b611ba26658d15e1762800082613698565b341015611bc25760405163611f16b160e11b815260040160405180910390fd5b60408051602081018a90526bffffffffffffffffffffffff193360601b16918101919091526054810188905260748101879052600090609401604051602081830303815290604052805190602001209050611c738686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f00000000000000000000000000000000000000000000000000000000000000009250859150612b0e9050565b611c90576040516309bde33960e01b815260040160405180910390fd5b611c9989612b24565b60005b84811015611cbe57611cac612825565b80611cb681613746565b915050611c9c565b50611cd1600e8054600019430140019055565b505050505050505050565b6060306000611cea826115b2565b905060008167ffffffffffffffff811115611d0757611d076137f9565b604051908082528060200260200182016040528015611d30578160200160208202803683370190505b5090506000805b83811015611dae576000611d4b8683610c14565b6000818152601760205260409020549091506001600160a01b0389811691161415611d9b57808484611d7c81613746565b955081518110611d8e57611d8e6137e3565b6020026020010181815250505b5080611da681613746565b915050611d37565b508152949350505050565b601054611dd95760405163237ce2fd60e21b815260040160405180910390fd5b611de1612110565b611dfe576040516357be4ad560e01b815260040160405180910390fd5b60165460011415611e2257604051631dd4f54560e11b815260040160405180910390fd5b601654611e425760405163df469ccb60e01b815260040160405180910390fd5b600060ff602a601154611e55919061366c565b611e5f90436136b7565b1115611e8e576001602a611e738143613684565b611e7d9190613698565b611e8791906136b7565b9050611eac565b6001602a601154611e9f919061366c565b611ea991906136b7565b90505b804080611ebb57611ebb613775565b4360115560138054906000611ecf83613746565b91905055506000611ede611957565b6040805160208082528183019092529192506000919060208201818036833701905050905060015b828111611fc45780840193508360208301526000611f23306115b2565b83516020850120611f349190613761565b90506000611f423083610c14565b9050611f4d816128d5565b6000818152601760205260409020546001600160a01b0316611f755760001990920191611fba565b600081815260176020526040812080546001600160a01b03191690556014805491611f9f83613746565b909155505060168054906000611fb4836136fa565b91905055505b5050600101611f06565b50601654600114156111a8576000805b611fdd306115b2565b81101561202057611fee3082610c14565b6000818152601760205260409020549092506001600160a01b031615612018576012829055612020565b600101611fd4565b50601354601280546000908152601860205260409081902092909255600f5490549151638967562360e01b815260048101929092526001600160a01b031690638967562390602401600060405180830381600087803b15801561208257600080fd5b505af1158015612096573d6000803e3d6000fd5b50506012546000908152601760205260408082205490516001600160a01b0390911693504780156108fc02935091818181858888f193505050501580156120e1573d6000803e3d6000fd5b506012546000818152601760205260409020546121099130916001600160a01b03169061267e565b5050505050565b6000602a601154612121919061366c565b431015905090565b61219c604051806101a001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581526020016000151581526020016000151581525090565b60145481526016546020820152601554604082015260135460608201524760808201526121c7611957565b60a082015260125460e08201526121dc611442565b6101008201526121ea612110565b61220e5743602a6011546121fe919061366c565b61220891906136b7565b60c08201525b612216612110565b15156101208201526122266119c9565b151561014082015260105415156101608201526101008101514311801561225257506001816020015111155b151561018082015290565b61226561287b565b6001600160a01b0381166122ca5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b1c565b6122d38161297c565b50565b6122de6119c9565b6122fb5760405163fd270db760e01b815260040160405180910390fd5b6122d38161283c565b606081612328816000908152600260205260409020546001600160a01b0316151590565b61234557604051634a1850bf60e11b815260040160405180910390fd5b60003061235185611552565b6001600160a01b03161415612369575060135461237a565b506000838152601860205260409020545b600f546001600160a01b031663a98edced6000600a54600160a81b900460ff1660028111156123ab576123ab6137b7565b14866123b6886129ce565b856123c08a611552565b6040516001600160e01b031960e088901b16815294151560048601526024850193909352604484019190915260648301526001600160a01b0316608482015260a40160006040518083038186803b15801561241a57600080fd5b505afa15801561242e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bdb91908101906132bd565b6001600160a01b0383166124b1576124ac81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6124d4565b816001600160a01b0316836001600160a01b0316146124d4576124d48382612b62565b6001600160a01b0382166124eb57610bbd81612bff565b826001600160a01b0316826001600160a01b031614610bbd57610bbd8282612cae565b60006001600160e01b0319821663780e9d6360e01b14806109e857506109e882612cf2565b6000818152600260205260409020546001600160a01b03166122d35760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610b1c565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906125c782611552565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061260c83611552565b9050806001600160a01b0316846001600160a01b0316148061265357506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b80610bdb5750836001600160a01b031661266c84610a80565b6001600160a01b031614949350505050565b826001600160a01b031661269182611552565b6001600160a01b0316146126f55760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610b1c565b6001600160a01b0382166127575760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610b1c565b612762838383612d42565b61276d600082612592565b6001600160a01b03831660009081526003602052604081208054600192906127969084906136b7565b90915550506001600160a01b03821660009081526003602052604081208054600192906127c490849061366c565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061283060085490565b90506122d33382612d4d565b612847333083610be3565b600081815260176020526040812080546001600160a01b03191633179055601680549161287383613746565b919050555050565b600a546001600160a01b0316331461164a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b1c565b60006128e082611552565b90506128ee81600084612d42565b6128f9600083612592565b6001600160a01b03811660009081526003602052604081208054600192906129229084906136b7565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000600d54826040516020016129ee929190918252602082015260400190565b60408051601f19818403018152919052805160209091012092915050565b816001600160a01b0316836001600160a01b03161415612a6e5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b1c565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612ae684848461267e565b612af284848484612e9b565b6111a85760405162461bcd60e51b8152600401610b1c906134d0565b600082612b1b8584612fa5565b14949350505050565b6000612b3261010083613684565b90506000612b4261010084613761565b6000928352600c60205260409092208054600190931b9092179091555050565b60006001612b6f846115b2565b612b7991906136b7565b600083815260076020526040902054909150808214612bcc576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090612c11906001906136b7565b60008381526009602052604081205460088054939450909284908110612c3957612c396137e3565b906000526020600020015490508060088381548110612c5a57612c5a6137e3565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480612c9257612c926137cd565b6001900381819060005260206000200160009055905550505050565b6000612cb9836115b2565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b60006001600160e01b031982166380ac58cd60e01b1480612d2357506001600160e01b03198216635b5e139f60e01b145b806109e857506301ffc9a760e01b6001600160e01b03198316146109e8565b610bbd838383612456565b6001600160a01b038216612da35760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b1c565b6000818152600260205260409020546001600160a01b031615612e085760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b1c565b612e1460008383612d42565b6001600160a01b0382166000908152600360205260408120805460019290612e3d90849061366c565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160a01b0384163b15612f9d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612edf903390899088908890600401613414565b602060405180830381600087803b158015612ef957600080fd5b505af1925050508015612f29575060408051601f3d908101601f19168201909252612f26918101906132a0565b60015b612f83573d808015612f57576040519150601f19603f3d011682016040523d82523d6000602084013e612f5c565b606091505b508051612f7b5760405162461bcd60e51b8152600401610b1c906134d0565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610bdb565b506001610bdb565b600081815b8451811015612fea57612fd682868381518110612fc957612fc96137e3565b6020026020010151612ff2565b915080612fe281613746565b915050612faa565b509392505050565b600081831061300e57600082815260208490526040902061301d565b60008381526020839052604090205b9392505050565b80356001600160a01b03811681146119c457600080fd5b60006020828403121561304d57600080fd5b61301d82613024565b6000806040838503121561306957600080fd5b61307283613024565b915061308060208401613024565b90509250929050565b60008060006060848603121561309e57600080fd5b6130a784613024565b92506130b560208501613024565b9150604084013590509250925092565b600080600080608085870312156130db57600080fd5b6130e485613024565b93506130f260208601613024565b925060408501359150606085013567ffffffffffffffff81111561311557600080fd5b8501601f8101871361312657600080fd5b803561313961313482613644565b613613565b81815288602083850101111561314e57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561318357600080fd5b61318c83613024565b9150602083013580151581146131a157600080fd5b809150509250929050565b600080604083850312156131bf57600080fd5b6131c883613024565b946020939093013593505050565b600060208083850312156131e957600080fd5b823567ffffffffffffffff8082111561320157600080fd5b818501915085601f83011261321557600080fd5b813581811115613227576132276137f9565b8060051b9150613238848301613613565b8181528481019084860184860187018a101561325357600080fd5b600095505b83861015613276578035835260019590950194918601918601613258565b5098975050505050505050565b60006020828403121561329557600080fd5b813561301d8161380f565b6000602082840312156132b257600080fd5b815161301d8161380f565b6000602082840312156132cf57600080fd5b815167ffffffffffffffff8111156132e657600080fd5b8201601f810184136132f757600080fd5b805161330561313482613644565b81815285602083850101111561331a57600080fd5b61332b8260208301602086016136ce565b95945050505050565b60006020828403121561334657600080fd5b5035919050565b60008060008060008060a0878903121561336657600080fd5b863595506020870135945060408701359350606087013567ffffffffffffffff8082111561339357600080fd5b818901915089601f8301126133a757600080fd5b8135818111156133b657600080fd5b8a60208260051b85010111156133cb57600080fd5b602083019550809450505050608087013590509295509295509295565b600081518084526134008160208601602086016136ce565b601f01601f19169290920160200192915050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613447908301846133e8565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156134895783518352928401929184019160010161346d565b50909695505050505050565b60208101600383106134b757634e487b7160e01b600052602160045260246000fd5b91905290565b60208152600061301d60208301846133e8565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b60006101a082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e0830152610100808401518184015250610120808401516135e38285018215159052565b50506101408381015115159083015261016080840151151590830152610180928301511515929091019190915290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561363c5761363c6137f9565b604052919050565b600067ffffffffffffffff82111561365e5761365e6137f9565b50601f01601f191660200190565b6000821982111561367f5761367f61378b565b500190565b600082613693576136936137a1565b500490565b60008160001904831182151516156136b2576136b261378b565b500290565b6000828210156136c9576136c961378b565b500390565b60005b838110156136e95781810151838201526020016136d1565b838111156111a85750506000910152565b6000816137095761370961378b565b506000190190565b600181811c9082168061372557607f821691505b6020821081141561180657634e487b7160e01b600052602260045260246000fd5b600060001982141561375a5761375a61378b565b5060010190565b600082613770576137706137a1565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b0319811681146122d357600080fdfea2646970667358221220dae9601cc6aa1fba524034cb8a7b4712794491d5df82b16c3aaddf921884c1fd64736f6c63430008070033bdd3ef7aa3fe0f5e1ca451a428919fed839d046e4397767d9d8d98271dac4a7f000000000000000000000000b60d7d1d5f63f8f720526919b770ff3985e183e4799a04ec1676eb17f6792c74bbd3482bb9063e1274a084903d0bef83c5414231
Deployed Bytecode
0x60806040526004361061033e5760003560e01c80638a19c8bc116101ae578063ccb9fe1d116100eb578063e97deabf1161008f578063f2fde38b1161006c578063f2fde38b14610962578063f51f96dd14610982578063f6b3a00a1461099d578063fd5ad319146109bd57005b8063e97deabf146108c1578063e985e9c5146108f7578063f2e45a4f1461094057005b8063dba7fd4a116100c8578063dba7fd4a1461086a578063dcafd0bc14610880578063e13cbe3814610895578063e23666de146108ac57005b8063ccb9fe1d14610807578063d0f9e2be14610827578063d660a7bd1461085457005b8063acedb5b411610152578063c040e6b81161012f578063c040e6b814610791578063c57540b9146107bf578063c87b56dd146107d4578063cb0274d5146107f457005b8063acedb5b41461073c578063b88d4fde1461075c578063bd978e8d1461077c57005b806395d89b411161018b57806395d89b41146106c75780639671219b146106dc5780639e34070f146106fc578063a22cb4651461071c57005b80638a19c8bc146106735780638ada6b0f146106895780638da5cb5b146106a957005b80633ccfd60b1161027c578063580e77d41161022057806370a08231116101fd57806370a0823114610620578063715018a61461064057806376c242461461065557806378aafea21461066b57005b8063580e77d4146105d65780636352211e146105eb5780636e4ed7961461060b57005b806346feb24a1161025957806346feb24a1461056b578063473e3ea41461058b5780634f6ccce7146105a05780635533f19a146105c057005b80633ccfd60b1461051657806342842e0e1461052b57806344021ad71461054b57005b8063150b7a02116102e35780632ae07c33116102c05780632ae07c33146104b85780632f745c59146104ce5780633364b0d2146104ee57806339af9afe146104f657005b8063150b7a021461044057806318160ddd1461047957806323b872dd1461049857005b8063095ea7b31161031c578063095ea7b3146103cf5780630a212469146103ef5780630bc634d914610407578063130eb2f61461042957005b806301ffc9a71461034057806306fdde0314610375578063081812fc14610397575b005b34801561034c57600080fd5b5061036061035b366004613283565b6109dd565b60405190151581526020015b60405180910390f35b34801561038157600080fd5b5061038a6109ee565b60405161036c91906134bd565b3480156103a357600080fd5b506103b76103b2366004613334565b610a80565b6040516001600160a01b03909116815260200161036c565b3480156103db57600080fd5b5061033e6103ea3660046131ac565b610aa7565b3480156103fb57600080fd5b50600b54421015610360565b34801561041357600080fd5b5061041c610bc2565b60405161036c9190613451565b34801561043557600080fd5b506010541515610360565b34801561044c57600080fd5b5061046061045b3660046130c5565b610bd2565b6040516001600160e01b0319909116815260200161036c565b34801561048557600080fd5b506008545b60405190815260200161036c565b3480156104a457600080fd5b5061033e6104b3366004613089565b610be3565b3480156104c457600080fd5b5061048a61313881565b3480156104da57600080fd5b5061048a6104e93660046131ac565b610c14565b61033e610caa565b34801561050257600080fd5b5061033e6105113660046131d6565b610de3565b34801561052257600080fd5b5061033e610e61565b34801561053757600080fd5b5061033e610546366004613089565b610f21565b34801561055757600080fd5b5061033e610566366004613334565b610f3c565b34801561057757600080fd5b5061033e610586366004613334565b6111ae565b34801561059757600080fd5b5061048a611442565b3480156105ac57600080fd5b5061048a6105bb366004613334565b611454565b3480156105cc57600080fd5b5061048a600b5481565b3480156105e257600080fd5b5061033e6114e7565b3480156105f757600080fd5b506103b7610606366004613334565b611552565b34801561061757600080fd5b5061048a602a81565b34801561062c57600080fd5b5061048a61063b36600461303b565b6115b2565b34801561064c57600080fd5b5061033e611638565b34801561066157600080fd5b5061048a60155481565b61033e61164c565b34801561067f57600080fd5b5061048a60135481565b34801561069557600080fd5b50600f546103b7906001600160a01b031681565b3480156106b557600080fd5b50600a546001600160a01b03166103b7565b3480156106d357600080fd5b5061038a6116f6565b3480156106e857600080fd5b5061038a6106f7366004613334565b611705565b34801561070857600080fd5b50610360610717366004613334565b61180c565b34801561072857600080fd5b5061033e610737366004613170565b61184d565b34801561074857600080fd5b5061033e610757366004613334565b611858565b34801561076857600080fd5b5061033e6107773660046130c5565b611925565b34801561078857600080fd5b5061048a611957565b34801561079d57600080fd5b50600a546107b290600160a81b900460ff1681565b60405161036c9190613495565b3480156107cb57600080fd5b506103606119c9565b3480156107e057600080fd5b5061038a6107ef366004613334565b6119ec565b61033e61080236600461334d565b611ac8565b34801561081357600080fd5b5061041c61082236600461303b565b611cdc565b34801561083357600080fd5b5061048a610842366004613334565b60186020526000908152604090205481565b34801561086057600080fd5b5061048a60145481565b34801561087657600080fd5b5061048a60165481565b34801561088c57600080fd5b5061033e611db9565b3480156108a157600080fd5b5061048a6203ca5081565b3480156108b857600080fd5b50610360612110565b3480156108cd57600080fd5b506103b76108dc366004613334565b6017602052600090815260409020546001600160a01b031681565b34801561090357600080fd5b50610360610912366004613056565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b34801561094c57600080fd5b50610955612129565b60405161036c9190613570565b34801561096e57600080fd5b5061033e61097d36600461303b565b61225d565b34801561098e57600080fd5b5061048a6658d15e1762800081565b3480156109a957600080fd5b5061033e6109b8366004613334565b6122d6565b3480156109c957600080fd5b5061038a6109d8366004613334565b612304565b60006109e88261250e565b92915050565b6060600080546109fd90613711565b80601f0160208091040260200160405190810160405280929190818152602001828054610a2990613711565b8015610a765780601f10610a4b57610100808354040283529160200191610a76565b820191906000526020600020905b815481529060010190602001808311610a5957829003601f168201915b5050505050905090565b6000610a8b82612533565b506000908152600460205260409020546001600160a01b031690565b6000610ab282611552565b9050806001600160a01b0316836001600160a01b03161415610b255760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b0382161480610b415750610b418133610912565b610bb35760405162461bcd60e51b815260206004820152603e60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206e6f7220617070726f76656420666f7220616c6c00006064820152608401610b1c565b610bbd8383612592565b505050565b6060610bcd33611cdc565b905090565b630a85bd0160e11b5b949350505050565b610bed3382612600565b610c095760405162461bcd60e51b8152600401610b1c90613522565b610bbd83838361267e565b6000610c1f836115b2565b8210610c815760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201526a74206f6620626f756e647360a81b6064820152608401610b1c565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6002600a54600160a81b900460ff166002811115610cca57610cca6137b7565b141580610cd95750600b544210155b15610cf757604051631117739360e21b815260040160405180910390fd5b6000610d0a6658d15e1762800034613684565b905080610d2a5760405163c755930f60e01b815260040160405180910390fd5b6014811115610d37575060145b60005b81811015610d5257610d4a612825565b600101610d3a565b50610d65600e8054600019430140019055565b6000610d78826658d15e17628000613698565b610d8290346136b7565b90508015610ddf57604051600090339083908381818185875af1925050503d8060008114610dcc576040519150601f19603f3d011682016040523d82523d6000602084013e610dd1565b606091505b5050905080610bbd57600080fd5b5050565b610deb6119c9565b610e085760405163fd270db760e01b815260040160405180910390fd5b601481511115610e2b576040516359a363c360e01b815260040160405180910390fd5b60005b8151811015610ddf57610e59828281518110610e4c57610e4c6137e3565b602002602001015161283c565b600101610e2e565b610e6961287b565b60105415610e8a57604051631f0f458560e31b815260040160405180910390fd5b600a54600160a01b900460ff16610eb457604051633b9aea6160e01b815260040160405180910390fd5b600a805460ff60a01b1981169091556001600160a01b0316612710610edb47610bf2613698565b610ee59190613684565b604051600081818185875af1925050503d8060008114610bbd576040519150601f19603f3d011682016040523d82523d6000602084013e505050565b610bbd83838360405180602001604052806000815250611925565b6000818152601760205260409020546001600160a01b03163314610f735760405163c625044360e01b815260040160405180910390fd5b601654600114158015610f895750610f89612110565b15610fa75760405163b1be465b60e01b815260040160405180910390fd5b60135480610fc8576040516329dfd3af60e21b815260040160405180910390fd5b60008281526018602090815260408083208490556017909152812080546001600160a01b0319169055601654610ffe9047613684565b9050611009836128d5565b6014805490600061101983613746565b90915550506016805490600061102e836136fa565b9091555050604051339082156108fc029083906000818181858888f19350505050158015611060573d6000803e3d6000fd5b5060165460011415610bbd576000805b611079306115b2565b8110156110bc5761108a3082610c14565b6000818152601760205260409020549092506001600160a01b0316156110b45760128290556110bc565b600101611070565b506012805460009081526018602052604090819020859055600f5491549051638967562360e01b81526001600160a01b03909216916389675623916111079160040190815260200190565b600060405180830381600087803b15801561112157600080fd5b505af1158015611135573d6000803e3d6000fd5b50506012546000908152601760205260408082205490516001600160a01b0390911693504780156108fc02935091818181858888f19350505050158015611180573d6000803e3d6000fd5b506012546000818152601760205260409020546111a89130916001600160a01b03169061267e565b50505050565b6000818152601760205260409020546001600160a01b031633146111e55760405163c625044360e01b815260040160405180910390fd5b6016546001141580156111fb57506111fb612110565b156112195760405163b1be465b60e01b815260040160405180910390fd5b6013548061123a576040516329dfd3af60e21b815260040160405180910390fd5b60008281526018602052604090819020829055600f54905163907d870160e01b8152600481018490526001600160a01b039091169063907d870190602401600060405180830381600087803b15801561129257600080fd5b505af11580156112a6573d6000803e3d6000fd5b505050600083815260176020526040902080546001600160a01b0319169055506112d130338461267e565b601580549060006112e183613746565b9091555050601680549060006112f6836136fa565b919050555060165460011415610ddf576000805b611313306115b2565b811015611356576113243082610c14565b6000818152601760205260409020549092506001600160a01b03161561134e576012829055611356565b60010161130a565b506012805460009081526018602052604090819020849055600f5491549051638967562360e01b81526001600160a01b03909216916389675623916113a19160040190815260200190565b600060405180830381600087803b1580156113bb57600080fd5b505af11580156113cf573d6000803e3d6000fd5b50506012546000908152601760205260408082205490516001600160a01b0390911693504780156108fc02935091818181858888f1935050505015801561141a573d6000803e3d6000fd5b50601254600081815260176020526040902054610bbd9130916001600160a01b03169061267e565b6000613138601054610bcd919061366c565b600061145f60085490565b82106114c25760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201526b7574206f6620626f756e647360a01b6064820152608401610b1c565b600882815481106114d5576114d56137e3565b90600052602060002001549050919050565b6114ef61287b565b6001600a54600160a81b900460ff16600281111561150f5761150f6137b7565b1461152d576040516334e6c21f60e01b815260040160405180910390fd5b600a805460ff60a81b1916600160a91b17905561154d6203ca504261366c565b600b55565b6000818152600260205260408120546001600160a01b0316806109e85760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610b1c565b60006001600160a01b03821661161c5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b6064820152608401610b1c565b506001600160a01b031660009081526003602052604090205490565b61164061287b565b61164a600061297c565b565b61165461287b565b6000600a54600160a81b900460ff166002811115611674576116746137b7565b1461169257604051630da27c1960e11b815260040160405180910390fd5b601054156116b357604051631f0f458560e31b815260040160405180910390fd5b600a54600160a01b900460ff16156116de5760405163061865db60e41b815260040160405180910390fd5b4360108190556116f1906131389061366c565b601155565b6060600180546109fd90613711565b606081611729816000908152600260205260409020546001600160a01b0316151590565b61174657604051634a1850bf60e11b815260040160405180910390fd5b600f546001600160a01b0316636cfbaa746000600a54600160a81b900460ff166002811115611777576117776137b7565b1485611782876129ce565b6040516001600160e01b031960e086901b1681529215156004840152602483019190915260448201526064015b60006040518083038186803b1580156117c757600080fd5b505afa1580156117db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261180391908101906132bd565b91505b50919050565b60008061181b61010084613684565b9050600061182b61010085613761565b6000928352600c602052604090922054600190921b9182169091149392505050565b610ddf338383612a0c565b61186061287b565b6002600a54600160a81b900460ff166002811115611880576118806137b7565b1461189e5760405163634a054360e11b815260040160405180910390fd5b600b544210156118c15760405163f1da374560e01b815260040160405180910390fd5b600d546040805160208101849052016040516020818303038152906040528051906020012060001c1461190757604051639ea6d12760e01b815260040160405180910390fd5b600e805491909118600d5560009055600a805460ff60a81b19169055565b61192f3383612600565b61194b5760405162461bcd60e51b8152600401610b1c90613522565b6111a884848484612adb565b60006016546000141561196a5750600090565b6016546001906107d01161199c5760006103e860165461198a91906136b7565b90506119986101f482613684565b9150505b60165481106119b75760016016546119b491906136b7565b90505b60328111156119c4575060325b919050565b60006119d6601054151590565b8015610bcd57506119e5611442565b4310905090565b606081611a10816000908152600260205260409020546001600160a01b0316151590565b611a2d57604051634a1850bf60e11b815260040160405180910390fd5b600f546001600160a01b031663f7db218c6000600a54600160a81b900460ff166002811115611a5e57611a5e6137b7565b1485611a69876129ce565b600088815260186020526040902054611a8189611552565b6040516001600160e01b031960e088901b16815294151560048601526024850193909352604484019190915260648301526001600160a01b0316608482015260a4016117af565b6001600a54600160a81b900460ff166002811115611ae857611ae86137b7565b14611b06576040516334e6c21f60e01b815260040160405180910390fd5b611b0f8661180c565b15611b2d57604051630c8d9eab60e31b815260040160405180910390fd5b80611b4b5760405163843ce46b60e01b815260040160405180910390fd5b6000611b57858761366c565b905080821115611b7a5760405163843ce46b60e01b815260040160405180910390fd5b600086831115611b9157611b8e87846136b7565b90505b611ba26658d15e1762800082613698565b341015611bc25760405163611f16b160e11b815260040160405180910390fd5b60408051602081018a90526bffffffffffffffffffffffff193360601b16918101919091526054810188905260748101879052600090609401604051602081830303815290604052805190602001209050611c738686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f799a04ec1676eb17f6792c74bbd3482bb9063e1274a084903d0bef83c54142319250859150612b0e9050565b611c90576040516309bde33960e01b815260040160405180910390fd5b611c9989612b24565b60005b84811015611cbe57611cac612825565b80611cb681613746565b915050611c9c565b50611cd1600e8054600019430140019055565b505050505050505050565b6060306000611cea826115b2565b905060008167ffffffffffffffff811115611d0757611d076137f9565b604051908082528060200260200182016040528015611d30578160200160208202803683370190505b5090506000805b83811015611dae576000611d4b8683610c14565b6000818152601760205260409020549091506001600160a01b0389811691161415611d9b57808484611d7c81613746565b955081518110611d8e57611d8e6137e3565b6020026020010181815250505b5080611da681613746565b915050611d37565b508152949350505050565b601054611dd95760405163237ce2fd60e21b815260040160405180910390fd5b611de1612110565b611dfe576040516357be4ad560e01b815260040160405180910390fd5b60165460011415611e2257604051631dd4f54560e11b815260040160405180910390fd5b601654611e425760405163df469ccb60e01b815260040160405180910390fd5b600060ff602a601154611e55919061366c565b611e5f90436136b7565b1115611e8e576001602a611e738143613684565b611e7d9190613698565b611e8791906136b7565b9050611eac565b6001602a601154611e9f919061366c565b611ea991906136b7565b90505b804080611ebb57611ebb613775565b4360115560138054906000611ecf83613746565b91905055506000611ede611957565b6040805160208082528183019092529192506000919060208201818036833701905050905060015b828111611fc45780840193508360208301526000611f23306115b2565b83516020850120611f349190613761565b90506000611f423083610c14565b9050611f4d816128d5565b6000818152601760205260409020546001600160a01b0316611f755760001990920191611fba565b600081815260176020526040812080546001600160a01b03191690556014805491611f9f83613746565b909155505060168054906000611fb4836136fa565b91905055505b5050600101611f06565b50601654600114156111a8576000805b611fdd306115b2565b81101561202057611fee3082610c14565b6000818152601760205260409020549092506001600160a01b031615612018576012829055612020565b600101611fd4565b50601354601280546000908152601860205260409081902092909255600f5490549151638967562360e01b815260048101929092526001600160a01b031690638967562390602401600060405180830381600087803b15801561208257600080fd5b505af1158015612096573d6000803e3d6000fd5b50506012546000908152601760205260408082205490516001600160a01b0390911693504780156108fc02935091818181858888f193505050501580156120e1573d6000803e3d6000fd5b506012546000818152601760205260409020546121099130916001600160a01b03169061267e565b5050505050565b6000602a601154612121919061366c565b431015905090565b61219c604051806101a001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581526020016000151581526020016000151581525090565b60145481526016546020820152601554604082015260135460608201524760808201526121c7611957565b60a082015260125460e08201526121dc611442565b6101008201526121ea612110565b61220e5743602a6011546121fe919061366c565b61220891906136b7565b60c08201525b612216612110565b15156101208201526122266119c9565b151561014082015260105415156101608201526101008101514311801561225257506001816020015111155b151561018082015290565b61226561287b565b6001600160a01b0381166122ca5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b1c565b6122d38161297c565b50565b6122de6119c9565b6122fb5760405163fd270db760e01b815260040160405180910390fd5b6122d38161283c565b606081612328816000908152600260205260409020546001600160a01b0316151590565b61234557604051634a1850bf60e11b815260040160405180910390fd5b60003061235185611552565b6001600160a01b03161415612369575060135461237a565b506000838152601860205260409020545b600f546001600160a01b031663a98edced6000600a54600160a81b900460ff1660028111156123ab576123ab6137b7565b14866123b6886129ce565b856123c08a611552565b6040516001600160e01b031960e088901b16815294151560048601526024850193909352604484019190915260648301526001600160a01b0316608482015260a40160006040518083038186803b15801561241a57600080fd5b505afa15801561242e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610bdb91908101906132bd565b6001600160a01b0383166124b1576124ac81600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b6124d4565b816001600160a01b0316836001600160a01b0316146124d4576124d48382612b62565b6001600160a01b0382166124eb57610bbd81612bff565b826001600160a01b0316826001600160a01b031614610bbd57610bbd8282612cae565b60006001600160e01b0319821663780e9d6360e01b14806109e857506109e882612cf2565b6000818152600260205260409020546001600160a01b03166122d35760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b6044820152606401610b1c565b600081815260046020526040902080546001600160a01b0319166001600160a01b03841690811790915581906125c782611552565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008061260c83611552565b9050806001600160a01b0316846001600160a01b0316148061265357506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b80610bdb5750836001600160a01b031661266c84610a80565b6001600160a01b031614949350505050565b826001600160a01b031661269182611552565b6001600160a01b0316146126f55760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610b1c565b6001600160a01b0382166127575760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b6064820152608401610b1c565b612762838383612d42565b61276d600082612592565b6001600160a01b03831660009081526003602052604081208054600192906127969084906136b7565b90915550506001600160a01b03821660009081526003602052604081208054600192906127c490849061366c565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600061283060085490565b90506122d33382612d4d565b612847333083610be3565b600081815260176020526040812080546001600160a01b03191633179055601680549161287383613746565b919050555050565b600a546001600160a01b0316331461164a5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b1c565b60006128e082611552565b90506128ee81600084612d42565b6128f9600083612592565b6001600160a01b03811660009081526003602052604081208054600192906129229084906136b7565b909155505060008281526002602052604080822080546001600160a01b0319169055518391906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908390a45050565b600a80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6000600d54826040516020016129ee929190918252602082015260400190565b60408051601f19818403018152919052805160209091012092915050565b816001600160a01b0316836001600160a01b03161415612a6e5760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610b1c565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b612ae684848461267e565b612af284848484612e9b565b6111a85760405162461bcd60e51b8152600401610b1c906134d0565b600082612b1b8584612fa5565b14949350505050565b6000612b3261010083613684565b90506000612b4261010084613761565b6000928352600c60205260409092208054600190931b9092179091555050565b60006001612b6f846115b2565b612b7991906136b7565b600083815260076020526040902054909150808214612bcc576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090612c11906001906136b7565b60008381526009602052604081205460088054939450909284908110612c3957612c396137e3565b906000526020600020015490508060088381548110612c5a57612c5a6137e3565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480612c9257612c926137cd565b6001900381819060005260206000200160009055905550505050565b6000612cb9836115b2565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b60006001600160e01b031982166380ac58cd60e01b1480612d2357506001600160e01b03198216635b5e139f60e01b145b806109e857506301ffc9a760e01b6001600160e01b03198316146109e8565b610bbd838383612456565b6001600160a01b038216612da35760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610b1c565b6000818152600260205260409020546001600160a01b031615612e085760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610b1c565b612e1460008383612d42565b6001600160a01b0382166000908152600360205260408120805460019290612e3d90849061366c565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b60006001600160a01b0384163b15612f9d57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290612edf903390899088908890600401613414565b602060405180830381600087803b158015612ef957600080fd5b505af1925050508015612f29575060408051601f3d908101601f19168201909252612f26918101906132a0565b60015b612f83573d808015612f57576040519150601f19603f3d011682016040523d82523d6000602084013e612f5c565b606091505b508051612f7b5760405162461bcd60e51b8152600401610b1c906134d0565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050610bdb565b506001610bdb565b600081815b8451811015612fea57612fd682868381518110612fc957612fc96137e3565b6020026020010151612ff2565b915080612fe281613746565b915050612faa565b509392505050565b600081831061300e57600082815260208490526040902061301d565b60008381526020839052604090205b9392505050565b80356001600160a01b03811681146119c457600080fd5b60006020828403121561304d57600080fd5b61301d82613024565b6000806040838503121561306957600080fd5b61307283613024565b915061308060208401613024565b90509250929050565b60008060006060848603121561309e57600080fd5b6130a784613024565b92506130b560208501613024565b9150604084013590509250925092565b600080600080608085870312156130db57600080fd5b6130e485613024565b93506130f260208601613024565b925060408501359150606085013567ffffffffffffffff81111561311557600080fd5b8501601f8101871361312657600080fd5b803561313961313482613644565b613613565b81815288602083850101111561314e57600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b6000806040838503121561318357600080fd5b61318c83613024565b9150602083013580151581146131a157600080fd5b809150509250929050565b600080604083850312156131bf57600080fd5b6131c883613024565b946020939093013593505050565b600060208083850312156131e957600080fd5b823567ffffffffffffffff8082111561320157600080fd5b818501915085601f83011261321557600080fd5b813581811115613227576132276137f9565b8060051b9150613238848301613613565b8181528481019084860184860187018a101561325357600080fd5b600095505b83861015613276578035835260019590950194918601918601613258565b5098975050505050505050565b60006020828403121561329557600080fd5b813561301d8161380f565b6000602082840312156132b257600080fd5b815161301d8161380f565b6000602082840312156132cf57600080fd5b815167ffffffffffffffff8111156132e657600080fd5b8201601f810184136132f757600080fd5b805161330561313482613644565b81815285602083850101111561331a57600080fd5b61332b8260208301602086016136ce565b95945050505050565b60006020828403121561334657600080fd5b5035919050565b60008060008060008060a0878903121561336657600080fd5b863595506020870135945060408701359350606087013567ffffffffffffffff8082111561339357600080fd5b818901915089601f8301126133a757600080fd5b8135818111156133b657600080fd5b8a60208260051b85010111156133cb57600080fd5b602083019550809450505050608087013590509295509295509295565b600081518084526134008160208601602086016136ce565b601f01601f19169290920160200192915050565b6001600160a01b0385811682528416602082015260408101839052608060608201819052600090613447908301846133e8565b9695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156134895783518352928401929184019160010161346d565b50909695505050505050565b60208101600383106134b757634e487b7160e01b600052602160045260246000fd5b91905290565b60208152600061301d60208301846133e8565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6020808252602e908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526d1c881b9bdc88185c1c1c9bdd995960921b606082015260800190565b60006101a082019050825182526020830151602083015260408301516040830152606083015160608301526080830151608083015260a083015160a083015260c083015160c083015260e083015160e0830152610100808401518184015250610120808401516135e38285018215159052565b50506101408381015115159083015261016080840151151590830152610180928301511515929091019190915290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561363c5761363c6137f9565b604052919050565b600067ffffffffffffffff82111561365e5761365e6137f9565b50601f01601f191660200190565b6000821982111561367f5761367f61378b565b500190565b600082613693576136936137a1565b500490565b60008160001904831182151516156136b2576136b261378b565b500290565b6000828210156136c9576136c961378b565b500390565b60005b838110156136e95781810151838201526020016136d1565b838111156111a85750506000910152565b6000816137095761370961378b565b506000190190565b600181811c9082168061372557607f821691505b6020821081141561180657634e487b7160e01b600052602260045260246000fd5b600060001982141561375a5761375a61378b565b5060010190565b600082613770576137706137a1565b500690565b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052603160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160e01b0319811681146122d357600080fdfea2646970667358221220dae9601cc6aa1fba524034cb8a7b4712794491d5df82b16c3aaddf921884c1fd64736f6c63430008070033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
bdd3ef7aa3fe0f5e1ca451a428919fed839d046e4397767d9d8d98271dac4a7f000000000000000000000000b60d7d1d5f63f8f720526919b770ff3985e183e4799a04ec1676eb17f6792c74bbd3482bb9063e1274a084903d0bef83c5414231
-----Decoded View---------------
Arg [0] : _secretCommit (uint256): 85861585936666380609408835558486275043416692853044039650146259634895094303359
Arg [1] : _renderer (address): 0xb60d7D1D5F63f8F720526919b770FF3985e183e4
Arg [2] : _merkleRoot (bytes32): 0x799a04ec1676eb17f6792c74bbd3482bb9063e1274a084903d0bef83c5414231
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : bdd3ef7aa3fe0f5e1ca451a428919fed839d046e4397767d9d8d98271dac4a7f
Arg [1] : 000000000000000000000000b60d7d1d5f63f8f720526919b770ff3985e183e4
Arg [2] : 799a04ec1676eb17f6792c74bbd3482bb9063e1274a084903d0bef83c5414231
Deployed Bytecode Sourcemap
73373:21280:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;94469:181;;;;;;;;;;-1:-1:-1;94469:181:0;;;;;:::i;:::-;;:::i;:::-;;;8610:14:1;;8603:22;8585:41;;8573:2;8558:18;94469:181:0;;;;;;;;53872:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;55385:171::-;;;;;;;;;;-1:-1:-1;55385:171:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;7271:32:1;;;7253:51;;7241:2;7226:18;55385:171:0;7107:203:1;54902:417:0;;;;;;;;;;-1:-1:-1;54902:417:0;;;;;:::i;:::-;;:::i;75622:144::-;;;;;;;;;;-1:-1:-1;75714:8:0;;75695:15;:27;;75622:144;;83391:112;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;84199:96::-;;;;;;;;;;-1:-1:-1;84267:16:0;;:20;;84199:96;;94112:154;;;;;;;;;;-1:-1:-1;94112:154:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;;9637:33:1;;;9619:52;;9607:2;9592:18;94112:154:0;9475:202:1;67784:113:0;;;;;;;;;;-1:-1:-1;67872:10:0;:17;67784:113;;;17855:25:1;;;17843:2;17828:18;67784:113:0;17709:177:1;56085:336:0;;;;;;;;;;-1:-1:-1;56085:336:0;;;;;:::i;:::-;;:::i;81810:47::-;;;;;;;;;;;;81852:5;81810:47;;67452:256;;;;;;;;;;-1:-1:-1;67452:256:0;;;;;:::i;:::-;;:::i;78723:661::-;;;:::i;89469:305::-;;;;;;;;;;-1:-1:-1;89469:305:0;;;;;:::i;:::-;;:::i;76961:435::-;;;;;;;;;;;;;:::i;56492:185::-;;;;;;;;;;-1:-1:-1;56492:185:0;;;;;:::i;:::-;;:::i;89782:2004::-;;;;;;;;;;-1:-1:-1;89782:2004:0;;;;;:::i;:::-;;:::i;91794:1972::-;;;;;;;;;;-1:-1:-1;91794:1972:0;;;;;:::i;:::-;;:::i;84435:118::-;;;;;;;;;;;;;:::i;67974:233::-;;;;;;;;;;-1:-1:-1;67974:233:0;;;;;:::i;:::-;;:::i;74508:35::-;;;;;;;;;;;;;;;;76768:154;;;;;;;;;;;;;:::i;53583:222::-;;;;;;;;;;-1:-1:-1;53583:222:0;;;;;:::i;:::-;;:::i;81864:43::-;;;;;;;;;;;;81905:2;81864:43;;53314:207;;;;;;;;;;-1:-1:-1;53314:207:0;;;;;:::i;:::-;;:::i;32353:103::-;;;;;;;;;;;;;:::i;81740:28::-;;;;;;;;;;;;;;;;85399:371;;;:::i;81667:31::-;;;;;;;;;;;;;;;;80266:36;;;;;;;;;;-1:-1:-1;80266:36:0;;;;-1:-1:-1;;;;;80266:36:0;;;31705:87;;;;;;;;;;-1:-1:-1;31778:6:0;;-1:-1:-1;;;;;31778:6:0;31705:87;;54041:104;;;;;;;;;;;;;:::i;80340:206::-;;;;;;;;;;-1:-1:-1;80340:206:0;;;;;:::i;:::-;;:::i;75774:322::-;;;;;;;;;;-1:-1:-1;75774:322:0;;;;;:::i;:::-;;:::i;55628:155::-;;;;;;;;;;-1:-1:-1;55628:155:0;;;;;:::i;:::-;;:::i;76161:575::-;;;;;;;;;;-1:-1:-1;76161:575:0;;;;;:::i;:::-;;:::i;56748:323::-;;;;;;;;;;-1:-1:-1;56748:323:0;;;;;:::i;:::-;;:::i;84561:660::-;;;;;;;;;;;;;:::i;74469:32::-;;;;;;;;;;-1:-1:-1;74469:32:0;;;;-1:-1:-1;;;74469:32:0;;;;;;;;;;;;;:::i;84303:124::-;;;;;;;;;;;;;:::i;80554:240::-;;;;;;;;;;-1:-1:-1;80554:240:0;;;;;:::i;:::-;;:::i;77433:1261::-;;;;;;:::i;:::-;;:::i;83561:630::-;;;;;;;;;;-1:-1:-1;83561:630:0;;;;;:::i;:::-;;:::i;81973:49::-;;;;;;;;;;-1:-1:-1;81973:49:0;;;;;:::i;:::-;;;;;;;;;;;;;;81705:28;;;;;;;;;;;;;;;;81775:26;;;;;;;;;;;;;;;;85890:3464;;;;;;;;;;;;;:::i;74677:45::-;;;;;;;;;;;;74714:8;74677:45;;85229:132;;;;;;;;;;;;;:::i;81916:50::-;;;;;;;;;;-1:-1:-1;81916:50:0;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;81916:50:0;;;55854:164;;;;;;;;;;-1:-1:-1;55854:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;55975:25:0;;;55951:4;55975:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;55854:164;82590:739;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;32611:201::-;;;;;;;;;;-1:-1:-1;32611:201:0;;;;;:::i;:::-;;:::i;74729:47::-;;;;;;;;;;;;74765:11;74729:47;;89362:99;;;;;;;;;;-1:-1:-1;89362:99:0;;;;;:::i;:::-;;:::i;80802:483::-;;;;;;;;;;-1:-1:-1;80802:483:0;;;;;:::i;:::-;;:::i;94469:181::-;94581:4;94605:37;94629:12;94605:23;:37::i;:::-;94598:44;94469:181;-1:-1:-1;;94469:181:0:o;53872:100::-;53926:13;53959:5;53952:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;53872:100;:::o;55385:171::-;55461:7;55481:23;55496:7;55481:14;:23::i;:::-;-1:-1:-1;55524:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;55524:24:0;;55385:171::o;54902:417::-;54983:13;54999:23;55014:7;54999:14;:23::i;:::-;54983:39;;55047:5;-1:-1:-1;;;;;55041:11:0;:2;-1:-1:-1;;;;;55041:11:0;;;55033:57;;;;-1:-1:-1;;;55033:57:0;;15364:2:1;55033:57:0;;;15346:21:1;15403:2;15383:18;;;15376:30;15442:34;15422:18;;;15415:62;-1:-1:-1;;;15493:18:1;;;15486:31;15534:19;;55033:57:0;;;;;;;;;30330:10;-1:-1:-1;;;;;55125:21:0;;;;:62;;-1:-1:-1;55150:37:0;55167:5;30330:10;55854:164;:::i;55150:37::-;55103:174;;;;-1:-1:-1;;;55103:174:0;;13858:2:1;55103:174:0;;;13840:21:1;13897:2;13877:18;;;13870:30;13936:34;13916:18;;;13909:62;14007:32;13987:18;;;13980:60;14057:19;;55103:174:0;13656:426:1;55103:174:0;55290:21;55299:2;55303:7;55290:8;:21::i;:::-;54972:347;54902:417;;:::o;83391:112::-;83435:16;83471:24;83484:10;83471:12;:24::i;:::-;83464:31;;83391:112;:::o;94112:154::-;-1:-1:-1;;;94112:154:0;;;;;;;:::o;56085:336::-;56280:41;30330:10;56313:7;56280:18;:41::i;:::-;56272:100;;;;-1:-1:-1;;;56272:100:0;;;;;;;:::i;:::-;56385:28;56395:4;56401:2;56405:7;56385:9;:28::i;67452:256::-;67549:7;67585:23;67602:5;67585:16;:23::i;:::-;67577:5;:31;67569:87;;;;-1:-1:-1;;;67569:87:0;;10688:2:1;67569:87:0;;;10670:21:1;10727:2;10707:18;;;10700:30;10766:34;10746:18;;;10739:62;-1:-1:-1;;;10817:18:1;;;10810:41;10868:19;;67569:87:0;10486:407:1;67569:87:0;-1:-1:-1;;;;;;67674:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;67452:256::o;78723:661::-;75026:21;75017:5;;-1:-1:-1;;;75017:5:0;;;;:30;;;;;;;;:::i;:::-;;;:52;;;-1:-1:-1;75714:8:0;;75695:15;:27;;75051:18;75013:105;;;75093:13;;-1:-1:-1;;;75093:13:0;;;;;;;;;;;75013:105;78793:13:::1;78809:21;74765:11;78809:9;:21;:::i;:::-;78793:37:::0;-1:-1:-1;78847:10:0;78843:127:::1;;78881:18;;-1:-1:-1::0;;;78881:18:0::1;;;;;;;;;;;78843:127;78929:2;78921:5;:10;78917:53;;;-1:-1:-1::0;78956:2:0::1;78917:53;79008:9;79003:106;79027:5;79023:1;:9;79003:106;;;79050:16;:14;:16::i;:::-;79092:3;;79003:106;;;;79121:6;79965:10:::0;:50;;-1:-1:-1;;79997:12:0;:16;79987:27;79965:50;;;79814:220;79121:6:::1;79191:14;79221:17;79233:5:::0;74765:11:::1;79221:17;:::i;:::-;79208:31;::::0;:9:::1;:31;:::i;:::-;79191:48:::0;-1:-1:-1;79254:10:0;;79250:127:::1;;79299:35;::::0;79282:12:::1;::::0;79299:10:::1;::::0;79323:6;;79282:12;79299:35;79282:12;79299:35;79323:6;79299:10;:35:::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79281:53;;;79357:7;79349:16;;;::::0;::::1;79250:127;78782:602;;78723:661::o:0;89469:305::-;82098:11;:9;:11::i;:::-;82093:70;;82133:18;;-1:-1:-1;;;82133:18:0;;;;;;;;;;;82093:70;89578:2:::1;89559:9;:16;:21;89555:79;;;89604:18;;-1:-1:-1::0;;;89604:18:0::1;;;;;;;;;;;89555:79;89651:9;89646:121;89666:9;:16;89662:1;:20;89646:121;;;89700:24;89711:9;89721:1;89711:12;;;;;;;;:::i;:::-;;;;;;;89700:10;:24::i;:::-;89750:3;;89646:121;;76961:435:::0;31591:13;:11;:13::i;:::-;84267:16;;:20;77051:68:::1;;77092:15;;-1:-1:-1::0;;;77092:15:0::1;;;;;;;;;;;77051:68;77198:19;::::0;-1:-1:-1;;;77198:19:0;::::1;;;77193:85;;77241:25;;-1:-1:-1::0;;;77241:25:0::1;;;;;;;;;;;77193:85;77288:19;:27:::0;;-1:-1:-1;;;;77288:27:0;::::1;::::0;;;-1:-1:-1;;;;;31778:6:0;77378:5:::1;77347:28;:21;77371:4;77347:28;:::i;:::-;:36;;;;:::i;:::-;77326:62;::::0;::::1;::::0;;;;;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;54972:347:::0;54902:417;;:::o;56492:185::-;56630:39;56647:4;56653:2;56657:7;56630:39;;;;;;;;;;;;:16;:39::i;89782:2004::-;89845:25;;;;:15;:25;;;;;;-1:-1:-1;;;;;89845:25:0;89874:10;89845:39;89841:94;;89908:15;;-1:-1:-1;;;89908:15:0;;;;;;;;;;;89841:94;90047:7;;90058:1;90047:12;;:37;;;;;90063:21;:19;:21::i;:::-;90043:95;;;90108:18;;-1:-1:-1;;;90108:18:0;;;;;;;;;;;90043:95;90223:12;;90250:17;90246:76;;90291:19;;-1:-1:-1;;;90291:19:0;;;;;;;;;;;90246:76;90378:24;;;;:14;:24;;;;;;;;:32;;;90454:15;:25;;;;;90447:32;;-1:-1:-1;;;;;;90447:32:0;;;90581:7;;90557:31;;:21;:31;:::i;:::-;90534:54;;90599:15;90605:8;90599:5;:15::i;:::-;90625:9;:11;;;:9;:11;;;:::i;:::-;;;;-1:-1:-1;;90647:7:0;:9;;;:7;:9;;;:::i;:::-;;;;-1:-1:-1;;90667:42:0;;90675:10;;90667:42;;;;;90696:12;;90667:42;;;;90696:12;90675:10;90667:42;;;;;;;;;;;;;;;;;;;;;90814:7;;90825:1;90814:12;90810:969;;;90912:21;;90948:422;90972:24;90990:4;90972:9;:24::i;:::-;90968:1;:28;90948:422;;;91034:37;91062:4;91069:1;91034:19;:37::i;:::-;91136:1;91094:30;;;:15;:30;;;;;;91018:53;;-1:-1:-1;;;;;;91094:30:0;:44;91090:230;;91248:8;:24;;;91295:5;;91090:230;91349:3;;90948:422;;;-1:-1:-1;91449:8:0;;;91434:24;;;;:14;:24;;;;;;;:32;;;91508:8;;91542;;91508:43;;-1:-1:-1;;;91508:43:0;;-1:-1:-1;;;;;91508:8:0;;;;:33;;:43;;;;17855:25:1;;;17843:2;17828:18;;17709:177;91508:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;91649:8:0;;91633:25;;;;:15;:25;;;;;;;91625:66;;-1:-1:-1;;;;;91633:25:0;;;;-1:-1:-1;91669:21:0;91625:66;;;;;-1:-1:-1;91669:21:0;91625:66;91633:25;91625:66;91669:21;91633:25;91625:66;;;;;;;;;;;;;;;;;;;;-1:-1:-1;91747:8:0;;91731:25;;;;:15;:25;;;;;;91706:61;;91724:4;;-1:-1:-1;;;;;91731:25:0;;91706:9;:61::i;:::-;90828:951;89830:1956;;89782:2004;:::o;91794:1972::-;91856:25;;;;:15;:25;;;;;;-1:-1:-1;;;;;91856:25:0;91885:10;91856:39;91852:94;;91919:15;;-1:-1:-1;;;91919:15:0;;;;;;;;;;;91852:94;92058:7;;92069:1;92058:12;;:37;;;;;92074:21;:19;:21::i;:::-;92054:95;;;92119:18;;-1:-1:-1;;;92119:18:0;;;;;;;;;;;92054:95;92234:12;;92261:17;92257:76;;92302:19;;-1:-1:-1;;;92302:19:0;;;;;;;;;;;92257:76;92389:24;;;;:14;:24;;;;;;;:32;;;92457:8;;:37;;-1:-1:-1;;;92457:37:0;;;;;17855:25:1;;;-1:-1:-1;;;;;92457:8:0;;;;:27;;17828:18:1;;92457:37:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;92536:25:0;;;;:15;:25;;;;;92529:32;;-1:-1:-1;;;;;;92529:32:0;;;-1:-1:-1;92601:46:0;92619:4;92626:10;92552:8;92601:9;:46::i;:::-;92658:9;:11;;;:9;:11;;;:::i;:::-;;;;-1:-1:-1;;92680:7:0;:9;;;:7;:9;;;:::i;:::-;;;;;;92794:7;;92805:1;92794:12;92790:969;;;92892:21;;92928:422;92952:24;92970:4;92952:9;:24::i;:::-;92948:1;:28;92928:422;;;93014:37;93042:4;93049:1;93014:19;:37::i;:::-;93116:1;93074:30;;;:15;:30;;;;;;92998:53;;-1:-1:-1;;;;;;93074:30:0;:44;93070:230;;93228:8;:24;;;93275:5;;93070:230;93329:3;;92928:422;;;-1:-1:-1;93429:8:0;;;93414:24;;;;:14;:24;;;;;;;:32;;;93488:8;;93522;;93488:43;;-1:-1:-1;;;93488:43:0;;-1:-1:-1;;;;;93488:8:0;;;;:33;;:43;;;;17855:25:1;;;17843:2;17828:18;;17709:177;93488:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;93629:8:0;;93613:25;;;;:15;:25;;;;;;;93605:66;;-1:-1:-1;;;;;93613:25:0;;;;-1:-1:-1;93649:21:0;93605:66;;;;;-1:-1:-1;93649:21:0;93605:66;93613:25;93605:66;93649:21;93613:25;93605:66;;;;;;;;;;;;;;;;;;;;-1:-1:-1;93727:8:0;;93711:25;;;;:15;:25;;;;;;93686:61;;93704:4;;-1:-1:-1;;;;;93711:25:0;;93686:9;:61::i;84435:118::-;84484:7;81852:5;84511:16;;:34;;;;:::i;67974:233::-;68049:7;68085:30;67872:10;:17;;67784:113;68085:30;68077:5;:38;68069:95;;;;-1:-1:-1;;;68069:95:0;;15766:2:1;68069:95:0;;;15748:21:1;15805:2;15785:18;;;15778:30;15844:34;15824:18;;;15817:62;-1:-1:-1;;;15895:18:1;;;15888:42;15947:19;;68069:95:0;15564:408:1;68069:95:0;68182:10;68193:5;68182:17;;;;;;;;:::i;:::-;;;;;;;;;68175:24;;67974:233;;;:::o;76768:154::-;31591:13;:11;:13::i;:::-;75192:19:::1;75183:5;::::0;-1:-1:-1;;;75183:5:0;::::1;;;:28;::::0;::::1;;;;;;:::i;:::-;;75179:85;;75235:17;;-1:-1:-1::0;;;75235:17:0::1;;;;;;;;;;;75179:85;76835:5:::2;:29:::0;;-1:-1:-1;;;;76835:29:0::2;-1:-1:-1::0;;;76835:29:0::2;::::0;;76886:28:::2;74714:8;76886:15;:28;:::i;:::-;76875:8;:39:::0;76768:154::o;53583:222::-;53655:7;53691:16;;;:7;:16;;;;;;-1:-1:-1;;;;;53691:16:0;53726:19;53718:56;;;;-1:-1:-1;;;53718:56:0;;15011:2:1;53718:56:0;;;14993:21:1;15050:2;15030:18;;;15023:30;-1:-1:-1;;;15069:18:1;;;15062:54;15133:18;;53718:56:0;14809:348:1;53314:207:0;53386:7;-1:-1:-1;;;;;53414:19:0;;53406:73;;;;-1:-1:-1;;;53406:73:0;;13448:2:1;53406:73:0;;;13430:21:1;13487:2;13467:18;;;13460:30;13526:34;13506:18;;;13499:62;-1:-1:-1;;;13577:18:1;;;13570:39;13626:19;;53406:73:0;13246:405:1;53406:73:0;-1:-1:-1;;;;;;53497:16:0;;;;;:9;:16;;;;;;;53314:207::o;32353:103::-;31591:13;:11;:13::i;:::-;32418:30:::1;32445:1;32418:18;:30::i;:::-;32353:103::o:0;85399:371::-;31591:13;:11;:13::i;:::-;75493:20:::1;75484:5;::::0;-1:-1:-1;;;75484:5:0;::::1;;;:29;::::0;::::1;;;;;;:::i;:::-;;75480:86;;75537:17;;-1:-1:-1::0;;;75537:17:0::1;;;;;;;;;;;75480:86;84267:16:::0;;:20;85475:68:::2;;85516:15;;-1:-1:-1::0;;;85516:15:0::2;;;;;;;;;;;85475:68;85557:19;::::0;-1:-1:-1;;;85557:19:0;::::2;;;85553:80;;;85600:21;;-1:-1:-1::0;;;85600:21:0::2;;;;;;;;;;;85553:80;85691:12;85672:16;:31:::0;;;85732:30:::2;::::0;81852:5:::2;::::0;85732:30:::2;:::i;:::-;85714:15;:48:::0;85399:371::o;54041:104::-;54097:13;54130:7;54123:14;;;;;:::i;80340:206::-;80422:13;80408:3;80173:12;80181:3;58643:4;58667:16;;;:7;:16;;;;;;-1:-1:-1;;;;;58667:16:0;:30;;;58578:127;80173:12;80168:71;;80209:18;;-1:-1:-1;;;80209:18:0;;;;;;;;;;;80168:71;80455:8:::1;::::0;-1:-1:-1;;;;;80455:8:0::1;:24;:8;80480:5;::::0;-1:-1:-1;;;80480:5:0;::::1;;;:29;::::0;::::1;;;;;;:::i;:::-;;80511:3;80516:21;80533:3;80516:16;:21::i;:::-;80455:83;::::0;-1:-1:-1;;;;;;80455:83:0::1;::::0;;;;;;8858:14:1;;8851:22;80455:83:0::1;::::0;::::1;8833:41:1::0;8890:18;;;8883:34;;;;8933:18;;;8926:34;8806:18;;80455:83:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;80455:83:0::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;:::-;80448:90;;80249:1;80340:206:::0;;;;:::o;75774:322::-;75829:4;;75873:11;75881:3;75873:5;:11;:::i;:::-;75846:38;-1:-1:-1;75895:23:0;75921:11;75929:3;75921:5;:11;:::i;:::-;75943:19;75965:31;;;:13;:31;;;;;;;76023:1;:20;;;76062:18;;;:26;;;;75774:322;-1:-1:-1;;;75774:322:0:o;55628:155::-;55723:52;30330:10;55756:8;55766;55723:18;:52::i;76161:575::-;31591:13;:11;:13::i;:::-;75339:21:::1;75330:5;::::0;-1:-1:-1;;;75330:5:0;::::1;;;:30;::::0;::::1;;;;;;:::i;:::-;;75326:88;;75384:18;;-1:-1:-1::0;;;75384:18:0::1;;;;;;;;;;;75326:88;75714:8:::0;;75695:15;:27;;76251:80:::2;;76298:21;;-1:-1:-1::0;;;76298:21:0::2;;;;;;;;;;;76251:80;76402:6;::::0;76365:31:::2;::::0;;::::2;::::0;::::2;6367:19:1::0;;;6402:12;76365:31:0::2;;;;;;;;;;;;76355:42;;;;;;76347:51;;:61;76343:116;;76432:15;;-1:-1:-1::0;;;76432:15:0::2;;;;;;;;;;;76343:116;76605:10;::::0;;76589:26;;;::::2;76580:6;:35:::0;-1:-1:-1;76670:17:0;;76700:5:::2;:28:::0;;-1:-1:-1;;;;76700:28:0::2;::::0;;76161:575::o;56748:323::-;56922:41;30330:10;56955:7;56922:18;:41::i;:::-;56914:100;;;;-1:-1:-1;;;56914:100:0;;;;;;;:::i;:::-;57025:38;57039:4;57045:2;57049:7;57058:4;57025:13;:38::i;84561:660::-;84615:7;84641;;84652:1;84641:12;84637:53;;;-1:-1:-1;84677:1:0;;84561:660::o;84637:53::-;84810:7;;84721:1;;84821:4;-1:-1:-1;84806:117:0;;84842:14;84869:4;84859:7;;:14;;;;:::i;:::-;84842:31;-1:-1:-1;84899:12:0;84908:3;84842:31;84899:12;:::i;:::-;84888:23;;84827:96;84806:117;85000:7;;84988:8;:19;84984:74;;85045:1;85035:7;;:11;;;;:::i;:::-;85024:22;;84984:74;85142:2;85131:8;:13;85127:59;;;-1:-1:-1;85172:2:0;85127:59;85205:8;84561:660;-1:-1:-1;84561:660:0:o;84303:124::-;84345:4;84369:13;84267:16;;:20;;;84199:96;84369:13;:50;;;;;84401:18;:16;:18::i;:::-;84386:12;:33;84362:57;;84303:124;:::o;80554:240::-;80636:13;80622:3;80173:12;80181:3;58643:4;58667:16;;;:7;:16;;;;;;-1:-1:-1;;;;;58667:16:0;:30;;;58578:127;80173:12;80168:71;;80209:18;;-1:-1:-1;;;80209:18:0;;;;;;;;;;;80168:71;80669:8:::1;::::0;-1:-1:-1;;;;;80669:8:0::1;:23;:8;80693:5;::::0;-1:-1:-1;;;80693:5:0;::::1;;;:29;::::0;::::1;;;;;;:::i;:::-;;80724:3;80729:21;80746:3;80729:16;:21::i;:::-;80752:19;::::0;;;:14:::1;:19;::::0;;;;;80773:12:::1;80767:3:::0;80773:7:::1;:12::i;:::-;80669:117;::::0;-1:-1:-1;;;;;;80669:117:0::1;::::0;;;;;;9249:14:1;;9242:22;80669:117:0::1;::::0;::::1;9224:41:1::0;9281:18;;;9274:34;;;;9324:18;;;9317:34;;;;9367:18;;;9360:34;-1:-1:-1;;;;;9431:32:1;9410:19;;;9403:61;9196:19;;80669:117:0::1;8971:499:1::0;77433:1261:0;75192:19;75183:5;;-1:-1:-1;;;75183:5:0;;;;:28;;;;;;;;:::i;:::-;;75179:85;;75235:17;;-1:-1:-1;;;75235:17:0;;;;;;;;;;;75179:85;77635:17:::1;77645:6;77635:9;:17::i;:::-;77631:73;;;77676:16;;-1:-1:-1::0;;;77676:16:0::1;;;;;;;;;;;77631:73;77762:12:::0;77758:72:::1;;77798:20;;-1:-1:-1::0;;;77798:20:0::1;;;;;;;;;;;77758:72;77873:13;77889:21;77901:9:::0;77889;:21:::1;:::i;:::-;77873:37;;77935:5;77925:7;:15;77921:75;;;77964:20;;-1:-1:-1::0;;;77964:20:0::1;;;;;;;;;;;77921:75;78038:18;78085:9;78075:7;:19;78071:84;;;78124:19;78134:9:::0;78124:7;:19:::1;:::i;:::-;78111:32;;78071:84;78181:22;74765:11;78181:10:::0;:22:::1;:::i;:::-;78169:9;:34;78165:93;;;78227:19;;-1:-1:-1::0;;;78227:19:0::1;;;;;;;;;;;78165:93;78331:58;::::0;;::::1;::::0;::::1;6638:19:1::0;;;-1:-1:-1;;78356:10:0::1;6695:2:1::0;6691:15;6687:53;6673:12;;;6666:75;;;;6757:12;;;6750:28;;;6794:12;;;6787:28;;;78306:12:0::1;::::0;6831:13:1;;78331:58:0::1;;;;;;;;;;;;78321:69;;;;;;78306:84;;78406:50;78425:12;;78406:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;78439:10:0::1;::::0;-1:-1:-1;78451:4:0;;-1:-1:-1;78406:18:0::1;::::0;-1:-1:-1;78406:50:0:i:1;:::-;78401:105;;78480:14;;-1:-1:-1::0;;;78480:14:0::1;;;;;;;;;;;78401:105;78555:19;78567:6;78555:11;:19::i;:::-;78592:9;78587:81;78611:7;78607:1;:11;78587:81;;;78640:16;:14;:16::i;:::-;78620:3:::0;::::1;::::0;::::1;:::i;:::-;;;;78587:81;;;;78680:6;79965:10:::0;:50;;-1:-1:-1;;79997:12:0;:16;79987:27;79965:50;;;79814:220;78680:6:::1;77581:1113;;;77433:1261:::0;;;;;;:::o;83561:630::-;83620:16;83707:4;83649:22;83741:25;83707:4;83741:9;:25::i;:::-;83725:41;;83777:24;83818:5;83804:20;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;83804:20:0;;83777:47;;83837:13;83872:9;83867:221;83891:5;83887:1;:9;83867:221;;;83918:10;83931:38;83951:14;83967:1;83931:19;:38::i;:::-;83990:19;;;;:15;:19;;;;;;;;-1:-1:-1;;;;;;83990:29:0;;;:19;;:29;83986:91;;;84059:2;84040:7;84048;;;;:::i;:::-;;;84040:16;;;;;;;;:::i;:::-;;;;;;:21;;;;;83986:91;-1:-1:-1;83898:3:0;;;;:::i;:::-;;;;83867:221;;;-1:-1:-1;84124:22:0;;84131:7;83561:630;-1:-1:-1;;;;83561:630:0:o;85890:3464::-;84267:16;;85932:70;;85974:16;;-1:-1:-1;;;85974:16:0;;;;;;;;;;;85932:70;86017:21;:19;:21::i;:::-;86012:80;;86062:18;;-1:-1:-1;;;86062:18:0;;;;;;;;;;;86012:80;86108:7;;86119:1;86108:12;86104:69;;;86144:17;;-1:-1:-1;;;86144:17:0;;;;;;;;;;;86104:69;86187:7;;86183:62;;86223:10;;-1:-1:-1;;;86223:10:0;;;;;;;;;;;86183:62;86346:20;86433:3;81905:2;86397:15;;:32;;;;:::i;:::-;86381:49;;:12;:49;:::i;:::-;:55;86377:416;;;86644:1;81905:2;86594:29;81905:2;86594:12;:29;:::i;:::-;86593:48;;;;:::i;:::-;:52;;;;:::i;:::-;86578:67;;86377:416;;;86780:1;81905:2;86744:15;;:32;;;;:::i;:::-;86743:38;;;;:::i;:::-;86728:53;;86377:416;86829:23;;86871:12;86864:20;;;;:::i;:::-;86940:12;86922:15;:30;86963:12;:14;;;:12;:14;;;:::i;:::-;;;;;;87035:19;87057:23;:21;:23::i;:::-;87113:13;;;87123:2;87113:13;;;;;;;;;87035:45;;-1:-1:-1;87091:19:0;;87113:13;;;;;;;;;;;-1:-1:-1;;87091:35:0;-1:-1:-1;87205:1:0;87188:1139;87213:11;87208:1;:16;87188:1139;;87343:1;87333:7;:11;87323:21;;87455:7;87450:2;87442:6;87438:15;87431:32;87563:15;87610:24;87628:4;87610:9;:24::i;:::-;87589:17;;;;;;87581:53;;;;:::i;:::-;87563:71;;87695:20;87718:43;87746:4;87753:7;87718:19;:43::i;:::-;87695:66;;87776:19;87782:12;87776:5;:19::i;:::-;87937:1;87896:29;;;:15;:29;;;;;;-1:-1:-1;;;;;87896:29:0;87892:393;;-1:-1:-1;;88032:3:0;;;;87892:393;;;88182:29;;;;:15;:29;;;;;88175:36;;-1:-1:-1;;;;;;88175:36:0;;;88230:9;:11;;;;;;:::i;:::-;;;;-1:-1:-1;;88260:7:0;:9;;;:7;:9;;;:::i;:::-;;;;;;87892:393;-1:-1:-1;;88310:3:0;;87188:1139;;;;88375:7;;88386:1;88375:12;88371:976;;;88473:21;;88509:422;88533:24;88551:4;88533:9;:24::i;:::-;88529:1;:28;88509:422;;;88595:37;88623:4;88630:1;88595:19;:37::i;:::-;88697:1;88655:30;;;:15;:30;;;;;;88579:53;;-1:-1:-1;;;;;;88655:30:0;:44;88651:230;;88809:8;:24;;;88856:5;;88651:230;88910:3;;88509:422;;;-1:-1:-1;89022:12:0;;89010:8;;;88995:24;;;;:14;:24;;;;;;;:39;;;;89076:8;;89110;;89076:43;;-1:-1:-1;;;89076:43:0;;;;;17855:25:1;;;;-1:-1:-1;;;;;89076:8:0;;:33;;17828:18:1;;89076:43:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;89217:8:0;;89201:25;;;;:15;:25;;;;;;;89193:66;;-1:-1:-1;;;;;89201:25:0;;;;-1:-1:-1;89237:21:0;89193:66;;;;;-1:-1:-1;89237:21:0;89193:66;89201:25;89193:66;89237:21;89201:25;89193:66;;;;;;;;;;;;;;;;;;;;-1:-1:-1;89315:8:0;;89299:25;;;;:15;:25;;;;;;89274:61;;89292:4;;-1:-1:-1;;;;;89299:25:0;;89274:9;:61::i;:::-;88389:958;85921:3433;;;;85890:3464::o;85229:132::-;85281:4;81905:2;85321:15;;:32;;;;:::i;:::-;85305:12;:48;;85298:55;;85229:132;:::o;82590:739::-;82634:21;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;82634:21:0;82682:9;;82668:23;;82717:7;;82702:12;;;:22;82752:9;;82735:14;;;:26;82792:12;;82772:17;;;:32;82829:21;82815:11;;;:35;82877:23;:21;:23::i;:::-;82861:13;;;:39;82927:8;;82911:13;;;:24;82970:18;:16;:18::i;:::-;82946:21;;;:42;83006:21;:19;:21::i;:::-;83001:118;;83095:12;81905:2;83060:15;;:32;;;;:::i;:::-;:47;;;;:::i;:::-;83044:13;;;:63;83001:118;83144:21;:19;:21::i;:::-;83131:34;;:10;;;:34;83188:11;:9;:11::i;:::-;83176:23;;:9;;;:23;84267:16;;:20;;83210:11;;;:27;83279:21;;;;83264:12;:36;:57;;;;;83320:1;83304:4;:12;;;:17;;83264:57;83248:73;;:13;;;:73;:4;82590:739::o;32611:201::-;31591:13;:11;:13::i;:::-;-1:-1:-1;;;;;32700:22:0;::::1;32692:73;;;::::0;-1:-1:-1;;;32692:73:0;;11519:2:1;32692:73:0::1;::::0;::::1;11501:21:1::0;11558:2;11538:18;;;11531:30;11597:34;11577:18;;;11570:62;-1:-1:-1;;;11648:18:1;;;11641:36;11694:19;;32692:73:0::1;11317:402:1::0;32692:73:0::1;32776:28;32795:8;32776:18;:28::i;:::-;32611:201:::0;:::o;89362:99::-;82098:11;:9;:11::i;:::-;82093:70;;82133:18;;-1:-1:-1;;;82133:18:0;;;;;;;;;;;82093:70;89433:20:::1;89444:8;89433:10;:20::i;80802:483::-:0;80878:13;80864:3;80173:12;80181:3;58643:4;58667:16;;;:7;:16;;;;;;-1:-1:-1;;;;;58667:16:0;:30;;;58578:127;80173:12;80168:71;;80209:18;;-1:-1:-1;;;80209:18:0;;;;;;;;;;;80168:71;80904:14:::1;81043:4;81019:12;81027:3:::0;81019:7:::1;:12::i;:::-;-1:-1:-1::0;;;;;81019:29:0::1;;81015:144;;;-1:-1:-1::0;81074:12:0::1;::::0;81015:144:::1;;;-1:-1:-1::0;81128:19:0::1;::::0;;;:14:::1;:19;::::0;;;;;81015:144:::1;81178:8;::::0;-1:-1:-1;;;;;81178:8:0::1;:18;:8;81197:5;::::0;-1:-1:-1;;;81197:5:0;::::1;;;:29;::::0;::::1;;;;;;:::i;:::-;;81228:3;81233:21;81250:3;81233:16;:21::i;:::-;81256:6;81264:12;81272:3;81264:7;:12::i;:::-;81178:99;::::0;-1:-1:-1;;;;;;81178:99:0::1;::::0;;;;;;9249:14:1;;9242:22;81178:99:0::1;::::0;::::1;9224:41:1::0;9281:18;;;9274:34;;;;9324:18;;;9317:34;;;;9367:18;;;9360:34;-1:-1:-1;;;;;9431:32:1;9410:19;;;9403:61;9196:19;;81178:99:0::1;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;::::0;;::::1;-1:-1:-1::0;;81178:99:0::1;::::0;::::1;;::::0;::::1;::::0;;;::::1;::::0;::::1;:::i;68820:589::-:0;-1:-1:-1;;;;;69026:18:0;;69022:187;;69061:40;69093:7;70236:10;:17;;70209:24;;;;:15;:24;;;;;:44;;;70264:24;;;;;;;;;;;;70132:164;69061:40;69022:187;;;69131:2;-1:-1:-1;;;;;69123:10:0;:4;-1:-1:-1;;;;;69123:10:0;;69119:90;;69150:47;69183:4;69189:7;69150:32;:47::i;:::-;-1:-1:-1;;;;;69223:16:0;;69219:183;;69256:45;69293:7;69256:36;:45::i;69219:183::-;69329:4;-1:-1:-1;;;;;69323:10:0;:2;-1:-1:-1;;;;;69323:10:0;;69319:83;;69350:40;69378:2;69382:7;69350:27;:40::i;67144:224::-;67246:4;-1:-1:-1;;;;;;67270:50:0;;-1:-1:-1;;;67270:50:0;;:90;;;67324:36;67348:11;67324:23;:36::i;63360:135::-;58643:4;58667:16;;;:7;:16;;;;;;-1:-1:-1;;;;;58667:16:0;63434:53;;;;-1:-1:-1;;;63434:53:0;;15011:2:1;63434:53:0;;;14993:21:1;15050:2;15030:18;;;15023:30;-1:-1:-1;;;15069:18:1;;;15062:54;15133:18;;63434:53:0;14809:348:1;62639:174:0;62714:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;62714:29:0;-1:-1:-1;;;;;62714:29:0;;;;;;;;:24;;62768:23;62714:24;62768:14;:23::i;:::-;-1:-1:-1;;;;;62759:46:0;;;;;;;;;;;62639:174;;:::o;58872:264::-;58965:4;58982:13;58998:23;59013:7;58998:14;:23::i;:::-;58982:39;;59051:5;-1:-1:-1;;;;;59040:16:0;:7;-1:-1:-1;;;;;59040:16:0;;:52;;;-1:-1:-1;;;;;;55975:25:0;;;55951:4;55975:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;59060:32;59040:87;;;;59120:7;-1:-1:-1;;;;;59096:31:0;:20;59108:7;59096:11;:20::i;:::-;-1:-1:-1;;;;;59096:31:0;;59032:96;58872:264;-1:-1:-1;;;;58872:264:0:o;61895:625::-;62054:4;-1:-1:-1;;;;;62027:31:0;:23;62042:7;62027:14;:23::i;:::-;-1:-1:-1;;;;;62027:31:0;;62019:81;;;;-1:-1:-1;;;62019:81:0;;11926:2:1;62019:81:0;;;11908:21:1;11965:2;11945:18;;;11938:30;12004:34;11984:18;;;11977:62;-1:-1:-1;;;12055:18:1;;;12048:35;12100:19;;62019:81:0;11724:401:1;62019:81:0;-1:-1:-1;;;;;62119:16:0;;62111:65;;;;-1:-1:-1;;;62111:65:0;;12689:2:1;62111:65:0;;;12671:21:1;12728:2;12708:18;;;12701:30;12767:34;12747:18;;;12740:62;-1:-1:-1;;;12818:18:1;;;12811:34;12862:19;;62111:65:0;12487:400:1;62111:65:0;62189:39;62210:4;62216:2;62220:7;62189:20;:39::i;:::-;62293:29;62310:1;62314:7;62293:8;:29::i;:::-;-1:-1:-1;;;;;62335:15:0;;;;;;:9;:15;;;;;:20;;62354:1;;62335:15;:20;;62354:1;;62335:20;:::i;:::-;;;;-1:-1:-1;;;;;;;62366:13:0;;;;;;:9;:13;;;;;:18;;62383:1;;62366:13;:18;;62383:1;;62366:18;:::i;:::-;;;;-1:-1:-1;;62395:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;62395:21:0;-1:-1:-1;;;;;62395:21:0;;;;;;;;;62434:27;;62395:16;;62434:27;;;;;;;54972:347;54902:417;;:::o;79684:122::-;79730:15;79748:13;67872:10;:17;;67784:113;79748:13;79730:31;;79772:26;79778:10;79790:7;79772:5;:26::i;93805:221::-;93900:49;93913:10;93933:4;93940:8;93900:12;:49::i;:::-;93960:25;;;;:15;:25;;;;;:38;;-1:-1:-1;;;;;;93960:38:0;93988:10;93960:38;;;94009:7;:9;;;;;;:::i;:::-;;;;;;93805:221;:::o;31870:132::-;31778:6;;-1:-1:-1;;;;;31778:6:0;30330:10;31934:23;31926:68;;;;-1:-1:-1;;;31926:68:0;;14650:2:1;31926:68:0;;;14632:21:1;;;14669:18;;;14662:30;14728:34;14708:18;;;14701:62;14780:18;;31926:68:0;14448:356:1;61138:420:0;61198:13;61214:23;61229:7;61214:14;:23::i;:::-;61198:39;;61250:48;61271:5;61286:1;61290:7;61250:20;:48::i;:::-;61339:29;61356:1;61360:7;61339:8;:29::i;:::-;-1:-1:-1;;;;;61381:16:0;;;;;;:9;:16;;;;;:21;;61401:1;;61381:16;:21;;61401:1;;61381:21;:::i;:::-;;;;-1:-1:-1;;61420:16:0;;;;:7;:16;;;;;;61413:23;;-1:-1:-1;;;;;;61413:23:0;;;61454:36;61428:7;;61420:16;-1:-1:-1;;;;;61454:36:0;;;;;61420:16;;61454:36;78782:602:::1;;78723:661::o:0;32972:191::-;33065:6;;;-1:-1:-1;;;;;33082:17:0;;;-1:-1:-1;;;;;;33082:17:0;;;;;;;33115:40;;33065:6;;;33082:17;33065:6;;33115:40;;33046:16;;33115:40;33035:128;32972:191;:::o;81326:156::-;81393:7;81455:6;;81463:8;81438:34;;;;;;;;7012:19:1;;;7056:2;7047:12;;7040:28;7093:2;7084:12;;6855:247;81438:34:0;;;;-1:-1:-1;;81438:34:0;;;;;;;;;81428:45;;81438:34;81428:45;;;;;81326:156;-1:-1:-1;;81326:156:0:o;62956:315::-;63111:8;-1:-1:-1;;;;;63102:17:0;:5;-1:-1:-1;;;;;63102:17:0;;;63094:55;;;;-1:-1:-1;;;63094:55:0;;13094:2:1;63094:55:0;;;13076:21:1;13133:2;13113:18;;;13106:30;13172:27;13152:18;;;13145:55;13217:18;;63094:55:0;12892:349:1;63094:55:0;-1:-1:-1;;;;;63160:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;63160:46:0;;;;;;;;;;63222:41;;8585::1;;;63222::0;;8558:18:1;63222:41:0;;;;;;;62956:315;;;:::o;57952:313::-;58108:28;58118:4;58124:2;58128:7;58108:9;:28::i;:::-;58155:47;58178:4;58184:2;58188:7;58197:4;58155:22;:47::i;:::-;58147:110;;;;-1:-1:-1;;;58147:110:0;;;;;;;:::i;1978:190::-;2103:4;2156;2127:25;2140:5;2147:4;2127:12;:25::i;:::-;:33;;1978:190;-1:-1:-1;;;;1978:190:0:o;79425:251::-;79481:24;79508:11;79516:3;79508:5;:11;:::i;:::-;79481:38;-1:-1:-1;79530:23:0;79556:11;79564:3;79556:5;:11;:::i;:::-;79612:31;;;;:13;:31;;;;;;;;79647:1;:20;;;79612:56;;;79578:90;;;-1:-1:-1;;79425:251:0:o;70923:988::-;71189:22;71239:1;71214:22;71231:4;71214:16;:22::i;:::-;:26;;;;:::i;:::-;71251:18;71272:26;;;:17;:26;;;;;;71189:51;;-1:-1:-1;71405:28:0;;;71401:328;;-1:-1:-1;;;;;71472:18:0;;71450:19;71472:18;;;:12;:18;;;;;;;;:34;;;;;;;;;71523:30;;;;;;:44;;;71640:30;;:17;:30;;;;;:43;;;71401:328;-1:-1:-1;71825:26:0;;;;:17;:26;;;;;;;;71818:33;;;-1:-1:-1;;;;;71869:18:0;;;;;:12;:18;;;;;:34;;;;;;;71862:41;70923:988::o;72206:1079::-;72484:10;:17;72459:22;;72484:21;;72504:1;;72484:21;:::i;:::-;72516:18;72537:24;;;:15;:24;;;;;;72910:10;:26;;72459:46;;-1:-1:-1;72537:24:0;;72459:46;;72910:26;;;;;;:::i;:::-;;;;;;;;;72888:48;;72974:11;72949:10;72960;72949:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;73054:28;;;:15;:28;;;;;;;:41;;;73226:24;;;;;73219:31;73261:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;72277:1008;;;72206:1079;:::o;69710:221::-;69795:14;69812:20;69829:2;69812:16;:20::i;:::-;-1:-1:-1;;;;;69843:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;69888:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;69710:221:0:o;52945:305::-;53047:4;-1:-1:-1;;;;;;53084:40:0;;-1:-1:-1;;;53084:40:0;;:105;;-1:-1:-1;;;;;;;53141:48:0;;-1:-1:-1;;;53141:48:0;53084:105;:158;;;-1:-1:-1;;;;;;;;;;44692:40:0;;;53206:36;44583:157;94274:187;94405:48;94432:5;94439:3;94444:8;94405:26;:48::i;60470:439::-;-1:-1:-1;;;;;60550:16:0;;60542:61;;;;-1:-1:-1;;;60542:61:0;;14289:2:1;60542:61:0;;;14271:21:1;;;14308:18;;;14301:30;14367:34;14347:18;;;14340:62;14419:18;;60542:61:0;14087:356:1;60542:61:0;58643:4;58667:16;;;:7;:16;;;;;;-1:-1:-1;;;;;58667:16:0;:30;60614:58;;;;-1:-1:-1;;;60614:58:0;;12332:2:1;60614:58:0;;;12314:21:1;12371:2;12351:18;;;12344:30;12410;12390:18;;;12383:58;12458:18;;60614:58:0;12130:352:1;60614:58:0;60685:45;60714:1;60718:2;60722:7;60685:20;:45::i;:::-;-1:-1:-1;;;;;60743:13:0;;;;;;:9;:13;;;;;:18;;60760:1;;60743:13;:18;;60760:1;;60743:18;:::i;:::-;;;;-1:-1:-1;;60772:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;60772:21:0;-1:-1:-1;;;;;60772:21:0;;;;;;;;60811:33;;60772:16;;;60811:33;;60772:16;;60811:33;78782:602:::1;;78723:661::o:0;64059:853::-;64213:4;-1:-1:-1;;;;;64234:13:0;;34704:19;:23;64230:675;;64270:71;;-1:-1:-1;;;64270:71:0;;-1:-1:-1;;;;;64270:36:0;;;;;:71;;30330:10;;64321:4;;64327:7;;64336:4;;64270:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64270:71:0;;;;;;;;-1:-1:-1;;64270:71:0;;;;;;;;;;;;:::i;:::-;;;64266:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;64511:13:0;;64507:328;;64554:60;;-1:-1:-1;;;64554:60:0;;;;;;;:::i;64507:328::-;64785:6;64779:13;64770:6;64766:2;64762:15;64755:38;64266:584;-1:-1:-1;;;;;;64392:51:0;-1:-1:-1;;;64392:51:0;;-1:-1:-1;64385:58:0;;64230:675;-1:-1:-1;64889:4:0;64882:11;;2845:296;2928:7;2971:4;2928:7;2986:118;3010:5;:12;3006:1;:16;2986:118;;;3059:33;3069:12;3083:5;3089:1;3083:8;;;;;;;;:::i;:::-;;;;;;;3059:9;:33::i;:::-;3044:48;-1:-1:-1;3024:3:0;;;;:::i;:::-;;;;2986:118;;;-1:-1:-1;3121:12:0;2845:296;-1:-1:-1;;;2845:296:0:o;9052:149::-;9115:7;9146:1;9142;:5;:51;;9277:13;9371:15;;;9407:4;9400:15;;;9454:4;9438:21;;9142:51;;;9277:13;9371:15;;;9407:4;9400:15;;;9454:4;9438:21;;9150:20;9135:58;9052:149;-1:-1:-1;;;9052:149:0:o;14:173:1:-;82:20;;-1:-1:-1;;;;;131:31:1;;121:42;;111:70;;177:1;174;167:12;192:186;251:6;304:2;292:9;283:7;279:23;275:32;272:52;;;320:1;317;310:12;272:52;343:29;362:9;343:29;:::i;383:260::-;451:6;459;512:2;500:9;491:7;487:23;483:32;480:52;;;528:1;525;518:12;480:52;551:29;570:9;551:29;:::i;:::-;541:39;;599:38;633:2;622:9;618:18;599:38;:::i;:::-;589:48;;383:260;;;;;:::o;648:328::-;725:6;733;741;794:2;782:9;773:7;769:23;765:32;762:52;;;810:1;807;800:12;762:52;833:29;852:9;833:29;:::i;:::-;823:39;;881:38;915:2;904:9;900:18;881:38;:::i;:::-;871:48;;966:2;955:9;951:18;938:32;928:42;;648:328;;;;;:::o;981:888::-;1076:6;1084;1092;1100;1153:3;1141:9;1132:7;1128:23;1124:33;1121:53;;;1170:1;1167;1160:12;1121:53;1193:29;1212:9;1193:29;:::i;:::-;1183:39;;1241:38;1275:2;1264:9;1260:18;1241:38;:::i;:::-;1231:48;;1326:2;1315:9;1311:18;1298:32;1288:42;;1381:2;1370:9;1366:18;1353:32;1408:18;1400:6;1397:30;1394:50;;;1440:1;1437;1430:12;1394:50;1463:22;;1516:4;1508:13;;1504:27;-1:-1:-1;1494:55:1;;1545:1;1542;1535:12;1494:55;1581:2;1568:16;1606:48;1622:31;1650:2;1622:31;:::i;:::-;1606:48;:::i;:::-;1677:2;1670:5;1663:17;1717:7;1712:2;1707;1703;1699:11;1695:20;1692:33;1689:53;;;1738:1;1735;1728:12;1689:53;1793:2;1788;1784;1780:11;1775:2;1768:5;1764:14;1751:45;1837:1;1832:2;1827;1820:5;1816:14;1812:23;1805:34;1858:5;1848:15;;;;;981:888;;;;;;;:::o;1874:347::-;1939:6;1947;2000:2;1988:9;1979:7;1975:23;1971:32;1968:52;;;2016:1;2013;2006:12;1968:52;2039:29;2058:9;2039:29;:::i;:::-;2029:39;;2118:2;2107:9;2103:18;2090:32;2165:5;2158:13;2151:21;2144:5;2141:32;2131:60;;2187:1;2184;2177:12;2131:60;2210:5;2200:15;;;1874:347;;;;;:::o;2226:254::-;2294:6;2302;2355:2;2343:9;2334:7;2330:23;2326:32;2323:52;;;2371:1;2368;2361:12;2323:52;2394:29;2413:9;2394:29;:::i;:::-;2384:39;2470:2;2455:18;;;;2442:32;;-1:-1:-1;;;2226:254:1:o;2485:957::-;2569:6;2600:2;2643;2631:9;2622:7;2618:23;2614:32;2611:52;;;2659:1;2656;2649:12;2611:52;2699:9;2686:23;2728:18;2769:2;2761:6;2758:14;2755:34;;;2785:1;2782;2775:12;2755:34;2823:6;2812:9;2808:22;2798:32;;2868:7;2861:4;2857:2;2853:13;2849:27;2839:55;;2890:1;2887;2880:12;2839:55;2926:2;2913:16;2948:2;2944;2941:10;2938:36;;;2954:18;;:::i;:::-;3000:2;2997:1;2993:10;2983:20;;3023:28;3047:2;3043;3039:11;3023:28;:::i;:::-;3085:15;;;3116:12;;;;3148:11;;;3178;;;3174:20;;3171:33;-1:-1:-1;3168:53:1;;;3217:1;3214;3207:12;3168:53;3239:1;3230:10;;3249:163;3263:2;3260:1;3257:9;3249:163;;;3320:17;;3308:30;;3281:1;3274:9;;;;;3358:12;;;;3390;;3249:163;;;-1:-1:-1;3431:5:1;2485:957;-1:-1:-1;;;;;;;;2485:957:1:o;3447:245::-;3505:6;3558:2;3546:9;3537:7;3533:23;3529:32;3526:52;;;3574:1;3571;3564:12;3526:52;3613:9;3600:23;3632:30;3656:5;3632:30;:::i;3697:249::-;3766:6;3819:2;3807:9;3798:7;3794:23;3790:32;3787:52;;;3835:1;3832;3825:12;3787:52;3867:9;3861:16;3886:30;3910:5;3886:30;:::i;3951:635::-;4031:6;4084:2;4072:9;4063:7;4059:23;4055:32;4052:52;;;4100:1;4097;4090:12;4052:52;4133:9;4127:16;4166:18;4158:6;4155:30;4152:50;;;4198:1;4195;4188:12;4152:50;4221:22;;4274:4;4266:13;;4262:27;-1:-1:-1;4252:55:1;;4303:1;4300;4293:12;4252:55;4332:2;4326:9;4357:48;4373:31;4401:2;4373:31;:::i;4357:48::-;4428:2;4421:5;4414:17;4468:7;4463:2;4458;4454;4450:11;4446:20;4443:33;4440:53;;;4489:1;4486;4479:12;4440:53;4502:54;4553:2;4548;4541:5;4537:14;4532:2;4528;4524:11;4502:54;:::i;:::-;4575:5;3951:635;-1:-1:-1;;;;;3951:635:1:o;4591:180::-;4650:6;4703:2;4691:9;4682:7;4678:23;4674:32;4671:52;;;4719:1;4716;4709:12;4671:52;-1:-1:-1;4742:23:1;;4591:180;-1:-1:-1;4591:180:1:o;4776:889::-;4898:6;4906;4914;4922;4930;4938;4991:3;4979:9;4970:7;4966:23;4962:33;4959:53;;;5008:1;5005;4998:12;4959:53;5044:9;5031:23;5021:33;;5101:2;5090:9;5086:18;5073:32;5063:42;;5152:2;5141:9;5137:18;5124:32;5114:42;;5207:2;5196:9;5192:18;5179:32;5230:18;5271:2;5263:6;5260:14;5257:34;;;5287:1;5284;5277:12;5257:34;5325:6;5314:9;5310:22;5300:32;;5370:7;5363:4;5359:2;5355:13;5351:27;5341:55;;5392:1;5389;5382:12;5341:55;5432:2;5419:16;5458:2;5450:6;5447:14;5444:34;;;5474:1;5471;5464:12;5444:34;5527:7;5522:2;5512:6;5509:1;5505:14;5501:2;5497:23;5493:32;5490:45;5487:65;;;5548:1;5545;5538:12;5487:65;5579:2;5575;5571:11;5561:21;;5601:6;5591:16;;;;;5654:3;5643:9;5639:19;5626:33;5616:43;;4776:889;;;;;;;;:::o;5766:257::-;5807:3;5845:5;5839:12;5872:6;5867:3;5860:19;5888:63;5944:6;5937:4;5932:3;5928:14;5921:4;5914:5;5910:16;5888:63;:::i;:::-;6005:2;5984:15;-1:-1:-1;;5980:29:1;5971:39;;;;6012:4;5967:50;;5766:257;-1:-1:-1;;5766:257:1:o;7315:488::-;-1:-1:-1;;;;;7584:15:1;;;7566:34;;7636:15;;7631:2;7616:18;;7609:43;7683:2;7668:18;;7661:34;;;7731:3;7726:2;7711:18;;7704:31;;;7509:4;;7752:45;;7777:19;;7769:6;7752:45;:::i;:::-;7744:53;7315:488;-1:-1:-1;;;;;;7315:488:1:o;7808:632::-;7979:2;8031:21;;;8101:13;;8004:18;;;8123:22;;;7950:4;;7979:2;8202:15;;;;8176:2;8161:18;;;7950:4;8245:169;8259:6;8256:1;8253:13;8245:169;;;8320:13;;8308:26;;8389:15;;;;8354:12;;;;8281:1;8274:9;8245:169;;;-1:-1:-1;8431:3:1;;7808:632;-1:-1:-1;;;;;;7808:632:1:o;9919:338::-;10061:2;10046:18;;10094:1;10083:13;;10073:144;;10139:10;10134:3;10130:20;10127:1;10120:31;10174:4;10171:1;10164:15;10202:4;10199:1;10192:15;10073:144;10226:25;;;9919:338;:::o;10262:219::-;10411:2;10400:9;10393:21;10374:4;10431:44;10471:2;10460:9;10456:18;10448:6;10431:44;:::i;10898:414::-;11100:2;11082:21;;;11139:2;11119:18;;;11112:30;11178:34;11173:2;11158:18;;11151:62;-1:-1:-1;;;11244:2:1;11229:18;;11222:48;11302:3;11287:19;;10898:414::o;15977:410::-;16179:2;16161:21;;;16218:2;16198:18;;;16191:30;16257:34;16252:2;16237:18;;16230:62;-1:-1:-1;;;16323:2:1;16308:18;;16301:44;16377:3;16362:19;;15977:410::o;16392:1312::-;16538:4;16580:3;16569:9;16565:19;16557:27;;16617:6;16611:13;16600:9;16593:32;16681:4;16673:6;16669:17;16663:24;16656:4;16645:9;16641:20;16634:54;16744:4;16736:6;16732:17;16726:24;16719:4;16708:9;16704:20;16697:54;16807:4;16799:6;16795:17;16789:24;16782:4;16771:9;16767:20;16760:54;16870:4;16862:6;16858:17;16852:24;16845:4;16834:9;16830:20;16823:54;16933:4;16925:6;16921:17;16915:24;16908:4;16897:9;16893:20;16886:54;16996:4;16988:6;16984:17;16978:24;16971:4;16960:9;16956:20;16949:54;17059:4;17051:6;17047:17;17041:24;17034:4;17023:9;17019:20;17012:54;17085:6;17145:2;17137:6;17133:15;17127:22;17122:2;17111:9;17107:18;17100:50;;17169:6;17222:2;17214:6;17210:15;17204:22;17235:49;17280:2;17269:9;17265:18;17251:12;5740:13;5733:21;5721:34;;5670:91;17235:49;-1:-1:-1;;17303:6:1;17346:15;;;17340:22;5740:13;5733:21;17403:18;;;5721:34;17441:6;17484:15;;;17478:22;5740:13;5733:21;17541:18;;;5721:34;17579:6;17622:15;;;17616:22;5740:13;5733:21;17679:18;;;;5721:34;;;;16392:1312;:::o;17891:275::-;17962:2;17956:9;18027:2;18008:13;;-1:-1:-1;;18004:27:1;17992:40;;18062:18;18047:34;;18083:22;;;18044:62;18041:88;;;18109:18;;:::i;:::-;18145:2;18138:22;17891:275;;-1:-1:-1;17891:275:1:o;18171:186::-;18219:4;18252:18;18244:6;18241:30;18238:56;;;18274:18;;:::i;:::-;-1:-1:-1;18340:2:1;18319:15;-1:-1:-1;;18315:29:1;18346:4;18311:40;;18171:186::o;18362:128::-;18402:3;18433:1;18429:6;18426:1;18423:13;18420:39;;;18439:18;;:::i;:::-;-1:-1:-1;18475:9:1;;18362:128::o;18495:120::-;18535:1;18561;18551:35;;18566:18;;:::i;:::-;-1:-1:-1;18600:9:1;;18495:120::o;18620:168::-;18660:7;18726:1;18722;18718:6;18714:14;18711:1;18708:21;18703:1;18696:9;18689:17;18685:45;18682:71;;;18733:18;;:::i;:::-;-1:-1:-1;18773:9:1;;18620:168::o;18793:125::-;18833:4;18861:1;18858;18855:8;18852:34;;;18866:18;;:::i;:::-;-1:-1:-1;18903:9:1;;18793:125::o;18923:258::-;18995:1;19005:113;19019:6;19016:1;19013:13;19005:113;;;19095:11;;;19089:18;19076:11;;;19069:39;19041:2;19034:10;19005:113;;;19136:6;19133:1;19130:13;19127:48;;;-1:-1:-1;;19171:1:1;19153:16;;19146:27;18923:258::o;19186:136::-;19225:3;19253:5;19243:39;;19262:18;;:::i;:::-;-1:-1:-1;;;19298:18:1;;19186:136::o;19327:380::-;19406:1;19402:12;;;;19449;;;19470:61;;19524:4;19516:6;19512:17;19502:27;;19470:61;19577:2;19569:6;19566:14;19546:18;19543:38;19540:161;;;19623:10;19618:3;19614:20;19611:1;19604:31;19658:4;19655:1;19648:15;19686:4;19683:1;19676:15;19712:135;19751:3;-1:-1:-1;;19772:17:1;;19769:43;;;19792:18;;:::i;:::-;-1:-1:-1;19839:1:1;19828:13;;19712:135::o;19852:112::-;19884:1;19910;19900:35;;19915:18;;:::i;:::-;-1:-1:-1;19949:9:1;;19852:112::o;19969:127::-;20030:10;20025:3;20021:20;20018:1;20011:31;20061:4;20058:1;20051:15;20085:4;20082:1;20075:15;20101:127;20162:10;20157:3;20153:20;20150:1;20143:31;20193:4;20190:1;20183:15;20217:4;20214:1;20207:15;20233:127;20294:10;20289:3;20285:20;20282:1;20275:31;20325:4;20322:1;20315:15;20349:4;20346:1;20339:15;20365:127;20426:10;20421:3;20417:20;20414:1;20407:31;20457:4;20454:1;20447:15;20481:4;20478:1;20471:15;20497:127;20558:10;20553:3;20549:20;20546:1;20539:31;20589:4;20586:1;20579:15;20613:4;20610:1;20603:15;20629:127;20690:10;20685:3;20681:20;20678:1;20671:31;20721:4;20718:1;20711:15;20745:4;20742:1;20735:15;20761:127;20822:10;20817:3;20813:20;20810:1;20803:31;20853:4;20850:1;20843:15;20877:4;20874:1;20867:15;20893:131;-1:-1:-1;;;;;;20967:32:1;;20957:43;;20947:71;;21014:1;21011;21004:12
Swarm Source
ipfs://dae9601cc6aa1fba524034cb8a7b4712794491d5df82b16c3aaddf921884c1fd
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.