Feature Tip: Add private address tag to any address under My Name Tag !
ERC-721
Overview
Max Total Supply
72 BLACKSQUARE
Holders
36
Market
Volume (24H)
N/A
Min Price (24H)
N/A
Max Price (24H)
N/A
Other Info
Token Contract
Balance
1 BLACKSQUARELoading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
BlackSquare
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED // Copyright 2021; All rights reserved // Author: 0x99c520ed5a5e57b2128737531f5626d026ea39f20960b0e750077b9768543949 pragma solidity >=0.8.0 <0.9.0; import "./ERC721Common.sol"; import "./BlackSquareRandomAttributes.sol"; import "base64-sol/base64.sol"; import "@openzeppelin/contracts/finance/PaymentSplitter.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; contract BlackSquare is ERC721Common, ReentrancyGuard { using Base64 for string; /// @notice Constants defining numbers and prices of tokens. uint256 immutable public MAX_TOKENS; uint256 constant public MINT_PRICE = 0.1 ether; uint256 constant public MAX_PER_ADDRESS = 10; /// @notice An instance of RandomAttributes.sol responsible for allocating /// metadata attributes after the call to setEntropy(). BlackSquareRandomAttributes immutable public attrs; /// @notice An escrow contract to split revenues. PaymentSplitter public paymentSplitter; constructor( string memory name, string memory symbol, address openSeaProxyRegistry, uint256 maxTokens, address payable _paymentSplitter ) ERC721Common(name, symbol, openSeaProxyRegistry) { attrs = new BlackSquareRandomAttributes(maxTokens); paymentSplitter = PaymentSplitter(_paymentSplitter); MAX_TOKENS = maxTokens; } /// @notice Tracks the number of tokens already minted by an address, /// regardless of transferring out. mapping(address => uint) public minted; /// @notice Mint the specified number of tokens to the sender. /// @dev Reduces n if the origin or sender has already minted tokens or if // the total supply is insufficient. The cost is then calculated and the /// excess is reimbursed. Although it's possible for someone to set up /// multiple wallets, this was a minimal requirement included in the spec. function safeMint(uint256 n) nonReentrant payable public { /** * ##### CHECKS */ n = _capExtra(n, msg.sender, "Sender limit"); // Enforce the limit even if proxying through a contract. if (msg.sender != tx.origin) { n = _capExtra(n, tx.origin, "Origin limit"); } uint256 nextTokenId = totalSupply(); uint256 left = MAX_TOKENS - nextTokenId; require (left > 0, "Sold out"); if (n > left) { n = left; } uint256 cost = n * MINT_PRICE; require(msg.value >= cost, "Insufficient payment"); /** * ##### EFFECTS */ minted[msg.sender] += n; if (msg.sender != tx.origin) { minted[tx.origin] += n; } for (uint end = nextTokenId + n; nextTokenId < end; nextTokenId++) { _safeMint(msg.sender, nextTokenId); } /** * ##### INTERACTIONS (also nonReentrant) */ payable(paymentSplitter).transfer(cost); if (msg.value > cost) { address payable reimburse = payable(msg.sender); reimburse.transfer(msg.value - cost); } } /// @notice Changes the address of the PaymentSplitter contract. function setPaymentSplitter(address payable _paymentSplitter) onlyOwner external { paymentSplitter = PaymentSplitter(_paymentSplitter); } /// @notice Returns min(n, max(extra tokens addr can mint)). function _capExtra(uint256 n, address addr, string memory zeroMsg) internal view returns (uint256) { uint256 extra = MAX_PER_ADDRESS - minted[addr]; require (extra > 0, zeroMsg); if (n > extra) { return extra; } return n; } /// @notice Sets the entropy source for deciding on random attributes. /// @dev This MUST be set after all tokens are minted so minters can't cheat /// the system, and MUST also be a value out of our control; in the absence /// of a VRF, a good choice is the block hash of the first block after final /// token mint. function setEntropy(bytes32 entropy) onlyOwner external { attrs.setEntropy(entropy); } /// @notice Returns the value passed to setEntropy() or 0 if not already /// called. function getEntropy() external view returns (bytes32) { return attrs.getEntropy(); } /// @notice Exposes RandomAttributes._newTieredTrait(). function newTieredTrait(uint index, RandomAttributes.TieredTrait memory trait) onlyOwner public { attrs._newTieredTrait(index, trait); } /// @notice Exposes RandomAttributes._newAllocatedTrait(), allowing for /// multiple allocations to be passed in a single call. function newAllocatedTraits(uint firstIndex, RandomAttributes.Allocated[] memory alloc) onlyOwner public { for (uint i = 0; i < alloc.length; i++) { attrs._newAllocatedTrait(firstIndex+i, alloc[i]); } } /// @notice Returns the number equivalent to a basis point (0.01%) as used /// by RandomAttributes. function basisPoint() external view returns (uint256) { return attrs.BASIS_POINT(); } /// @notice Returns the token's metadata. This will change after the call to /// setEntropy(), after which it will be immutable. function tokenURI(uint256 tokenId) override public view returns (string memory) { require (ERC721._exists(tokenId), "Token doesn't exist"); bytes memory json = abi.encodePacked( '{', '"name": "', name(), ' #', Strings.toString(tokenId), '",', '"image": "data:image/svg+xml;base64,', 'PHN2ZyB3aWR0aD0iMTQwMCIgaGVpZ2h0PSIxNDAwIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv', 'MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj48cmVj', 'dCB3aWR0aD0iMTQwMCIgaGVpZ2h0PSIxNDAwIiBzdHlsZT0iZmlsbDpyZ2IoMCwwLDApO3N0cm9r', 'ZS13aWlkdGg6MCIgLz48L3N2Zz4=",', '"attributes": [' ); if (attrs.entropySet()) { json = abi.encodePacked( json, '{"value": "The world is better with you in it"}', attrs._attributesOf(tokenId) ); } else { json = abi.encodePacked(json, '{"value": "AWGMI?"}'); } json = abi.encodePacked( json, ']', '}' ); return string(abi.encodePacked( "data:application/json;base64,", Base64.encode(json) )); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.6.0; /// @title Base64 /// @author Brecht Devos - <[email protected]> /// @notice Provides functions for encoding/decoding base64 library Base64 { string internal constant TABLE_ENCODE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; bytes internal constant TABLE_DECODE = hex"0000000000000000000000000000000000000000000000000000000000000000" hex"00000000000000000000003e0000003f3435363738393a3b3c3d000000000000" hex"00000102030405060708090a0b0c0d0e0f101112131415161718190000000000" hex"001a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132330000000000"; function encode(bytes memory data) internal pure returns (string memory) { if (data.length == 0) return ''; // load the table into memory string memory table = TABLE_ENCODE; // multiply by 4/3 rounded up uint256 encodedLen = 4 * ((data.length + 2) / 3); // add some extra buffer at the end required for the writing string memory result = new string(encodedLen + 32); assembly { // set the actual output length mstore(result, encodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 3 bytes at a time for {} lt(dataPtr, endPtr) {} { // read 3 bytes dataPtr := add(dataPtr, 3) let input := mload(dataPtr) // write 4 characters mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and(shr( 6, input), 0x3F)))) resultPtr := add(resultPtr, 1) mstore8(resultPtr, mload(add(tablePtr, and( input, 0x3F)))) resultPtr := add(resultPtr, 1) } // padding with '=' 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; } function decode(string memory _data) internal pure returns (bytes memory) { bytes memory data = bytes(_data); if (data.length == 0) return new bytes(0); require(data.length % 4 == 0, "invalid base64 decoder input"); // load the table into memory bytes memory table = TABLE_DECODE; // every 4 characters represent 3 bytes uint256 decodedLen = (data.length / 4) * 3; // add some extra buffer at the end required for the writing bytes memory result = new bytes(decodedLen + 32); assembly { // padding with '=' let lastBytes := mload(add(data, mload(data))) if eq(and(lastBytes, 0xFF), 0x3d) { decodedLen := sub(decodedLen, 1) if eq(and(lastBytes, 0xFFFF), 0x3d3d) { decodedLen := sub(decodedLen, 1) } } // set the actual output length mstore(result, decodedLen) // prepare the lookup table let tablePtr := add(table, 1) // input ptr let dataPtr := data let endPtr := add(dataPtr, mload(data)) // result ptr, jump over length let resultPtr := add(result, 32) // run over the input, 4 characters at a time for {} lt(dataPtr, endPtr) {} { // read 4 characters dataPtr := add(dataPtr, 4) let input := mload(dataPtr) // write 3 bytes let output := add( add( shl(18, and(mload(add(tablePtr, and(shr(24, input), 0xFF))), 0xFF)), shl(12, and(mload(add(tablePtr, and(shr(16, input), 0xFF))), 0xFF))), add( shl( 6, and(mload(add(tablePtr, and(shr( 8, input), 0xFF))), 0xFF)), and(mload(add(tablePtr, and( input , 0xFF))), 0xFF) ) ) mstore(resultPtr, shl(232, output)) resultPtr := add(resultPtr, 3) } } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. * * _Available since v3.4._ */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; /** * @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); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; assembly { size := extcodesize(account) } return size > 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 assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC721.sol"; import "../../../security/Pausable.sol"; /** * @dev ERC721 token with pausable token transfers, minting and burning. * * Useful for scenarios such as preventing trades until the end of an evaluation * period, or having an emergency switch for freezing all token transfers in the * event of a large bug. */ abstract contract ERC721Pausable is ERC721, Pausable { /** * @dev See {ERC721-_beforeTokenTransfer}. * * Requirements: * * - the contract must not be paused. */ function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override { super._beforeTokenTransfer(from, to, tokenId); require(!paused(), "ERC721Pausable: token transfer while paused"); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../ERC721.sol"; import "./IERC721Enumerable.sol"; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev 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(); } }
// SPDX-License-Identifier: MIT 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 `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, 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 be 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 Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @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 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); /** * @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; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "./extensions/IERC721Metadata.sol"; import "../../utils/Address.sol"; import "../../utils/Context.sol"; import "../../utils/Strings.sol"; import "../../utils/introspection/ERC165.sol"; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: balance query for the zero address"); 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: owner query for nonexistent token"); 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) { require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token"); 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 overriden 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 owner nor approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { require(_exists(tokenId), "ERC721: approved query for nonexistent token"); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { require(operator != _msgSender(), "ERC721: approve to caller"); _operatorApprovals[_msgSender()][operator] = approved; emit ApprovalForAll(_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: transfer caller is not 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: transfer caller is not 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) { require(_exists(tokenId), "ERC721: operator query for nonexistent token"); address owner = ERC721.ownerOf(tokenId); return (spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, 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); } /** * @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); } /** * @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 of token that is not own"); 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); } /** * @dev Approve `to` to operate on `tokenId` * * Emits a {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @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 { 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 {} }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Address.sol"; import "../utils/Context.sol"; import "../utils/math/SafeMath.sol"; /** * @title PaymentSplitter * @dev This contract allows to split Ether payments among a group of accounts. The sender does not need to be aware * that the Ether will be split in this way, since it is handled transparently by the contract. * * The split can be in equal parts or in any other arbitrary proportion. The way this is specified is by assigning each * account to a number of shares. Of all the Ether that this contract receives, each account will then be able to claim * an amount proportional to the percentage of total shares they were assigned. * * `PaymentSplitter` follows a _pull payment_ model. This means that payments are not automatically forwarded to the * accounts but kept in this contract, and the actual transfer is triggered as a separate step by calling the {release} * function. */ contract PaymentSplitter is Context { event PayeeAdded(address account, uint256 shares); event PaymentReleased(address to, uint256 amount); event PaymentReceived(address from, uint256 amount); uint256 private _totalShares; uint256 private _totalReleased; mapping(address => uint256) private _shares; mapping(address => uint256) private _released; address[] private _payees; /** * @dev Creates an instance of `PaymentSplitter` where each account in `payees` is assigned the number of shares at * the matching position in the `shares` array. * * All addresses in `payees` must be non-zero. Both arrays must have the same non-zero length, and there must be no * duplicates in `payees`. */ constructor(address[] memory payees, uint256[] memory shares_) payable { require(payees.length == shares_.length, "PaymentSplitter: payees and shares length mismatch"); require(payees.length > 0, "PaymentSplitter: no payees"); for (uint256 i = 0; i < payees.length; i++) { _addPayee(payees[i], shares_[i]); } } /** * @dev The Ether received will be logged with {PaymentReceived} events. Note that these events are not fully * reliable: it's possible for a contract to receive Ether without triggering this function. This only affects the * reliability of the events, and not the actual splitting of Ether. * * To learn more about this see the Solidity documentation for * https://solidity.readthedocs.io/en/latest/contracts.html#fallback-function[fallback * functions]. */ receive() external payable virtual { emit PaymentReceived(_msgSender(), msg.value); } /** * @dev Getter for the total shares held by payees. */ function totalShares() public view returns (uint256) { return _totalShares; } /** * @dev Getter for the total amount of Ether already released. */ function totalReleased() public view returns (uint256) { return _totalReleased; } /** * @dev Getter for the amount of shares held by an account. */ function shares(address account) public view returns (uint256) { return _shares[account]; } /** * @dev Getter for the amount of Ether already released to a payee. */ function released(address account) public view returns (uint256) { return _released[account]; } /** * @dev Getter for the address of the payee number `index`. */ function payee(uint256 index) public view returns (address) { return _payees[index]; } /** * @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the * total shares and their previous withdrawals. */ function release(address payable account) public virtual { require(_shares[account] > 0, "PaymentSplitter: account has no shares"); uint256 totalReceived = address(this).balance + _totalReleased; uint256 payment = (totalReceived * _shares[account]) / _totalShares - _released[account]; require(payment != 0, "PaymentSplitter: account is not due payment"); _released[account] = _released[account] + payment; _totalReleased = _totalReleased + payment; Address.sendValue(account, payment); emit PaymentReleased(account, payment); } /** * @dev Add a new payee to the contract. * @param account The address of the payee to add. * @param shares_ The number of shares owned by the payee. */ function _addPayee(address account, uint256 shares_) private { require(account != address(0), "PaymentSplitter: account is the zero address"); require(shares_ > 0, "PaymentSplitter: shares are 0"); require(_shares[account] == 0, "PaymentSplitter: account already has shares"); _payees.push(account); _shares[account] = shares_; _totalShares = _totalShares + shares_; emit PayeeAdded(account, shares_); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @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() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { 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 { _setOwner(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"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // Copyright 2021 Arran Schlosberg pragma solidity >=0.8.0 <0.9.0; import "./Random.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; /// @notice An abstract contract that allows for random allocation of attributes /// to a set of tokens (presumably ERC721 but not limited). /// @dev Inheriting contracts need to override two functions to define how /// attributes are expressed (e.g. ERC721 metadata JSON). abstract contract RandomAttributes is Ownable, Random { /// @notice Maximum number of tokens that will ever exist. /// @dev See _allocatedTo() for usage. uint256 immutable public MAX_TOKENS; constructor(uint256 maxTokens) { MAX_TOKENS = maxTokens; } /// @dev Override to define how TieredTraits are expressed. function attrForTrait(string memory trait, string memory value) virtual internal pure returns (bytes memory) {} /// @dev Override to define how Allocated traits are expressed. function attrFromName(string memory name) virtual internal pure returns (bytes memory) {} /// @notice Sets the entropy value used for random allocation. /// @dev NB See Random.sol for important considerations. function setEntropy(bytes32 entropy) onlyOwner external { Random._setEntropy(entropy); } /// @notice An attribute / trait that is allocated proportionally into /// Tiers. All will have the same Trait name, but different Tier names. /// @dev No checks are performed to ensure that the sum of all proportions /// <= Random.ONE. Proportions do not have to add to ONE, and any shortfall /// will result in that proportion of tokens not receiving this trait. struct TieredTrait { string name; Tier[] tiers; } /// @notice A Tier within a TieredTrait. /// @dev See Random.ONE, Random.PERCENT, and Random.BASIS_POINT for /// defining proportions. NB: As these allocations are subject to a random /// distribution, final proportions won't be exact. See Allocated if exact /// values are required, but note that they are more expensive to compute /// so MUST only be used for low values of k. struct Tier { string name; uint256 proportion; } /// @notice All TieredTraits to be assigned. TieredTrait[] internal _tiered; /// @notice Adds a new TieredTrait. /// @param index The expected index in the _tiered array, to guarantee /// idempotent calls during deployment. function _newTieredTrait(uint index, TieredTrait memory trait) onlyOwner external { // Ensure that calls are idempotent. Without this, pushing multiple // traits to the chain with one transaction failing could result in // unexpected indices. require(index == _tiered.length, "RandomAttributes: invalid tiered index"); _tiered.push(); _tiered[index].name = trait.name; _addToTieredTrait(index, 0, trait.tiers); } /// @notice Extends an existing TieredTrait with more Tiers. /// @param startIndex The expected index of the first Tier to be added, to /// guarantee idempotent calls during deployment. function _addToTieredTrait(uint traitIndex, uint startIndex, Tier[] memory tiers) onlyOwner public { // See _newTieredTrait() for logic. require(startIndex == _tiered[traitIndex].tiers.length, "RandomAttributes: invalid startIndex"); // Solidity doesn't support copy from memory to storage for this type, // so push each element. for (uint i = 0; i < tiers.length; i++) { _tiered[traitIndex].tiers.push(tiers[i]); } } /// @notice Alias for _tieredTraitsFor() with zero-value entropy. function _tieredTraitsFor(uint256 tokenId, TieredTrait[] memory traits) internal view returns (bytes memory) { return _tieredTraitsFor(tokenId, traits, new bytes(0)); } /// @notice Computes all Tiers, for all Traits, assigned to the token. The /// Tiers are passed to attrForTrait() and the returned values concatenated /// with abi.encodePacked() to be returned. /// @param traits The TieredTraits to be assigned. These are typically the /// values stored in _tiered, but MAY differ. /// @param _entropy Optional additional entropy for use in allocating Tiers. /// @dev The entropy in Random._entropy is always used, while the _entropy /// param is an additional source. The Random._entropy value is used to /// differentiate between contract instances whereas the parameter allows /// for different rolls of the dice within the same contract. This function /// SHOULD be used in a call, not a transaction, as it hasn't been optimised /// for gas consumption. function _tieredTraitsFor(uint256 tokenId, TieredTrait[] memory traits, bytes memory _entropy) internal view returns (bytes memory) { uint256 threshold; bytes memory assigned; for (uint i=0; i < traits.length; i++) { uint rand = _uniform(abi.encode(_entropy, tokenId, traits[i].name)); // Although it would be more computationally efficient to perform a // binary search here, it adds code complexity that can result in a // bug. Testing of random functions is difficult enough as it is, so // we opt for simplicity for negligible gas cost (or zero given that // this function is intended for gas-free calls). threshold = 0; for (uint j = 0; j < traits[i].tiers.length; j++) { threshold += traits[i].tiers[j].proportion; if (rand <= threshold) { assigned = abi.encodePacked(assigned, attrForTrait(traits[i].name, traits[i].tiers[j].name)); break; } } } return assigned; } /// @notice A directly allocated attribute that is assigned to exactly k /// tokens. /// @dev Allocation is very expensive, and may even cause a gas-free call to /// reach block limits (still enforced, just not paid). It scales roughly /// linearly as O(k) as long as k << MAX_TOKENS. If k approaches MAX_TOKENS /// then the probability of allocating to the same token on different random /// samplings increases and _isAllocatedTo() becomes much less efficient. If /// k is too large, TieredTraits SHOULD be used instead. struct Allocated { string name; uint256 k; } /// @notice All Allocated attributes to be assigned. Allocated[] internal _allocs; /// @notice Adds a new Allocated attribute. /// @param index The expected index in the _allocs array, to guarantee /// idempotent calls during deployment. function _newAllocatedTrait(uint index, Allocated memory alloc) onlyOwner external { require(index == _allocs.length, "RandomAttributes: invalid allocated index"); _allocs.push(alloc); } /// @notice Alias for _allocatedTo() with zero-value entropy. function _allocatedTo(uint256 tokenId, Allocated[] memory allocs) internal view returns (bytes memory) { return _allocatedTo(tokenId, allocs, new bytes(0)); } /// @notice Computes all Allocated attributes assigned to the given token. /// The names are passed to attrFromName() and the returned values /// concatenated with abi.encodePacked() to be returned. /// @param allocs The Allocated to be assigned. These are typically the /// values stored in _allocs, but MAY differ. /// @param _entropy Optional additional entropy for use in selecting tokens /// receiving Allocated attributes. /// @dev The entropy in Random._entropy is always used, while the _entropy /// param is an additional source. The Random._entropy value is used to /// differentiate between contract instances whereas the parameter allows /// for different rolls of the dice within the same contract. This function /// SHOULD be used in a call, not a transaction, as it hasn't been optimised /// for gas consumption. function _allocatedTo(uint256 tokenId, Allocated[] memory allocs, bytes memory _entropy) internal view returns (bytes memory) { // Determine how many bits of entropy are needed to choose from // MAX_TOKENS. uint256 logN = 0; uint256 n = MAX_TOKENS; assembly { for {} gt(n, 0) {n := shr(1, n)} { logN := add(logN, 1) } } uint256 mask = 2**logN - 1; bytes memory allocated; for (uint i=0; i < allocs.length; i++) { if (_isAllocatedTo(tokenId, allocs[i], logN, mask, _entropy)) { allocated = abi.encodePacked(allocated, attrFromName(allocs[i].name)); } } return allocated; } /// @notice Returns whether a _specific_ Allocated attribute is assigned to /// the specific tokenId. /// @param logN An approximation of log_2(MAX_TOKENS) used to determine the /// number of random bits used for a single sample. MUST be the smallest /// integer value >log_2(MAX_TOKENS). /// @param mask A bitwise mask for sampling random bits. MUST be equal to /// 2**logN - 1, i.e. the smallest all-ones binary mask that is larger than /// MAX_TOKENS. /// @param _entropy See _allocatedTo(). /// @dev Functions by sampling from keccak256(<entropy sources>,counter) in /// an unbiased fashion until either tokenId receives an Allocated trait or /// all traits are allocated. This function SHOULD be used in a call, not a /// transaction, as it hasn't been optimised for gas consumption. function _isAllocatedTo(uint256 tokenId, Allocated memory alloc, uint256 logN, uint256 mask, bytes memory _entropy) private view returns (bool) { // randSrc is a pool of entropy sourced from the hash of entropy sources // and a counter. When replenished, bitsRemaining is set to 256, and // reduced by logN after each sample. uint256 counter = 0; uint256 randSrc; uint256 bitsRemaining = 0; // The random sample [0,mask]. This is the smallest range that includes // MAX_TOKEN, thus improving efficiency of rejection sampling. uint256 rand; // Keeps track of the tokens other than tokenId to which this trait has // been allocated. Effectively a set, but Solidity doesn't support // mapping types out of storage, and this function MUST be `view`. bool[] memory already = new bool[](MAX_TOKENS); for (uint i = 0; i < alloc.k; i++) { while (true) { // Do we need to replenish the entropy source? if (bitsRemaining < logN) { randSrc = uint256(keccak256(abi.encode(_entropy, Random._entropy, alloc.name, counter))); counter++; bitsRemaining = 256; } // Sample from randSrc. assembly { rand := and(randSrc, mask) randSrc := shr(logN, randSrc) // Can never wrap because of the replenishment in the if // block above. bitsRemaining := sub(bitsRemaining, logN) } if (rand == tokenId) { return true; } if (rand >= MAX_TOKENS) { // The random value is out of range and therefore rejected. // Don't use % MAX_TOKENS because this biases low-valued // numbers, so instead we roll the dice again without // incrementing i. continue; } if (already[rand]) { // Although this can be collapsed into the previous if // statement, it's separated to check for test coverage. // It's very hard to test random functions like this, so // every bit of extra information helps. continue; } already[rand] = true; // Note the inner loop so this allocates to the next token. break; } } return false; } /// @notice Returns the concatenation of _tieredTraitsFor() and /// _allocatedTo() for the specified token, using zero-value entropy and the /// contract-stored attributes. function _attributesOf(uint256 tokenId) external view returns (bytes memory) { TieredTrait[] memory tiered = _tiered; Allocated[] memory allocs = _allocs; return abi.encodePacked( _tieredTraitsFor(tokenId, tiered), _allocatedTo(tokenId, allocs) ); } }
// SPDX-License-Identifier: MIT // Copyright 2021 Arran Schlosberg pragma solidity >=0.8.0 <0.9.0; /** * @notice Random contracts can generate unbiased pseudorandom numbers from * seeds. Best practice requires only setting the `entropy` value _after_ * user interaction, and obtaining it from a source out of the control of anyone * who may benefit from the outcome. Ideally a VRF would be used. If the * contract admin can't be trusted, they can publicly nominate a future block * number and use its hash; NOTE that this can be manipulated by a miner, so * their expected return of such an action should be considered. If the admin * can be trusted then they can use a commit-and-reveal approach. */ contract Random { /// @notice A base entropy source that ensures that calls to _uniform(seed) /// return different values to calls in another contract despite having the /// same seed. bytes32 internal _entropy; /// @notice Immutably sets the entropy value if not already set. function _setEntropy(bytes32 entropy) internal { require (!entropySet(), "Entropy already set"); _entropy = entropy; } /// @notice Returns if the entropy value has been set, assuming that this /// value was not 0. function entropySet() public view returns (bool) { return uint256(_entropy) != 0; } /// @notice Returns the value passed to _setEntropy(). function getEntropy() public view returns (bytes32) { require (entropySet(), "Entropy not set"); return _entropy; } /** * @dev As we're generating random numbers from hashes, their ranges are * always powers of two. However we need denominators that are * human-friendly and therefore powers of 10. Generating a random number in * [0,10^59] can be performed in an unbiased manner by repeatedly sampling * 196 bits from keccak256(seed||counter) until it's within the range. These * values are chosen because 10^59/2^196 = 0.9957 so we very rarely have to * try again and waste computation. */ uint256 private constant RAND_MASK = 2**196 - 1; uint256 public constant ONE = 1e59; /// @notice Values equivalent to 1% and 0.01%. uint256 public constant PERCENT = 1e57; uint256 public constant BASIS_POINT = 1e55; /// @notice Returns a uniformly distributed random number [0, ONE]. function _uniform(bytes memory seed) internal view returns (uint256) { uint256 rand = RAND_MASK; // The loop will always run at least once because RAND_MASK > ONE. for (uint j = 0; rand > ONE; j++) { rand = uint256(keccak256(abi.encode(_entropy, seed, j))); assembly { rand := and(rand, RAND_MASK) } } return rand; } }
// SPDX-License-Identifier: MIT // Copyright 2021 Arran Schlosberg pragma solidity >=0.8.0 <0.9.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/security/Pausable.sol"; /// @notice A Pausable contract that can only be toggled by the Owner. contract OwnerPausable is Ownable, Pausable { /// @notice Pauses the contract. function pause() onlyOwner public { Pausable._pause(); } /// @notice Unpauses the contract. function unpause() onlyOwner public { Pausable._unpause(); } }
// SPDX-License-Identifier: MIT // Copyright 2021 Arran Schlosberg pragma solidity >=0.8.0 <0.9.0; import "./BaseOpenSea.sol"; import "./OwnerPausable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol"; /// @notice An ERC721 contract with common functionality: /// - OpenSea gas-free listings /// - OpenZeppelin Enumerable and Pausable /// - OpenZeppelin Pausable with functions exposed to Owner only. contract ERC721Common is BaseOpenSea, ERC721Enumerable, ERC721Pausable, OwnerPausable { constructor( string memory name, string memory symbol, address openSeaProxyRegistry ) ERC721(name, symbol) { if (openSeaProxyRegistry != address(0)) { BaseOpenSea._setOpenSeaRegistry(openSeaProxyRegistry); } } /// @notice Overrides _beforeTokenTransfer as required by inheritance. function _beforeTokenTransfer( address from, address to, uint256 tokenId ) internal virtual override (ERC721Enumerable, ERC721Pausable) { super._beforeTokenTransfer(from, to, tokenId); } /// @notice Overrides supportsInterface as required by inheritance. function supportsInterface(bytes4 interfaceId) public view override (ERC721, ERC721Enumerable) returns (bool) { return super.supportsInterface(interfaceId); } /// @notice Returns true if either standard isApprovedForAll() returns true /// or the operator is the OpenSea proxy for the owner. function isApprovedForAll(address owner, address operator) public view override returns (bool) { return super.isApprovedForAll(owner, operator) || BaseOpenSea.isOwnersOpenSeaProxy(owner, operator); } }
// SPDX-License-Identifier: UNLICENSED // Copyright 2021; All rights reserved // Author: 0x99c520ed5a5e57b2128737531f5626d026ea39f20960b0e750077b9768543949 pragma solidity >=0.8.0 <0.9.0; import "./RandomAttributes.sol"; /// @notice A concrete extension of the abstract RandomAttributes contract, used /// for the BlackSquare token. contract BlackSquareRandomAttributes is RandomAttributes { constructor(uint256 maxTokens) RandomAttributes(maxTokens) {} /// @notice Returns an ERC721 metadata attribute for the trait[_type] and /// value. /// @dev Assumes that there is already another attribute before this one in /// the JSON list. function attrForTrait(string memory trait, string memory value) override internal pure returns (bytes memory) { return abi.encodePacked(',{"trait_type": "', trait, '", "value": "', value, '"}'); } /// @notice Returns attrForTrait("Looks Rare", @name). function attrFromName(string memory name) override internal pure returns (bytes memory) { return attrForTrait("Looks Rare", name); } /// @notice Returns the i'th tiered trait to allow for testing of exhaustive /// proportions (i.e. add to 100%). function tieredTrait(uint256 i) external view returns (RandomAttributes.TieredTrait memory) { return RandomAttributes._tiered[i]; } /// @notice Returns the total number of tiered traits. function numTraits() external view returns (uint256) { return RandomAttributes._tiered.length; } }
//SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // https://gist.github.com/dievardump/483eb43bc6ed30b14f01e01842e3339b/ /// @title OpenSea contract helper that defines a few things /// @author Simon Fremaux (@dievardump) /// @dev This is a contract used to add OpenSea's support for gas-less trading /// by checking if operator is owner's proxy contract BaseOpenSea { string private _contractURI; ProxyRegistry private _proxyRegistry; /// @notice Returns the contract URI function. Used on OpenSea to get details /// about a contract (owner, royalties etc...) /// See documentation: https://docs.opensea.io/docs/contract-level-metadata function contractURI() public view returns (string memory) { return _contractURI; } /// @notice Helper for OpenSea gas-less trading /// @dev Allows to check if `operator` is owner's OpenSea proxy /// @param owner the owner we check for /// @param operator the operator (proxy) we check for function isOwnersOpenSeaProxy(address owner, address operator) public view returns (bool) { ProxyRegistry proxyRegistry = _proxyRegistry; return // we have a proxy registry address address(proxyRegistry) != address(0) && // current operator is owner's proxy address address(proxyRegistry.proxies(owner)) == operator; } /// @dev Internal function to set the _contractURI /// @param contractURI_ the new contract uri function _setContractURI(string memory contractURI_) internal { _contractURI = contractURI_; } /// @dev Internal function to set the _proxyRegistry /// @param proxyRegistryAddress the new proxy registry address function _setOpenSeaRegistry(address proxyRegistryAddress) internal { _proxyRegistry = ProxyRegistry(proxyRegistryAddress); } } contract OwnableDelegateProxy {} contract ProxyRegistry { mapping(address => OwnableDelegateProxy) public proxies; }
{ "remappings": [], "optimizer": { "enabled": false, "runs": 200 }, "evmVersion": "london", "libraries": {}, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"openSeaProxyRegistry","type":"address"},{"internalType":"uint256","name":"maxTokens","type":"uint256"},{"internalType":"address payable","name":"_paymentSplitter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"MAX_PER_ADDRESS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINT_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"attrs","outputs":[{"internalType":"contract BlackSquareRandomAttributes","name":"","type":"address"}],"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":"basisPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"getEntropy","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isOwnersOpenSeaProxy","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minted","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":"uint256","name":"firstIndex","type":"uint256"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"k","type":"uint256"}],"internalType":"struct RandomAttributes.Allocated[]","name":"alloc","type":"tuple[]"}],"name":"newAllocatedTraits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"components":[{"internalType":"string","name":"name","type":"string"},{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"proportion","type":"uint256"}],"internalType":"struct RandomAttributes.Tier[]","name":"tiers","type":"tuple[]"}],"internalType":"struct RandomAttributes.TieredTrait","name":"trait","type":"tuple"}],"name":"newTieredTrait","outputs":[],"stateMutability":"nonpayable","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":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paymentSplitter","outputs":[{"internalType":"contract PaymentSplitter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"n","type":"uint256"}],"name":"safeMint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"entropy","type":"bytes32"}],"name":"setEntropy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_paymentSplitter","type":"address"}],"name":"setPaymentSplitter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c06040523480156200001157600080fd5b506040516200921f3803806200921f833981810160405281019062000037919062000614565b8484848282816002908051906020019062000054929190620002d4565b5080600390805190602001906200006d929190620002d4565b5050506200009062000084620001c260201b60201c565b620001ca60201b60201c565b6000600c60146101000a81548160ff021916908315150217905550600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614620000f757620000f6816200029060201b620021651760201c565b5b5050506001600d8190555081604051620001119062000365565b6200011d9190620006eb565b604051809103906000f0801580156200013a573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff168152505080600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816080818152505050505050506200076d565b600033905090565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b828054620002e29062000737565b90600052602060002090601f01602090048101928262000306576000855562000352565b82601f106200032157805160ff191683800117855562000352565b8280016001018555821562000352579182015b828111156200035157825182559160200191906001019062000334565b5b50905062000361919062000373565b5090565b612bc5806200665a83390190565b5b808211156200038e57600081600090555060010162000374565b5090565b6000604051905090565b600080fd5b600080fd5b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b620003fb82620003b0565b810181811067ffffffffffffffff821117156200041d576200041c620003c1565b5b80604052505050565b60006200043262000392565b9050620004408282620003f0565b919050565b600067ffffffffffffffff821115620004635762000462620003c1565b5b6200046e82620003b0565b9050602081019050919050565b60005b838110156200049b5780820151818401526020810190506200047e565b83811115620004ab576000848401525b50505050565b6000620004c8620004c28462000445565b62000426565b905082815260208101848484011115620004e757620004e6620003ab565b5b620004f48482856200047b565b509392505050565b600082601f830112620005145762000513620003a6565b5b815162000526848260208601620004b1565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200055c826200052f565b9050919050565b6200056e816200054f565b81146200057a57600080fd5b50565b6000815190506200058e8162000563565b92915050565b6000819050919050565b620005a98162000594565b8114620005b557600080fd5b50565b600081519050620005c9816200059e565b92915050565b6000620005dc826200052f565b9050919050565b620005ee81620005cf565b8114620005fa57600080fd5b50565b6000815190506200060e81620005e3565b92915050565b600080600080600060a086880312156200063357620006326200039c565b5b600086015167ffffffffffffffff811115620006545762000653620003a1565b5b6200066288828901620004fc565b955050602086015167ffffffffffffffff811115620006865762000685620003a1565b5b6200069488828901620004fc565b9450506040620006a7888289016200057d565b9350506060620006ba88828901620005b8565b9250506080620006cd88828901620005fd565b9150509295509295909350565b620006e58162000594565b82525050565b6000602082019050620007026000830184620006da565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806200075057607f821691505b6020821081141562000767576200076662000708565b5b50919050565b60805160a051615e8f620007cb60003960008181610af301528181610c43015281816111da015281816117750152818161197701528181611c7601528181611d1a0152611ee0015260008181610dfb01526121430152615e8f6000f3fe60806040526004361061021a5760003560e01c80636352211e11610123578063a22cb465116100ab578063e8a3d4851161006f578063e8a3d485146107c4578063e985e9c5146107ef578063ed4a6b0c1461082c578063f2fde38b14610857578063f47c84c5146108805761021a565b8063a22cb465146106e1578063b88d4fde1461070a578063c002d23d14610733578063c87b56dd1461075e578063e24d9e2c1461079b5761021a565b80638456cb59116100f25780638456cb59146106225780638a7ac5c7146106395780638da5cb5b1461066257806395d89b411461068d57806396b83514146106b85761021a565b80636352211e146105685780636b29b79f146105a557806370a08231146105ce578063715018a61461060b5761021a565b80632f745c59116101a657806342842e0e1161017557806342842e0e1461046f5780634f6ccce7146104985780635404bbf7146104d55780635c975abb146105005780636102de981461052b5761021a565b80632f745c59146103d45780632f7b19151461041157806331c864e81461043c5780633f4ba83a146104585761021a565b80630aaef285116101ed5780630aaef285146102ed5780630cc96d521461031857806318160ddd146103435780631e7269c51461036e57806323b872dd146103ab5761021a565b806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287578063095ea7b3146102c4575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190613744565b6108ab565b604051610253919061378c565b60405180910390f35b34801561026857600080fd5b506102716108bd565b60405161027e9190613840565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a99190613898565b61094f565b6040516102bb9190613906565b60405180910390f35b3480156102d057600080fd5b506102eb60048036038101906102e6919061394d565b6109d4565b005b3480156102f957600080fd5b50610302610aec565b60405161030f919061399c565b60405180910390f35b34801561032457600080fd5b5061032d610af1565b60405161033a9190613a16565b60405180910390f35b34801561034f57600080fd5b50610358610b15565b604051610365919061399c565b60405180910390f35b34801561037a57600080fd5b5061039560048036038101906103909190613a31565b610b22565b6040516103a2919061399c565b60405180910390f35b3480156103b757600080fd5b506103d260048036038101906103cd9190613a5e565b610b3a565b005b3480156103e057600080fd5b506103fb60048036038101906103f6919061394d565b610b9a565b604051610408919061399c565b60405180910390f35b34801561041d57600080fd5b50610426610c3f565b604051610433919061399c565b60405180910390f35b61045660048036038101906104519190613898565b610ce4565b005b34801561046457600080fd5b5061046d6110bf565b005b34801561047b57600080fd5b5061049660048036038101906104919190613a5e565b611145565b005b3480156104a457600080fd5b506104bf60048036038101906104ba9190613898565b611165565b6040516104cc919061399c565b60405180910390f35b3480156104e157600080fd5b506104ea6111d6565b6040516104f79190613aca565b60405180910390f35b34801561050c57600080fd5b5061051561127b565b604051610522919061378c565b60405180910390f35b34801561053757600080fd5b50610552600480360381019061054d9190613ae5565b611292565b60405161055f919061378c565b60405180910390f35b34801561057457600080fd5b5061058f600480360381019061058a9190613898565b6113b3565b60405161059c9190613906565b60405180910390f35b3480156105b157600080fd5b506105cc60048036038101906105c79190613b63565b611465565b005b3480156105da57600080fd5b506105f560048036038101906105f09190613a31565b611525565b604051610602919061399c565b60405180910390f35b34801561061757600080fd5b506106206115dd565b005b34801561062e57600080fd5b50610637611665565b005b34801561064557600080fd5b50610660600480360381019061065b9190613e21565b6116eb565b005b34801561066e57600080fd5b5061067761183d565b6040516106849190613906565b60405180910390f35b34801561069957600080fd5b506106a2611867565b6040516106af9190613840565b60405180910390f35b3480156106c457600080fd5b506106df60048036038101906106da9190614052565b6118f9565b005b3480156106ed57600080fd5b50610708600480360381019061070391906140da565b611a06565b005b34801561071657600080fd5b50610731600480360381019061072c91906141bb565b611b87565b005b34801561073f57600080fd5b50610748611be9565b604051610755919061399c565b60405180910390f35b34801561076a57600080fd5b5061078560048036038101906107809190613898565b611bf5565b6040516107929190613840565b60405180910390f35b3480156107a757600080fd5b506107c260048036038101906107bd919061426a565b611e62565b005b3480156107d057600080fd5b506107d9611f6c565b6040516107e69190613840565b60405180910390f35b3480156107fb57600080fd5b5061081660048036038101906108119190613ae5565b611ffe565b604051610823919061378c565b60405180910390f35b34801561083857600080fd5b50610841612023565b60405161084e91906142ca565b60405180910390f35b34801561086357600080fd5b5061087e60048036038101906108799190613a31565b612049565b005b34801561088c57600080fd5b50610895612141565b6040516108a2919061399c565b60405180910390f35b60006108b6826121a9565b9050919050565b6060600280546108cc90614314565b80601f01602080910402602001604051908101604052809291908181526020018280546108f890614314565b80156109455780601f1061091a57610100808354040283529160200191610945565b820191906000526020600020905b81548152906001019060200180831161092857829003601f168201915b5050505050905090565b600061095a82612223565b610999576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610990906143b8565b60405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006109df826113b3565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a479061444a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a6f61228f565b73ffffffffffffffffffffffffffffffffffffffff161480610a9e5750610a9d81610a9861228f565b611ffe565b5b610add576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad4906144dc565b60405180910390fd5b610ae78383612297565b505050565b600a81565b7f000000000000000000000000000000000000000000000000000000000000000081565b6000600a80549050905090565b600f6020528060005260406000206000915090505481565b610b4b610b4561228f565b82612350565b610b8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b819061456e565b60405180910390fd5b610b9583838361242e565b505050565b6000610ba583611525565b8210610be6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdd90614600565b60405180910390fd5b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663ada5f6426040518163ffffffff1660e01b815260040160206040518083038186803b158015610ca757600080fd5b505afa158015610cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cdf9190614635565b905090565b6002600d541415610d2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d21906146ae565b60405180910390fd5b6002600d81905550610d7281336040518060400160405280600c81526020017f53656e646572206c696d6974000000000000000000000000000000000000000081525061268a565b90503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610dea57610de781326040518060400160405280600c81526020017f4f726967696e206c696d6974000000000000000000000000000000000000000081525061268a565b90505b6000610df4610b15565b90506000817f0000000000000000000000000000000000000000000000000000000000000000610e2491906146fd565b905060008111610e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e609061477d565b60405180910390fd5b80831115610e75578092505b600067016345785d8a000084610e8b919061479d565b905080341015610ed0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ec790614843565b60405180910390fd5b83600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610f1f9190614863565b925050819055503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fb05783600f60003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610fa89190614863565b925050819055505b60008484610fbe9190614863565b90505b80841015610fe657610fd3338561273f565b8380610fde906148b9565b945050610fc1565b50600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561104f573d6000803e3d6000fd5b50803411156110b15760003390508073ffffffffffffffffffffffffffffffffffffffff166108fc833461108391906146fd565b9081150290604051600060405180830381858888f193505050501580156110ae573d6000803e3d6000fd5b50505b5050506001600d8190555050565b6110c761228f565b73ffffffffffffffffffffffffffffffffffffffff166110e561183d565b73ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111329061494e565b60405180910390fd5b61114361275d565b565b61116083838360405180602001604052806000815250611b87565b505050565b600061116f610b15565b82106111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a7906149e0565b60405180910390fd5b600a82815481106111c4576111c3614a00565b5b90600052602060002001549050919050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16635404bbf76040518163ffffffff1660e01b815260040160206040518083038186803b15801561123e57600080fd5b505afa158015611252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112769190614a44565b905090565b6000600c60149054906101000a900460ff16905090565b600080600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156113aa57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1663c4552791866040518263ffffffff1660e01b81526004016113429190613906565b60206040518083038186803b15801561135a57600080fd5b505afa15801561136e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113929190614aaf565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b6000806004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561145c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145390614b4e565b60405180910390fd5b80915050919050565b61146d61228f565b73ffffffffffffffffffffffffffffffffffffffff1661148b61183d565b73ffffffffffffffffffffffffffffffffffffffff16146114e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d89061494e565b60405180910390fd5b80600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158d90614be0565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6115e561228f565b73ffffffffffffffffffffffffffffffffffffffff1661160361183d565b73ffffffffffffffffffffffffffffffffffffffff1614611659576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116509061494e565b60405180910390fd5b61166360006127ff565b565b61166d61228f565b73ffffffffffffffffffffffffffffffffffffffff1661168b61183d565b73ffffffffffffffffffffffffffffffffffffffff16146116e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d89061494e565b60405180910390fd5b6116e96128c5565b565b6116f361228f565b73ffffffffffffffffffffffffffffffffffffffff1661171161183d565b73ffffffffffffffffffffffffffffffffffffffff1614611767576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175e9061494e565b60405180910390fd5b60005b8151811015611838577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663217167ad82856117bb9190614863565b8484815181106117ce576117cd614a00565b5b60200260200101516040518363ffffffff1660e01b81526004016117f3929190614c96565b600060405180830381600087803b15801561180d57600080fd5b505af1158015611821573d6000803e3d6000fd5b505050508080611830906148b9565b91505061176a565b505050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461187690614314565b80601f01602080910402602001604051908101604052809291908181526020018280546118a290614314565b80156118ef5780601f106118c4576101008083540402835291602001916118ef565b820191906000526020600020905b8154815290600101906020018083116118d257829003601f168201915b5050505050905090565b61190161228f565b73ffffffffffffffffffffffffffffffffffffffff1661191f61183d565b73ffffffffffffffffffffffffffffffffffffffff1614611975576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196c9061494e565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a7b21d7583836040518363ffffffff1660e01b81526004016119d0929190614e09565b600060405180830381600087803b1580156119ea57600080fd5b505af11580156119fe573d6000803e3d6000fd5b505050505050565b611a0e61228f565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a7390614e85565b60405180910390fd5b8060076000611a8961228f565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611b3661228f565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611b7b919061378c565b60405180910390a35050565b611b98611b9261228f565b83612350565b611bd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bce9061456e565b60405180910390fd5b611be384848484612968565b50505050565b67016345785d8a000081565b6060611c0082612223565b611c3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3690614ef1565b60405180910390fd5b6000611c496108bd565b611c52846129c4565b604051602001611c6392919061534f565b60405160208183030381529060405290507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a0d0ddbf6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cda57600080fd5b505afa158015611cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1291906153f6565b15611ded57807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663922050cc856040518263ffffffff1660e01b8152600401611d71919061399c565b60006040518083038186803b158015611d8957600080fd5b505afa158015611d9d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611dc69190615493565b604051602001611dd7929190615595565b6040516020818303038152906040529050611e10565b80604051602001611dfe9190615610565b60405160208183030381529060405290505b80604051602001611e2191906156ca565b6040516020818303038152906040529050611e3b81612b25565b604051602001611e4b9190615743565b604051602081830303815290604052915050919050565b611e6a61228f565b73ffffffffffffffffffffffffffffffffffffffff16611e8861183d565b73ffffffffffffffffffffffffffffffffffffffff1614611ede576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed59061494e565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663e24d9e2c826040518263ffffffff1660e01b8152600401611f379190613aca565b600060405180830381600087803b158015611f5157600080fd5b505af1158015611f65573d6000803e3d6000fd5b5050505050565b606060008054611f7b90614314565b80601f0160208091040260200160405190810160405280929190818152602001828054611fa790614314565b8015611ff45780601f10611fc957610100808354040283529160200191611ff4565b820191906000526020600020905b815481529060010190602001808311611fd757829003601f168201915b5050505050905090565b600061200a8383612c9e565b8061201b575061201a8383611292565b5b905092915050565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61205161228f565b73ffffffffffffffffffffffffffffffffffffffff1661206f61183d565b73ffffffffffffffffffffffffffffffffffffffff16146120c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120bc9061494e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612135576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212c906157d7565b60405180910390fd5b61213e816127ff565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061221c575061221b82612d32565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661230a836113b3565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061235b82612223565b61239a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161239190615869565b60405180910390fd5b60006123a5836113b3565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061241457508373ffffffffffffffffffffffffffffffffffffffff166123fc8461094f565b73ffffffffffffffffffffffffffffffffffffffff16145b8061242557506124248185611ffe565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661244e826113b3565b73ffffffffffffffffffffffffffffffffffffffff16146124a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161249b906158fb565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161250b9061598d565b60405180910390fd5b61251f838383612e14565b61252a600082612297565b6001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461257a91906146fd565b925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546125d19190614863565b92505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600080600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600a6126d991906146fd565b9050600081118390612721576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127189190613840565b60405180910390fd5b50808511156127335780915050612738565b849150505b9392505050565b612759828260405180602001604052806000815250612e24565b5050565b61276561127b565b6127a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279b906159f9565b60405180910390fd5b6000600c60146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6127e861228f565b6040516127f59190613906565b60405180910390a1565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6128cd61127b565b1561290d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161290490615a65565b60405180910390fd5b6001600c60146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861295161228f565b60405161295e9190613906565b60405180910390a1565b61297384848461242e565b61297f84848484612e7f565b6129be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b590615af7565b60405180910390fd5b50505050565b60606000821415612a0c576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612b20565b600082905060005b60008214612a3e578080612a27906148b9565b915050600a82612a379190615b46565b9150612a14565b60008167ffffffffffffffff811115612a5a57612a59613b95565b5b6040519080825280601f01601f191660200182016040528015612a8c5781602001600182028036833780820191505090505b5090505b60008514612b1957600182612aa591906146fd565b9150600a85612ab49190615b77565b6030612ac09190614863565b60f81b818381518110612ad657612ad5614a00565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612b129190615b46565b9450612a90565b8093505050505b919050565b6060600082511415612b4857604051806020016040528060008152509050612c99565b6000604051806060016040528060408152602001615e1a6040913990506000600360028551612b779190614863565b612b819190615b46565b6004612b8d919061479d565b90506000602082612b9e9190614863565b67ffffffffffffffff811115612bb757612bb6613b95565b5b6040519080825280601f01601f191660200182016040528015612be95781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015612c58576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825360018201915050612bfd565b600389510660018114612c725760028114612c8257612c8d565b613d3d60f01b6002830352612c8d565b603d60f81b60018303525b50505050508093505050505b919050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612dfd57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612e0d5750612e0c82613016565b5b9050919050565b612e1f838383613080565b505050565b612e2e83836130d8565b612e3b6000848484612e7f565b612e7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e7190615af7565b60405180910390fd5b505050565b6000612ea08473ffffffffffffffffffffffffffffffffffffffff166132a6565b15613009578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612ec961228f565b8786866040518563ffffffff1660e01b8152600401612eeb9493929190615bf2565b602060405180830381600087803b158015612f0557600080fd5b505af1925050508015612f3657506040513d601f19601f82011682018060405250810190612f339190615c53565b60015b612fb9573d8060008114612f66576040519150601f19603f3d011682016040523d82523d6000602084013e612f6b565b606091505b50600081511415612fb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fa890615af7565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061300e565b600190505b949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b61308b8383836132b9565b61309361127b565b156130d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ca90615cf2565b60405180910390fd5b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613148576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161313f90615d5e565b60405180910390fd5b61315181612223565b15613191576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318890615dca565b60405180910390fd5b61319d60008383612e14565b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131ed9190614863565b92505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080823b905060008111915050919050565b6132c48383836133cd565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561330757613302816133d2565b613346565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461334557613344838261341b565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156133895761338481613588565b6133c8565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146133c7576133c68282613659565b5b5b505050565b505050565b600a80549050600b600083815260200190815260200160002081905550600a81908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161342884611525565b61343291906146fd565b9050600060096000848152602001908152602001600020549050818114613517576000600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816009600083815260200190815260200160002081905550505b6009600084815260200190815260200160002060009055600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600a8054905061359c91906146fd565b90506000600b60008481526020019081526020016000205490506000600a83815481106135cc576135cb614a00565b5b9060005260206000200154905080600a83815481106135ee576135ed614a00565b5b906000526020600020018190555081600b600083815260200190815260200160002081905550600b600085815260200190815260200160002060009055600a80548061363d5761363c615dea565b5b6001900381819060005260206000200160009055905550505050565b600061366483611525565b905081600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806009600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613721816136ec565b811461372c57600080fd5b50565b60008135905061373e81613718565b92915050565b60006020828403121561375a576137596136e2565b5b60006137688482850161372f565b91505092915050565b60008115159050919050565b61378681613771565b82525050565b60006020820190506137a1600083018461377d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156137e15780820151818401526020810190506137c6565b838111156137f0576000848401525b50505050565b6000601f19601f8301169050919050565b6000613812826137a7565b61381c81856137b2565b935061382c8185602086016137c3565b613835816137f6565b840191505092915050565b6000602082019050818103600083015261385a8184613807565b905092915050565b6000819050919050565b61387581613862565b811461388057600080fd5b50565b6000813590506138928161386c565b92915050565b6000602082840312156138ae576138ad6136e2565b5b60006138bc84828501613883565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006138f0826138c5565b9050919050565b613900816138e5565b82525050565b600060208201905061391b60008301846138f7565b92915050565b61392a816138e5565b811461393557600080fd5b50565b60008135905061394781613921565b92915050565b60008060408385031215613964576139636136e2565b5b600061397285828601613938565b925050602061398385828601613883565b9150509250929050565b61399681613862565b82525050565b60006020820190506139b1600083018461398d565b92915050565b6000819050919050565b60006139dc6139d76139d2846138c5565b6139b7565b6138c5565b9050919050565b60006139ee826139c1565b9050919050565b6000613a00826139e3565b9050919050565b613a10816139f5565b82525050565b6000602082019050613a2b6000830184613a07565b92915050565b600060208284031215613a4757613a466136e2565b5b6000613a5584828501613938565b91505092915050565b600080600060608486031215613a7757613a766136e2565b5b6000613a8586828701613938565b9350506020613a9686828701613938565b9250506040613aa786828701613883565b9150509250925092565b6000819050919050565b613ac481613ab1565b82525050565b6000602082019050613adf6000830184613abb565b92915050565b60008060408385031215613afc57613afb6136e2565b5b6000613b0a85828601613938565b9250506020613b1b85828601613938565b9150509250929050565b6000613b30826138c5565b9050919050565b613b4081613b25565b8114613b4b57600080fd5b50565b600081359050613b5d81613b37565b92915050565b600060208284031215613b7957613b786136e2565b5b6000613b8784828501613b4e565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613bcd826137f6565b810181811067ffffffffffffffff82111715613bec57613beb613b95565b5b80604052505050565b6000613bff6136d8565b9050613c0b8282613bc4565b919050565b600067ffffffffffffffff821115613c2b57613c2a613b95565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff821115613c6b57613c6a613b95565b5b613c74826137f6565b9050602081019050919050565b82818337600083830152505050565b6000613ca3613c9e84613c50565b613bf5565b905082815260208101848484011115613cbf57613cbe613c4b565b5b613cca848285613c81565b509392505050565b600082601f830112613ce757613ce6613b90565b5b8135613cf7848260208601613c90565b91505092915050565b600060408284031215613d1657613d15613c41565b5b613d206040613bf5565b9050600082013567ffffffffffffffff811115613d4057613d3f613c46565b5b613d4c84828501613cd2565b6000830152506020613d6084828501613883565b60208301525092915050565b6000613d7f613d7a84613c10565b613bf5565b90508083825260208201905060208402830185811115613da257613da1613c3c565b5b835b81811015613de957803567ffffffffffffffff811115613dc757613dc6613b90565b5b808601613dd48982613d00565b85526020850194505050602081019050613da4565b5050509392505050565b600082601f830112613e0857613e07613b90565b5b8135613e18848260208601613d6c565b91505092915050565b60008060408385031215613e3857613e376136e2565b5b6000613e4685828601613883565b925050602083013567ffffffffffffffff811115613e6757613e666136e7565b5b613e7385828601613df3565b9150509250929050565b600067ffffffffffffffff821115613e9857613e97613b95565b5b602082029050602081019050919050565b600060408284031215613ebf57613ebe613c41565b5b613ec96040613bf5565b9050600082013567ffffffffffffffff811115613ee957613ee8613c46565b5b613ef584828501613cd2565b6000830152506020613f0984828501613883565b60208301525092915050565b6000613f28613f2384613e7d565b613bf5565b90508083825260208201905060208402830185811115613f4b57613f4a613c3c565b5b835b81811015613f9257803567ffffffffffffffff811115613f7057613f6f613b90565b5b808601613f7d8982613ea9565b85526020850194505050602081019050613f4d565b5050509392505050565b600082601f830112613fb157613fb0613b90565b5b8135613fc1848260208601613f15565b91505092915050565b600060408284031215613fe057613fdf613c41565b5b613fea6040613bf5565b9050600082013567ffffffffffffffff81111561400a57614009613c46565b5b61401684828501613cd2565b600083015250602082013567ffffffffffffffff81111561403a57614039613c46565b5b61404684828501613f9c565b60208301525092915050565b60008060408385031215614069576140686136e2565b5b600061407785828601613883565b925050602083013567ffffffffffffffff811115614098576140976136e7565b5b6140a485828601613fca565b9150509250929050565b6140b781613771565b81146140c257600080fd5b50565b6000813590506140d4816140ae565b92915050565b600080604083850312156140f1576140f06136e2565b5b60006140ff85828601613938565b9250506020614110858286016140c5565b9150509250929050565b600067ffffffffffffffff82111561413557614134613b95565b5b61413e826137f6565b9050602081019050919050565b600061415e6141598461411a565b613bf5565b90508281526020810184848401111561417a57614179613c4b565b5b614185848285613c81565b509392505050565b600082601f8301126141a2576141a1613b90565b5b81356141b284826020860161414b565b91505092915050565b600080600080608085870312156141d5576141d46136e2565b5b60006141e387828801613938565b94505060206141f487828801613938565b935050604061420587828801613883565b925050606085013567ffffffffffffffff811115614226576142256136e7565b5b6142328782880161418d565b91505092959194509250565b61424781613ab1565b811461425257600080fd5b50565b6000813590506142648161423e565b92915050565b6000602082840312156142805761427f6136e2565b5b600061428e84828501614255565b91505092915050565b60006142a2826139c1565b9050919050565b60006142b482614297565b9050919050565b6142c4816142a9565b82525050565b60006020820190506142df60008301846142bb565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061432c57607f821691505b602082108114156143405761433f6142e5565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006143a2602c836137b2565b91506143ad82614346565b604082019050919050565b600060208201905081810360008301526143d181614395565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006144346021836137b2565b915061443f826143d8565b604082019050919050565b6000602082019050818103600083015261446381614427565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006144c66038836137b2565b91506144d18261446a565b604082019050919050565b600060208201905081810360008301526144f5816144b9565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b60006145586031836137b2565b9150614563826144fc565b604082019050919050565b600060208201905081810360008301526145878161454b565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b60006145ea602b836137b2565b91506145f58261458e565b604082019050919050565b60006020820190508181036000830152614619816145dd565b9050919050565b60008151905061462f8161386c565b92915050565b60006020828403121561464b5761464a6136e2565b5b600061465984828501614620565b91505092915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614698601f836137b2565b91506146a382614662565b602082019050919050565b600060208201905081810360008301526146c78161468b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061470882613862565b915061471383613862565b925082821015614726576147256146ce565b5b828203905092915050565b7f536f6c64206f7574000000000000000000000000000000000000000000000000600082015250565b60006147676008836137b2565b915061477282614731565b602082019050919050565b600060208201905081810360008301526147968161475a565b9050919050565b60006147a882613862565b91506147b383613862565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156147ec576147eb6146ce565b5b828202905092915050565b7f496e73756666696369656e74207061796d656e74000000000000000000000000600082015250565b600061482d6014836137b2565b9150614838826147f7565b602082019050919050565b6000602082019050818103600083015261485c81614820565b9050919050565b600061486e82613862565b915061487983613862565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156148ae576148ad6146ce565b5b828201905092915050565b60006148c482613862565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156148f7576148f66146ce565b5b600182019050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006149386020836137b2565b915061494382614902565b602082019050919050565b600060208201905081810360008301526149678161492b565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b60006149ca602c836137b2565b91506149d58261496e565b604082019050919050565b600060208201905081810360008301526149f9816149bd565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050614a3e8161423e565b92915050565b600060208284031215614a5a57614a596136e2565b5b6000614a6884828501614a2f565b91505092915050565b6000614a7c826138e5565b9050919050565b614a8c81614a71565b8114614a9757600080fd5b50565b600081519050614aa981614a83565b92915050565b600060208284031215614ac557614ac46136e2565b5b6000614ad384828501614a9a565b91505092915050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b6000614b386029836137b2565b9150614b4382614adc565b604082019050919050565b60006020820190508181036000830152614b6781614b2b565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614bca602a836137b2565b9150614bd582614b6e565b604082019050919050565b60006020820190508181036000830152614bf981614bbd565b9050919050565b600082825260208201905092915050565b6000614c1c826137a7565b614c268185614c00565b9350614c368185602086016137c3565b614c3f816137f6565b840191505092915050565b614c5381613862565b82525050565b60006040830160008301518482036000860152614c768282614c11565b9150506020830151614c8b6020860182614c4a565b508091505092915050565b6000604082019050614cab600083018561398d565b8181036020830152614cbd8184614c59565b90509392505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006040830160008301518482036000860152614d0f8282614c11565b9150506020830151614d246020860182614c4a565b508091505092915050565b6000614d3b8383614cf2565b905092915050565b6000602082019050919050565b6000614d5b82614cc6565b614d658185614cd1565b935083602082028501614d7785614ce2565b8060005b85811015614db35784840389528151614d948582614d2f565b9450614d9f83614d43565b925060208a01995050600181019050614d7b565b50829750879550505050505092915050565b60006040830160008301518482036000860152614de28282614c11565b91505060208301518482036020860152614dfc8282614d50565b9150508091505092915050565b6000604082019050614e1e600083018561398d565b8181036020830152614e308184614dc5565b90509392505050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614e6f6019836137b2565b9150614e7a82614e39565b602082019050919050565b60006020820190508181036000830152614e9e81614e62565b9050919050565b7f546f6b656e20646f65736e277420657869737400000000000000000000000000600082015250565b6000614edb6013836137b2565b9150614ee682614ea5565b602082019050919050565b60006020820190508181036000830152614f0a81614ece565b9050919050565b600081905092915050565b7f7b00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614f52600183614f11565b9150614f5d82614f1c565b600182019050919050565b7f226e616d65223a20220000000000000000000000000000000000000000000000600082015250565b6000614f9e600983614f11565b9150614fa982614f68565b600982019050919050565b6000614fbf826137a7565b614fc98185614f11565b9350614fd98185602086016137c3565b80840191505092915050565b7f2023000000000000000000000000000000000000000000000000000000000000600082015250565b600061501b600283614f11565b915061502682614fe5565b600282019050919050565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b6000615067600283614f11565b915061507282615031565b600282019050919050565b7f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b62617360008201527f6536342c00000000000000000000000000000000000000000000000000000000602082015250565b60006150d9602483614f11565b91506150e48261507d565b602482019050919050565b7f50484e325a79423361575230614430694d5451774d434967614756705a32683060008201527f505349784e4441774969423462577875637a30696148523063446f764c33643360208201527f647935334d793576636d63760000000000000000000000000000000000000000604082015250565b6000615171604c83614f11565b915061517c826150ef565b604c82019050919050565b7f4d6a41774d43397a646d6369494868746247357a4f6e68736157357250534a6f60008201527f644852774f693876643364334c6e637a4c6d39795a7938784f546b354c33687360208201527f61573572496a3438636d566a0000000000000000000000000000000000000000604082015250565b6000615209604c83614f11565b915061521482615187565b604c82019050919050565b7f6443423361575230614430694d5451774d434967614756705a3268305053497860008201527f4e4441774969427a64486c735a5430695a6d6c73624470795a32496f4d43777760208201527f4c4441704f334e30636d39720000000000000000000000000000000000000000604082015250565b60006152a1604c83614f11565b91506152ac8261521f565b604c82019050919050565b7f5a53313361576c6b644767364d4349674c7a34384c334e325a7a343d222c0000600082015250565b60006152ed601e83614f11565b91506152f8826152b7565b601e82019050919050565b7f2261747472696275746573223a205b0000000000000000000000000000000000600082015250565b6000615339600f83614f11565b915061534482615303565b600f82019050919050565b600061535a82614f45565b915061536582614f91565b91506153718285614fb4565b915061537c8261500e565b91506153888284614fb4565b91506153938261505a565b915061539e826150cc565b91506153a982615164565b91506153b4826151fc565b91506153bf82615294565b91506153ca826152e0565b91506153d58261532c565b91508190509392505050565b6000815190506153f0816140ae565b92915050565b60006020828403121561540c5761540b6136e2565b5b600061541a848285016153e1565b91505092915050565b60006154366154318461411a565b613bf5565b90508281526020810184848401111561545257615451613c4b565b5b61545d8482856137c3565b509392505050565b600082601f83011261547a57615479613b90565b5b815161548a848260208601615423565b91505092915050565b6000602082840312156154a9576154a86136e2565b5b600082015167ffffffffffffffff8111156154c7576154c66136e7565b5b6154d384828501615465565b91505092915050565b600081519050919050565b600081905092915050565b60006154fd826154dc565b61550781856154e7565b93506155178185602086016137c3565b80840191505092915050565b7f7b2276616c7565223a202254686520776f726c6420697320626574746572207760008201527f69746820796f7520696e206974227d0000000000000000000000000000000000602082015250565b600061557f602f83614f11565b915061558a82615523565b602f82019050919050565b60006155a182856154f2565b91506155ac82615572565b91506155b882846154f2565b91508190509392505050565b7f7b2276616c7565223a20224157474d493f227d00000000000000000000000000600082015250565b60006155fa601383614f11565b9150615605826155c4565b601382019050919050565b600061561c82846154f2565b9150615627826155ed565b915081905092915050565b7f5d00000000000000000000000000000000000000000000000000000000000000600082015250565b6000615668600183614f11565b915061567382615632565b600182019050919050565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b60006156b4600183614f11565b91506156bf8261567e565b600182019050919050565b60006156d682846154f2565b91506156e18261565b565b91506156ec826156a7565b915081905092915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b600061572d601d83614f11565b9150615738826156f7565b601d82019050919050565b600061574e82615720565b915061575a8284614fb4565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006157c16026836137b2565b91506157cc82615765565b604082019050919050565b600060208201905081810360008301526157f0816157b4565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000615853602c836137b2565b915061585e826157f7565b604082019050919050565b6000602082019050818103600083015261588281615846565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b60006158e56029836137b2565b91506158f082615889565b604082019050919050565b60006020820190508181036000830152615914816158d8565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006159776024836137b2565b91506159828261591b565b604082019050919050565b600060208201905081810360008301526159a68161596a565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006159e36014836137b2565b91506159ee826159ad565b602082019050919050565b60006020820190508181036000830152615a12816159d6565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000615a4f6010836137b2565b9150615a5a82615a19565b602082019050919050565b60006020820190508181036000830152615a7e81615a42565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000615ae16032836137b2565b9150615aec82615a85565b604082019050919050565b60006020820190508181036000830152615b1081615ad4565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000615b5182613862565b9150615b5c83613862565b925082615b6c57615b6b615b17565b5b828204905092915050565b6000615b8282613862565b9150615b8d83613862565b925082615b9d57615b9c615b17565b5b828206905092915050565b600082825260208201905092915050565b6000615bc4826154dc565b615bce8185615ba8565b9350615bde8185602086016137c3565b615be7816137f6565b840191505092915050565b6000608082019050615c0760008301876138f7565b615c1460208301866138f7565b615c21604083018561398d565b8181036060830152615c338184615bb9565b905095945050505050565b600081519050615c4d81613718565b92915050565b600060208284031215615c6957615c686136e2565b5b6000615c7784828501615c3e565b91505092915050565b7f4552433732315061757361626c653a20746f6b656e207472616e73666572207760008201527f68696c6520706175736564000000000000000000000000000000000000000000602082015250565b6000615cdc602b836137b2565b9150615ce782615c80565b604082019050919050565b60006020820190508181036000830152615d0b81615ccf565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000615d486020836137b2565b9150615d5382615d12565b602082019050919050565b60006020820190508181036000830152615d7781615d3b565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615db4601c836137b2565b9150615dbf82615d7e565b602082019050919050565b60006020820190508181036000830152615de381615da7565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205fc5c8265fb8fc07c2b26cdf8270eb45ab16aacebdeb179ace2494903ad87e5864736f6c6343000809003360a06040523480156200001157600080fd5b5060405162002bc538038062002bc5833981810160405281019062000037919062000174565b80620000586200004c6200006860201b60201c565b6200007060201b60201c565b80608081815250505050620001a6565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b6000819050919050565b6200014e8162000139565b81146200015a57600080fd5b50565b6000815190506200016e8162000143565b92915050565b6000602082840312156200018d576200018c62000134565b5b60006200019d848285016200015d565b91505092915050565b6080516129ee620001d760003960008181610eb5015281816112600152818161144f015261154b01526129ee6000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c8063a7b21d7511610097578063c2ee3a0811610066578063c2ee3a0814610277578063e24d9e2c14610295578063f2fde38b146102b1578063f47c84c5146102cd57610100565b8063a7b21d7514610203578063ada5f6421461021f578063ae1882fe1461023d578063b85a8b201461025957610100565b8063715018a6116100d3578063715018a61461018d5780638da5cb5b14610197578063922050cc146101b5578063a0d0ddbf146101e557610100565b8063217167ad1461010557806331aa7a70146101215780635404bbf71461015157806361ee40ab1461016f575b600080fd5b61011f600480360381019061011a91906118f4565b6102eb565b005b61013b60048036038101906101369190611950565b610407565b6040516101489190611b57565b60405180910390f35b6101596105d0565b6040516101669190611b92565b60405180910390f35b610177610621565b6040516101849190611bbc565b60405180910390f35b61019561062e565b005b61019f6106b6565b6040516101ac9190611c18565b60405180910390f35b6101cf60048036038101906101ca9190611950565b6106df565b6040516101dc9190611c88565b60405180910390f35b6101ed6109ff565b6040516101fa9190611cc5565b60405180910390f35b61021d60048036038101906102189190611eba565b610a0f565b005b610227610b42565b6040516102349190611bbc565b60405180910390f35b61025760048036038101906102529190611f16565b610b5d565b005b610261610cfa565b60405161026e9190611bbc565b60405180910390f35b61027f610d16565b60405161028c9190611bbc565b60405180910390f35b6102af60048036038101906102aa9190611fb1565b610d33565b005b6102cb60048036038101906102c6919061200a565b610dbb565b005b6102d5610eb3565b6040516102e29190611bbc565b60405180910390f35b6102f3610ed7565b73ffffffffffffffffffffffffffffffffffffffff166103116106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610367576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035e90612094565b60405180910390fd5b60038054905082146103ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103a590612126565b60405180910390fd5b600381908060018154018082558091505060019003906000526020600020906002020160009091909190915060008201518160000190805190602001906103f6929190611631565b506020820151816001015550505050565b61040f6116b7565b6002828154811061042357610422612146565b5b906000526020600020906002020160405180604001604052908160008201805461044c906121a4565b80601f0160208091040260200160405190810160405280929190818152602001828054610478906121a4565b80156104c55780601f1061049a576101008083540402835291602001916104c5565b820191906000526020600020905b8154815290600101906020018083116104a857829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156105c15783829060005260206000209060020201604051806040016040529081600082018054610526906121a4565b80601f0160208091040260200160405190810160405280929190818152602001828054610552906121a4565b801561059f5780601f106105745761010080835404028352916020019161059f565b820191906000526020600020905b81548152906001019060200180831161058257829003601f168201915b50505050508152602001600182015481525050815260200190600101906104f3565b50505050815250509050919050565b60006105da6109ff565b610619576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061090612222565b60405180910390fd5b600154905090565b6000600280549050905090565b610636610ed7565b73ffffffffffffffffffffffffffffffffffffffff166106546106b6565b73ffffffffffffffffffffffffffffffffffffffff16146106aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016106a190612094565b60405180910390fd5b6106b46000610edf565b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060006002805480602002602001604051908101604052809291908181526020016000905b828210156108c45783829060005260206000209060020201604051806040016040529081600082018054610738906121a4565b80601f0160208091040260200160405190810160405280929190818152602001828054610764906121a4565b80156107b15780601f10610786576101008083540402835291602001916107b1565b820191906000526020600020905b81548152906001019060200180831161079457829003601f168201915b5050505050815260200160018201805480602002602001604051908101604052809291908181526020016000905b828210156108ad5783829060005260206000209060020201604051806040016040529081600082018054610812906121a4565b80601f016020809104026020016040519081016040528092919081815260200182805461083e906121a4565b801561088b5780601f106108605761010080835404028352916020019161088b565b820191906000526020600020905b81548152906001019060200180831161086e57829003601f168201915b50505050508152602001600182015481525050815260200190600101906107df565b505050508152505081526020019060010190610705565b50505050905060006003805480602002602001604051908101604052809291908181526020016000905b828210156109bc5783829060005260206000209060020201604051806040016040529081600082018054610921906121a4565b80601f016020809104026020016040519081016040528092919081815260200182805461094d906121a4565b801561099a5780601f1061096f5761010080835404028352916020019161099a565b820191906000526020600020905b81548152906001019060200180831161097d57829003601f168201915b50505050508152602001600182015481525050815260200190600101906108ee565b5050505090506109cc8483610fa3565b6109d68583611005565b6040516020016109e792919061227e565b60405160208183030381529060405292505050919050565b60008060015460001c1415905090565b610a17610ed7565b73ffffffffffffffffffffffffffffffffffffffff16610a356106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610a8b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a8290612094565b60405180910390fd5b6002805490508214610ad2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ac990612314565b60405180910390fd5b600260018160018154018082558091505003906000526020600020905050806000015160028381548110610b0957610b08612146565b5b90600052602060002090600202016000019080519060200190610b2d929190611631565b50610b3e8260008360200151610b5d565b5050565b766867a5a867f103b2fffa5a71fba0e7b68000000000000081565b610b65610ed7565b73ffffffffffffffffffffffffffffffffffffffff16610b836106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610bd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bd090612094565b60405180910390fd5b60028381548110610bed57610bec612146565b5b9060005260206000209060020201600101805490508214610c43576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c3a906123a6565b60405180910390fd5b60005b8151811015610cf45760028481548110610c6357610c62612146565b5b9060005260206000209060020201600101828281518110610c8757610c86612146565b5b602002602001015190806001815401808255809150506001900390600052602060002090600202016000909190919091506000820151816000019080519060200190610cd4929190611631565b506020820151816001015550508080610cec906123f5565b915050610c46565b50505050565b7728c87cb5c89a2571ebfdcb54864ada834a0000000000000081565b780fee50b7025c36a0802f236d04753d5b48e80000000000000081565b610d3b610ed7565b73ffffffffffffffffffffffffffffffffffffffff16610d596106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610daf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610da690612094565b60405180910390fd5b610db881611067565b50565b610dc3610ed7565b73ffffffffffffffffffffffffffffffffffffffff16610de16106b6565b73ffffffffffffffffffffffffffffffffffffffff1614610e37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e2e90612094565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610ea7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e9e906124b0565b60405180910390fd5b610eb081610edf565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6060610ffd8383600067ffffffffffffffff811115610fc557610fc461174e565b5b6040519080825280601f01601f191660200182016040528015610ff75781602001600182028036833780820191505090505b506110b9565b905092915050565b606061105f8383600067ffffffffffffffff8111156110275761102661174e565b5b6040519080825280601f01601f1916602001820160405280156110595781602001600182028036833780820191505090505b50611259565b905092915050565b61106f6109ff565b156110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a69061251c565b60405180910390fd5b8060018190555050565b60606000606060005b855181101561124c57600061111786898985815181106110e5576110e4612146565b5b60200260200101516000015160405160200161110393929190612575565b604051602081830303815290604052611360565b90506000935060005b87838151811061113357611132612146565b5b602002602001015160200151518110156112375787838151811061115a57611159612146565b5b602002602001015160200151818151811061117857611177612146565b5b6020026020010151602001518561118f91906125ba565b945084821161122457836111fd8985815181106111af576111ae612146565b5b6020026020010151600001518a86815181106111ce576111cd612146565b5b60200260200101516020015184815181106111ec576111eb612146565b5b602002602001015160000151611410565b60405160200161120e92919061227e565b6040516020818303038152906040529350611237565b808061122f906123f5565b915050611120565b50508080611244906123f5565b9150506110c2565b5080925050509392505050565b60606000807f000000000000000000000000000000000000000000000000000000000000000090505b600081111561129c576001820191508060011c9050611282565b600060018360026112ad9190612743565b6112b7919061278e565b9050606060005b8751811015611351576112ee898983815181106112de576112dd612146565b5b602002602001015187868b61143c565b1561133e578161131b89838151811061130a57611309612146565b5b6020026020010151600001516115e9565b60405160200161132c92919061227e565b60405160208183030381529060405291505b8080611349906123f5565b9150506112be565b50809450505050509392505050565b600080780fffffffffffffffffffffffffffffffffffffffffffffffff905060005b780fee50b7025c36a0802f236d04753d5b48e8000000000000008211156114065760015484826040516020016113ba939291906127c2565b6040516020818303038152906040528051906020012060001c9150780fffffffffffffffffffffffffffffffffffffffffffffffff8216915080806113fe906123f5565b915050611382565b5080915050919050565b60608282604051602001611425929190612920565b604051602081830303815290604052905092915050565b60008060009050600080600090506000807f000000000000000000000000000000000000000000000000000000000000000067ffffffffffffffff8111156114875761148661174e565b5b6040519080825280602002602001820160405280156114b55781602001602082028036833780820191505090505b50905060005b8a602001518110156115d5575b6001156115c2578984101561152357876001548c60000151886040516020016114f49493929190612965565b6040516020818303038152906040528051906020012060001c9450858061151a906123f5565b96505061010093505b8885169250848a1c945089840393508b83141561154957600196505050505050506115e0565b7f00000000000000000000000000000000000000000000000000000000000000008310611575576114c8565b81838151811061158857611587612146565b5b60200260200101511561159a576114c8565b60018284815181106115af576115ae612146565b5b6020026020010190151590811515815250505b80806115cd906123f5565b9150506114bb565b506000955050505050505b95945050505050565b606061162a6040518060400160405280600a81526020017f4c6f6f6b7320526172650000000000000000000000000000000000000000000081525083611410565b9050919050565b82805461163d906121a4565b90600052602060002090601f01602090048101928261165f57600085556116a6565b82601f1061167857805160ff19168380011785556116a6565b828001600101855582156116a6579182015b828111156116a557825182559160200191906001019061168a565b5b5090506116b391906116d1565b5090565b604051806040016040528060608152602001606081525090565b5b808211156116ea5760008160009055506001016116d2565b5090565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61171581611702565b811461172057600080fd5b50565b6000813590506117328161170c565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6117868261173d565b810181811067ffffffffffffffff821117156117a5576117a461174e565b5b80604052505050565b60006117b86116ee565b90506117c4828261177d565b919050565b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff8211156117f3576117f261174e565b5b6117fc8261173d565b9050602081019050919050565b82818337600083830152505050565b600061182b611826846117d8565b6117ae565b905082815260208101848484011115611847576118466117d3565b5b611852848285611809565b509392505050565b600082601f83011261186f5761186e6117ce565b5b813561187f848260208601611818565b91505092915050565b60006040828403121561189e5761189d611738565b5b6118a860406117ae565b9050600082013567ffffffffffffffff8111156118c8576118c76117c9565b5b6118d48482850161185a565b60008301525060206118e884828501611723565b60208301525092915050565b6000806040838503121561190b5761190a6116f8565b5b600061191985828601611723565b925050602083013567ffffffffffffffff81111561193a576119396116fd565b5b61194685828601611888565b9150509250929050565b600060208284031215611966576119656116f8565b5b600061197484828501611723565b91505092915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156119b757808201518184015260208101905061199c565b838111156119c6576000848401525b50505050565b60006119d78261197d565b6119e18185611988565b93506119f1818560208601611999565b6119fa8161173d565b840191505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611a3a81611702565b82525050565b60006040830160008301518482036000860152611a5d82826119cc565b9150506020830151611a726020860182611a31565b508091505092915050565b6000611a898383611a40565b905092915050565b6000602082019050919050565b6000611aa982611a05565b611ab38185611a10565b935083602082028501611ac585611a21565b8060005b85811015611b015784840389528151611ae28582611a7d565b9450611aed83611a91565b925060208a01995050600181019050611ac9565b50829750879550505050505092915050565b60006040830160008301518482036000860152611b3082826119cc565b91505060208301518482036020860152611b4a8282611a9e565b9150508091505092915050565b60006020820190508181036000830152611b718184611b13565b905092915050565b6000819050919050565b611b8c81611b79565b82525050565b6000602082019050611ba76000830184611b83565b92915050565b611bb681611702565b82525050565b6000602082019050611bd16000830184611bad565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611c0282611bd7565b9050919050565b611c1281611bf7565b82525050565b6000602082019050611c2d6000830184611c09565b92915050565b600081519050919050565b600082825260208201905092915050565b6000611c5a82611c33565b611c648185611c3e565b9350611c74818560208601611999565b611c7d8161173d565b840191505092915050565b60006020820190508181036000830152611ca28184611c4f565b905092915050565b60008115159050919050565b611cbf81611caa565b82525050565b6000602082019050611cda6000830184611cb6565b92915050565b600067ffffffffffffffff821115611cfb57611cfa61174e565b5b602082029050602081019050919050565b600080fd5b600060408284031215611d2757611d26611738565b5b611d3160406117ae565b9050600082013567ffffffffffffffff811115611d5157611d506117c9565b5b611d5d8482850161185a565b6000830152506020611d7184828501611723565b60208301525092915050565b6000611d90611d8b84611ce0565b6117ae565b90508083825260208201905060208402830185811115611db357611db2611d0c565b5b835b81811015611dfa57803567ffffffffffffffff811115611dd857611dd76117ce565b5b808601611de58982611d11565b85526020850194505050602081019050611db5565b5050509392505050565b600082601f830112611e1957611e186117ce565b5b8135611e29848260208601611d7d565b91505092915050565b600060408284031215611e4857611e47611738565b5b611e5260406117ae565b9050600082013567ffffffffffffffff811115611e7257611e716117c9565b5b611e7e8482850161185a565b600083015250602082013567ffffffffffffffff811115611ea257611ea16117c9565b5b611eae84828501611e04565b60208301525092915050565b60008060408385031215611ed157611ed06116f8565b5b6000611edf85828601611723565b925050602083013567ffffffffffffffff811115611f0057611eff6116fd565b5b611f0c85828601611e32565b9150509250929050565b600080600060608486031215611f2f57611f2e6116f8565b5b6000611f3d86828701611723565b9350506020611f4e86828701611723565b925050604084013567ffffffffffffffff811115611f6f57611f6e6116fd565b5b611f7b86828701611e04565b9150509250925092565b611f8e81611b79565b8114611f9957600080fd5b50565b600081359050611fab81611f85565b92915050565b600060208284031215611fc757611fc66116f8565b5b6000611fd584828501611f9c565b91505092915050565b611fe781611bf7565b8114611ff257600080fd5b50565b60008135905061200481611fde565b92915050565b6000602082840312156120205761201f6116f8565b5b600061202e84828501611ff5565b91505092915050565b600082825260208201905092915050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061207e602083612037565b915061208982612048565b602082019050919050565b600060208201905081810360008301526120ad81612071565b9050919050565b7f52616e646f6d417474726962757465733a20696e76616c696420616c6c6f636160008201527f74656420696e6465780000000000000000000000000000000000000000000000602082015250565b6000612110602983612037565b915061211b826120b4565b604082019050919050565b6000602082019050818103600083015261213f81612103565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806121bc57607f821691505b602082108114156121d0576121cf612175565b5b50919050565b7f456e74726f7079206e6f74207365740000000000000000000000000000000000600082015250565b600061220c600f83612037565b9150612217826121d6565b602082019050919050565b6000602082019050818103600083015261223b816121ff565b9050919050565b600081905092915050565b600061225882611c33565b6122628185612242565b9350612272818560208601611999565b80840191505092915050565b600061228a828561224d565b9150612296828461224d565b91508190509392505050565b7f52616e646f6d417474726962757465733a20696e76616c69642074696572656460008201527f20696e6465780000000000000000000000000000000000000000000000000000602082015250565b60006122fe602683612037565b9150612309826122a2565b604082019050919050565b6000602082019050818103600083015261232d816122f1565b9050919050565b7f52616e646f6d417474726962757465733a20696e76616c69642073746172744960008201527f6e64657800000000000000000000000000000000000000000000000000000000602082015250565b6000612390602483612037565b915061239b82612334565b604082019050919050565b600060208201905081810360008301526123bf81612383565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061240082611702565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415612433576124326123c6565b5b600182019050919050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061249a602683612037565b91506124a58261243e565b604082019050919050565b600060208201905081810360008301526124c98161248d565b9050919050565b7f456e74726f707920616c72656164792073657400000000000000000000000000600082015250565b6000612506601383612037565b9150612511826124d0565b602082019050919050565b60006020820190508181036000830152612535816124f9565b9050919050565b60006125478261197d565b6125518185612037565b9350612561818560208601611999565b61256a8161173d565b840191505092915050565b6000606082019050818103600083015261258f8186611c4f565b905061259e6020830185611bad565b81810360408301526125b0818461253c565b9050949350505050565b60006125c582611702565b91506125d083611702565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03821115612605576126046123c6565b5b828201905092915050565b60008160011c9050919050565b6000808291508390505b600185111561266757808604811115612643576126426123c6565b5b60018516156126525780820291505b808102905061266085612610565b9450612627565b94509492505050565b600082612680576001905061273c565b8161268e576000905061273c565b81600181146126a457600281146126ae576126dd565b600191505061273c565b60ff8411156126c0576126bf6123c6565b5b8360020a9150848211156126d7576126d66123c6565b5b5061273c565b5060208310610133831016604e8410600b84101617156127125782820a90508381111561270d5761270c6123c6565b5b61273c565b61271f848484600161261d565b92509050818404811115612736576127356123c6565b5b81810290505b9392505050565b600061274e82611702565b915061275983611702565b92506127867fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8484612670565b905092915050565b600061279982611702565b91506127a483611702565b9250828210156127b7576127b66123c6565b5b828203905092915050565b60006060820190506127d76000830186611b83565b81810360208301526127e98185611c4f565b90506127f86040830184611bad565b949350505050565b600081905092915050565b7f2c7b2274726169745f74797065223a2022000000000000000000000000000000600082015250565b6000612841601183612800565b915061284c8261280b565b601182019050919050565b60006128628261197d565b61286c8185612800565b935061287c818560208601611999565b80840191505092915050565b7f222c202276616c7565223a202200000000000000000000000000000000000000600082015250565b60006128be600d83612800565b91506128c982612888565b600d82019050919050565b7f227d000000000000000000000000000000000000000000000000000000000000600082015250565b600061290a600283612800565b9150612915826128d4565b600282019050919050565b600061292b82612834565b91506129378285612857565b9150612942826128b1565b915061294e8284612857565b9150612959826128fd565b91508190509392505050565b6000608082019050818103600083015261297f8187611c4f565b905061298e6020830186611b83565b81810360408301526129a0818561253c565b90506129af6060830184611bad565b9594505050505056fea26469706673582212205b62e392c4bf9ee02aee3493ea664070f1667ca72124c9e7ba060f01efe2af7c64736f6c6343000809003300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c100000000000000000000000000000000000000000000000000000000000026f1000000000000000000000000be02b9ee0d4c0c13ea622fa82411033cf369dd50000000000000000000000000000000000000000000000000000000000000000c426c61636b205371756172650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b424c41434b535155415245000000000000000000000000000000000000000000
Deployed Bytecode
0x60806040526004361061021a5760003560e01c80636352211e11610123578063a22cb465116100ab578063e8a3d4851161006f578063e8a3d485146107c4578063e985e9c5146107ef578063ed4a6b0c1461082c578063f2fde38b14610857578063f47c84c5146108805761021a565b8063a22cb465146106e1578063b88d4fde1461070a578063c002d23d14610733578063c87b56dd1461075e578063e24d9e2c1461079b5761021a565b80638456cb59116100f25780638456cb59146106225780638a7ac5c7146106395780638da5cb5b1461066257806395d89b411461068d57806396b83514146106b85761021a565b80636352211e146105685780636b29b79f146105a557806370a08231146105ce578063715018a61461060b5761021a565b80632f745c59116101a657806342842e0e1161017557806342842e0e1461046f5780634f6ccce7146104985780635404bbf7146104d55780635c975abb146105005780636102de981461052b5761021a565b80632f745c59146103d45780632f7b19151461041157806331c864e81461043c5780633f4ba83a146104585761021a565b80630aaef285116101ed5780630aaef285146102ed5780630cc96d521461031857806318160ddd146103435780631e7269c51461036e57806323b872dd146103ab5761021a565b806301ffc9a71461021f57806306fdde031461025c578063081812fc14610287578063095ea7b3146102c4575b600080fd5b34801561022b57600080fd5b5061024660048036038101906102419190613744565b6108ab565b604051610253919061378c565b60405180910390f35b34801561026857600080fd5b506102716108bd565b60405161027e9190613840565b60405180910390f35b34801561029357600080fd5b506102ae60048036038101906102a99190613898565b61094f565b6040516102bb9190613906565b60405180910390f35b3480156102d057600080fd5b506102eb60048036038101906102e6919061394d565b6109d4565b005b3480156102f957600080fd5b50610302610aec565b60405161030f919061399c565b60405180910390f35b34801561032457600080fd5b5061032d610af1565b60405161033a9190613a16565b60405180910390f35b34801561034f57600080fd5b50610358610b15565b604051610365919061399c565b60405180910390f35b34801561037a57600080fd5b5061039560048036038101906103909190613a31565b610b22565b6040516103a2919061399c565b60405180910390f35b3480156103b757600080fd5b506103d260048036038101906103cd9190613a5e565b610b3a565b005b3480156103e057600080fd5b506103fb60048036038101906103f6919061394d565b610b9a565b604051610408919061399c565b60405180910390f35b34801561041d57600080fd5b50610426610c3f565b604051610433919061399c565b60405180910390f35b61045660048036038101906104519190613898565b610ce4565b005b34801561046457600080fd5b5061046d6110bf565b005b34801561047b57600080fd5b5061049660048036038101906104919190613a5e565b611145565b005b3480156104a457600080fd5b506104bf60048036038101906104ba9190613898565b611165565b6040516104cc919061399c565b60405180910390f35b3480156104e157600080fd5b506104ea6111d6565b6040516104f79190613aca565b60405180910390f35b34801561050c57600080fd5b5061051561127b565b604051610522919061378c565b60405180910390f35b34801561053757600080fd5b50610552600480360381019061054d9190613ae5565b611292565b60405161055f919061378c565b60405180910390f35b34801561057457600080fd5b5061058f600480360381019061058a9190613898565b6113b3565b60405161059c9190613906565b60405180910390f35b3480156105b157600080fd5b506105cc60048036038101906105c79190613b63565b611465565b005b3480156105da57600080fd5b506105f560048036038101906105f09190613a31565b611525565b604051610602919061399c565b60405180910390f35b34801561061757600080fd5b506106206115dd565b005b34801561062e57600080fd5b50610637611665565b005b34801561064557600080fd5b50610660600480360381019061065b9190613e21565b6116eb565b005b34801561066e57600080fd5b5061067761183d565b6040516106849190613906565b60405180910390f35b34801561069957600080fd5b506106a2611867565b6040516106af9190613840565b60405180910390f35b3480156106c457600080fd5b506106df60048036038101906106da9190614052565b6118f9565b005b3480156106ed57600080fd5b50610708600480360381019061070391906140da565b611a06565b005b34801561071657600080fd5b50610731600480360381019061072c91906141bb565b611b87565b005b34801561073f57600080fd5b50610748611be9565b604051610755919061399c565b60405180910390f35b34801561076a57600080fd5b5061078560048036038101906107809190613898565b611bf5565b6040516107929190613840565b60405180910390f35b3480156107a757600080fd5b506107c260048036038101906107bd919061426a565b611e62565b005b3480156107d057600080fd5b506107d9611f6c565b6040516107e69190613840565b60405180910390f35b3480156107fb57600080fd5b5061081660048036038101906108119190613ae5565b611ffe565b604051610823919061378c565b60405180910390f35b34801561083857600080fd5b50610841612023565b60405161084e91906142ca565b60405180910390f35b34801561086357600080fd5b5061087e60048036038101906108799190613a31565b612049565b005b34801561088c57600080fd5b50610895612141565b6040516108a2919061399c565b60405180910390f35b60006108b6826121a9565b9050919050565b6060600280546108cc90614314565b80601f01602080910402602001604051908101604052809291908181526020018280546108f890614314565b80156109455780601f1061091a57610100808354040283529160200191610945565b820191906000526020600020905b81548152906001019060200180831161092857829003601f168201915b5050505050905090565b600061095a82612223565b610999576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610990906143b8565b60405180910390fd5b6006600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b60006109df826113b3565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a479061444a565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16610a6f61228f565b73ffffffffffffffffffffffffffffffffffffffff161480610a9e5750610a9d81610a9861228f565b611ffe565b5b610add576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ad4906144dc565b60405180910390fd5b610ae78383612297565b505050565b600a81565b7f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde81565b6000600a80549050905090565b600f6020528060005260406000206000915090505481565b610b4b610b4561228f565b82612350565b610b8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b819061456e565b60405180910390fd5b610b9583838361242e565b505050565b6000610ba583611525565b8210610be6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bdd90614600565b60405180910390fd5b600860008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002054905092915050565b60007f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663ada5f6426040518163ffffffff1660e01b815260040160206040518083038186803b158015610ca757600080fd5b505afa158015610cbb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cdf9190614635565b905090565b6002600d541415610d2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d21906146ae565b60405180910390fd5b6002600d81905550610d7281336040518060400160405280600c81526020017f53656e646572206c696d6974000000000000000000000000000000000000000081525061268a565b90503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610dea57610de781326040518060400160405280600c81526020017f4f726967696e206c696d6974000000000000000000000000000000000000000081525061268a565b90505b6000610df4610b15565b90506000817f00000000000000000000000000000000000000000000000000000000000026f1610e2491906146fd565b905060008111610e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e609061477d565b60405180910390fd5b80831115610e75578092505b600067016345785d8a000084610e8b919061479d565b905080341015610ed0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ec790614843565b60405180910390fd5b83600f60003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610f1f9190614863565b925050819055503273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610fb05783600f60003273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254610fa89190614863565b925050819055505b60008484610fbe9190614863565b90505b80841015610fe657610fd3338561273f565b8380610fde906148b9565b945050610fc1565b50600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561104f573d6000803e3d6000fd5b50803411156110b15760003390508073ffffffffffffffffffffffffffffffffffffffff166108fc833461108391906146fd565b9081150290604051600060405180830381858888f193505050501580156110ae573d6000803e3d6000fd5b50505b5050506001600d8190555050565b6110c761228f565b73ffffffffffffffffffffffffffffffffffffffff166110e561183d565b73ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111329061494e565b60405180910390fd5b61114361275d565b565b61116083838360405180602001604052806000815250611b87565b505050565b600061116f610b15565b82106111b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111a7906149e0565b60405180910390fd5b600a82815481106111c4576111c3614a00565b5b90600052602060002001549050919050565b60007f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff16635404bbf76040518163ffffffff1660e01b815260040160206040518083038186803b15801561123e57600080fd5b505afa158015611252573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112769190614a44565b905090565b6000600c60149054906101000a900460ff16905090565b600080600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141580156113aa57508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1663c4552791866040518263ffffffff1660e01b81526004016113429190613906565b60206040518083038186803b15801561135a57600080fd5b505afa15801561136e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113929190614aaf565b73ffffffffffffffffffffffffffffffffffffffff16145b91505092915050565b6000806004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561145c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161145390614b4e565b60405180910390fd5b80915050919050565b61146d61228f565b73ffffffffffffffffffffffffffffffffffffffff1661148b61183d565b73ffffffffffffffffffffffffffffffffffffffff16146114e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114d89061494e565b60405180910390fd5b80600e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611596576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158d90614be0565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b6115e561228f565b73ffffffffffffffffffffffffffffffffffffffff1661160361183d565b73ffffffffffffffffffffffffffffffffffffffff1614611659576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116509061494e565b60405180910390fd5b61166360006127ff565b565b61166d61228f565b73ffffffffffffffffffffffffffffffffffffffff1661168b61183d565b73ffffffffffffffffffffffffffffffffffffffff16146116e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116d89061494e565b60405180910390fd5b6116e96128c5565b565b6116f361228f565b73ffffffffffffffffffffffffffffffffffffffff1661171161183d565b73ffffffffffffffffffffffffffffffffffffffff1614611767576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175e9061494e565b60405180910390fd5b60005b8151811015611838577f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663217167ad82856117bb9190614863565b8484815181106117ce576117cd614a00565b5b60200260200101516040518363ffffffff1660e01b81526004016117f3929190614c96565b600060405180830381600087803b15801561180d57600080fd5b505af1158015611821573d6000803e3d6000fd5b505050508080611830906148b9565b91505061176a565b505050565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60606003805461187690614314565b80601f01602080910402602001604051908101604052809291908181526020018280546118a290614314565b80156118ef5780601f106118c4576101008083540402835291602001916118ef565b820191906000526020600020905b8154815290600101906020018083116118d257829003601f168201915b5050505050905090565b61190161228f565b73ffffffffffffffffffffffffffffffffffffffff1661191f61183d565b73ffffffffffffffffffffffffffffffffffffffff1614611975576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161196c9061494e565b60405180910390fd5b7f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663a7b21d7583836040518363ffffffff1660e01b81526004016119d0929190614e09565b600060405180830381600087803b1580156119ea57600080fd5b505af11580156119fe573d6000803e3d6000fd5b505050505050565b611a0e61228f565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611a7c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a7390614e85565b60405180910390fd5b8060076000611a8961228f565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611b3661228f565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3183604051611b7b919061378c565b60405180910390a35050565b611b98611b9261228f565b83612350565b611bd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bce9061456e565b60405180910390fd5b611be384848484612968565b50505050565b67016345785d8a000081565b6060611c0082612223565b611c3f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c3690614ef1565b60405180910390fd5b6000611c496108bd565b611c52846129c4565b604051602001611c6392919061534f565b60405160208183030381529060405290507f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663a0d0ddbf6040518163ffffffff1660e01b815260040160206040518083038186803b158015611cda57600080fd5b505afa158015611cee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d1291906153f6565b15611ded57807f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663922050cc856040518263ffffffff1660e01b8152600401611d71919061399c565b60006040518083038186803b158015611d8957600080fd5b505afa158015611d9d573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250810190611dc69190615493565b604051602001611dd7929190615595565b6040516020818303038152906040529050611e10565b80604051602001611dfe9190615610565b60405160208183030381529060405290505b80604051602001611e2191906156ca565b6040516020818303038152906040529050611e3b81612b25565b604051602001611e4b9190615743565b604051602081830303815290604052915050919050565b611e6a61228f565b73ffffffffffffffffffffffffffffffffffffffff16611e8861183d565b73ffffffffffffffffffffffffffffffffffffffff1614611ede576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed59061494e565b60405180910390fd5b7f0000000000000000000000006e9e94bc2fb2b129e38d322d4060da30aff0efde73ffffffffffffffffffffffffffffffffffffffff1663e24d9e2c826040518263ffffffff1660e01b8152600401611f379190613aca565b600060405180830381600087803b158015611f5157600080fd5b505af1158015611f65573d6000803e3d6000fd5b5050505050565b606060008054611f7b90614314565b80601f0160208091040260200160405190810160405280929190818152602001828054611fa790614314565b8015611ff45780601f10611fc957610100808354040283529160200191611ff4565b820191906000526020600020905b815481529060010190602001808311611fd757829003601f168201915b5050505050905090565b600061200a8383612c9e565b8061201b575061201a8383611292565b5b905092915050565b600e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61205161228f565b73ffffffffffffffffffffffffffffffffffffffff1661206f61183d565b73ffffffffffffffffffffffffffffffffffffffff16146120c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120bc9061494e565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612135576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161212c906157d7565b60405180910390fd5b61213e816127ff565b50565b7f00000000000000000000000000000000000000000000000000000000000026f181565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60007f780e9d63000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061221c575061221b82612d32565b5b9050919050565b60008073ffffffffffffffffffffffffffffffffffffffff166004600084815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614159050919050565b600033905090565b816006600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff1661230a836113b3565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b600061235b82612223565b61239a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161239190615869565b60405180910390fd5b60006123a5836113b3565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061241457508373ffffffffffffffffffffffffffffffffffffffff166123fc8461094f565b73ffffffffffffffffffffffffffffffffffffffff16145b8061242557506124248185611ffe565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff1661244e826113b3565b73ffffffffffffffffffffffffffffffffffffffff16146124a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161249b906158fb565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612514576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161250b9061598d565b60405180910390fd5b61251f838383612e14565b61252a600082612297565b6001600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461257a91906146fd565b925050819055506001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546125d19190614863565b92505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b600080600f60008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054600a6126d991906146fd565b9050600081118390612721576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127189190613840565b60405180910390fd5b50808511156127335780915050612738565b849150505b9392505050565b612759828260405180602001604052806000815250612e24565b5050565b61276561127b565b6127a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279b906159f9565b60405180910390fd5b6000600c60146101000a81548160ff0219169083151502179055507f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6127e861228f565b6040516127f59190613906565b60405180910390a1565b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6128cd61127b565b1561290d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161290490615a65565b60405180910390fd5b6001600c60146101000a81548160ff0219169083151502179055507f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861295161228f565b60405161295e9190613906565b60405180910390a1565b61297384848461242e565b61297f84848484612e7f565b6129be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b590615af7565b60405180910390fd5b50505050565b60606000821415612a0c576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050612b20565b600082905060005b60008214612a3e578080612a27906148b9565b915050600a82612a379190615b46565b9150612a14565b60008167ffffffffffffffff811115612a5a57612a59613b95565b5b6040519080825280601f01601f191660200182016040528015612a8c5781602001600182028036833780820191505090505b5090505b60008514612b1957600182612aa591906146fd565b9150600a85612ab49190615b77565b6030612ac09190614863565b60f81b818381518110612ad657612ad5614a00565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a85612b129190615b46565b9450612a90565b8093505050505b919050565b6060600082511415612b4857604051806020016040528060008152509050612c99565b6000604051806060016040528060408152602001615e1a6040913990506000600360028551612b779190614863565b612b819190615b46565b6004612b8d919061479d565b90506000602082612b9e9190614863565b67ffffffffffffffff811115612bb757612bb6613b95565b5b6040519080825280601f01601f191660200182016040528015612be95781602001600182028036833780820191505090505b509050818152600183018586518101602084015b81831015612c58576003830192508251603f8160121c168501518253600182019150603f81600c1c168501518253600182019150603f8160061c168501518253600182019150603f8116850151825360018201915050612bfd565b600389510660018114612c725760028114612c8257612c8d565b613d3d60f01b6002830352612c8d565b603d60f81b60018303525b50505050508093505050505b919050565b6000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b60007f80ac58cd000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161480612dfd57507f5b5e139f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b80612e0d5750612e0c82613016565b5b9050919050565b612e1f838383613080565b505050565b612e2e83836130d8565b612e3b6000848484612e7f565b612e7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e7190615af7565b60405180910390fd5b505050565b6000612ea08473ffffffffffffffffffffffffffffffffffffffff166132a6565b15613009578373ffffffffffffffffffffffffffffffffffffffff1663150b7a02612ec961228f565b8786866040518563ffffffff1660e01b8152600401612eeb9493929190615bf2565b602060405180830381600087803b158015612f0557600080fd5b505af1925050508015612f3657506040513d601f19601f82011682018060405250810190612f339190615c53565b60015b612fb9573d8060008114612f66576040519150601f19603f3d011682016040523d82523d6000602084013e612f6b565b606091505b50600081511415612fb1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fa890615af7565b60405180910390fd5b805181602001fd5b63150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161491505061300e565b600190505b949350505050565b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b61308b8383836132b9565b61309361127b565b156130d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ca90615cf2565b60405180910390fd5b505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415613148576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161313f90615d5e565b60405180910390fd5b61315181612223565b15613191576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161318890615dca565b60405180910390fd5b61319d60008383612e14565b6001600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546131ed9190614863565b92505081905550816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080823b905060008111915050919050565b6132c48383836133cd565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561330757613302816133d2565b613346565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461334557613344838261341b565b5b5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156133895761338481613588565b6133c8565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146133c7576133c68282613659565b5b5b505050565b505050565b600a80549050600b600083815260200190815260200160002081905550600a81908060018154018082558091505060019003906000526020600020016000909190919091505550565b6000600161342884611525565b61343291906146fd565b9050600060096000848152602001908152602001600020549050818114613517576000600860008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002054905080600860008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600084815260200190815260200160002081905550816009600083815260200190815260200160002081905550505b6009600084815260200190815260200160002060009055600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008381526020019081526020016000206000905550505050565b60006001600a8054905061359c91906146fd565b90506000600b60008481526020019081526020016000205490506000600a83815481106135cc576135cb614a00565b5b9060005260206000200154905080600a83815481106135ee576135ed614a00565b5b906000526020600020018190555081600b600083815260200190815260200160002081905550600b600085815260200190815260200160002060009055600a80548061363d5761363c615dea565b5b6001900381819060005260206000200160009055905550505050565b600061366483611525565b905081600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600083815260200190815260200160002081905550806009600084815260200190815260200160002081905550505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b613721816136ec565b811461372c57600080fd5b50565b60008135905061373e81613718565b92915050565b60006020828403121561375a576137596136e2565b5b60006137688482850161372f565b91505092915050565b60008115159050919050565b61378681613771565b82525050565b60006020820190506137a1600083018461377d565b92915050565b600081519050919050565b600082825260208201905092915050565b60005b838110156137e15780820151818401526020810190506137c6565b838111156137f0576000848401525b50505050565b6000601f19601f8301169050919050565b6000613812826137a7565b61381c81856137b2565b935061382c8185602086016137c3565b613835816137f6565b840191505092915050565b6000602082019050818103600083015261385a8184613807565b905092915050565b6000819050919050565b61387581613862565b811461388057600080fd5b50565b6000813590506138928161386c565b92915050565b6000602082840312156138ae576138ad6136e2565b5b60006138bc84828501613883565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006138f0826138c5565b9050919050565b613900816138e5565b82525050565b600060208201905061391b60008301846138f7565b92915050565b61392a816138e5565b811461393557600080fd5b50565b60008135905061394781613921565b92915050565b60008060408385031215613964576139636136e2565b5b600061397285828601613938565b925050602061398385828601613883565b9150509250929050565b61399681613862565b82525050565b60006020820190506139b1600083018461398d565b92915050565b6000819050919050565b60006139dc6139d76139d2846138c5565b6139b7565b6138c5565b9050919050565b60006139ee826139c1565b9050919050565b6000613a00826139e3565b9050919050565b613a10816139f5565b82525050565b6000602082019050613a2b6000830184613a07565b92915050565b600060208284031215613a4757613a466136e2565b5b6000613a5584828501613938565b91505092915050565b600080600060608486031215613a7757613a766136e2565b5b6000613a8586828701613938565b9350506020613a9686828701613938565b9250506040613aa786828701613883565b9150509250925092565b6000819050919050565b613ac481613ab1565b82525050565b6000602082019050613adf6000830184613abb565b92915050565b60008060408385031215613afc57613afb6136e2565b5b6000613b0a85828601613938565b9250506020613b1b85828601613938565b9150509250929050565b6000613b30826138c5565b9050919050565b613b4081613b25565b8114613b4b57600080fd5b50565b600081359050613b5d81613b37565b92915050565b600060208284031215613b7957613b786136e2565b5b6000613b8784828501613b4e565b91505092915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b613bcd826137f6565b810181811067ffffffffffffffff82111715613bec57613beb613b95565b5b80604052505050565b6000613bff6136d8565b9050613c0b8282613bc4565b919050565b600067ffffffffffffffff821115613c2b57613c2a613b95565b5b602082029050602081019050919050565b600080fd5b600080fd5b600080fd5b600080fd5b600067ffffffffffffffff821115613c6b57613c6a613b95565b5b613c74826137f6565b9050602081019050919050565b82818337600083830152505050565b6000613ca3613c9e84613c50565b613bf5565b905082815260208101848484011115613cbf57613cbe613c4b565b5b613cca848285613c81565b509392505050565b600082601f830112613ce757613ce6613b90565b5b8135613cf7848260208601613c90565b91505092915050565b600060408284031215613d1657613d15613c41565b5b613d206040613bf5565b9050600082013567ffffffffffffffff811115613d4057613d3f613c46565b5b613d4c84828501613cd2565b6000830152506020613d6084828501613883565b60208301525092915050565b6000613d7f613d7a84613c10565b613bf5565b90508083825260208201905060208402830185811115613da257613da1613c3c565b5b835b81811015613de957803567ffffffffffffffff811115613dc757613dc6613b90565b5b808601613dd48982613d00565b85526020850194505050602081019050613da4565b5050509392505050565b600082601f830112613e0857613e07613b90565b5b8135613e18848260208601613d6c565b91505092915050565b60008060408385031215613e3857613e376136e2565b5b6000613e4685828601613883565b925050602083013567ffffffffffffffff811115613e6757613e666136e7565b5b613e7385828601613df3565b9150509250929050565b600067ffffffffffffffff821115613e9857613e97613b95565b5b602082029050602081019050919050565b600060408284031215613ebf57613ebe613c41565b5b613ec96040613bf5565b9050600082013567ffffffffffffffff811115613ee957613ee8613c46565b5b613ef584828501613cd2565b6000830152506020613f0984828501613883565b60208301525092915050565b6000613f28613f2384613e7d565b613bf5565b90508083825260208201905060208402830185811115613f4b57613f4a613c3c565b5b835b81811015613f9257803567ffffffffffffffff811115613f7057613f6f613b90565b5b808601613f7d8982613ea9565b85526020850194505050602081019050613f4d565b5050509392505050565b600082601f830112613fb157613fb0613b90565b5b8135613fc1848260208601613f15565b91505092915050565b600060408284031215613fe057613fdf613c41565b5b613fea6040613bf5565b9050600082013567ffffffffffffffff81111561400a57614009613c46565b5b61401684828501613cd2565b600083015250602082013567ffffffffffffffff81111561403a57614039613c46565b5b61404684828501613f9c565b60208301525092915050565b60008060408385031215614069576140686136e2565b5b600061407785828601613883565b925050602083013567ffffffffffffffff811115614098576140976136e7565b5b6140a485828601613fca565b9150509250929050565b6140b781613771565b81146140c257600080fd5b50565b6000813590506140d4816140ae565b92915050565b600080604083850312156140f1576140f06136e2565b5b60006140ff85828601613938565b9250506020614110858286016140c5565b9150509250929050565b600067ffffffffffffffff82111561413557614134613b95565b5b61413e826137f6565b9050602081019050919050565b600061415e6141598461411a565b613bf5565b90508281526020810184848401111561417a57614179613c4b565b5b614185848285613c81565b509392505050565b600082601f8301126141a2576141a1613b90565b5b81356141b284826020860161414b565b91505092915050565b600080600080608085870312156141d5576141d46136e2565b5b60006141e387828801613938565b94505060206141f487828801613938565b935050604061420587828801613883565b925050606085013567ffffffffffffffff811115614226576142256136e7565b5b6142328782880161418d565b91505092959194509250565b61424781613ab1565b811461425257600080fd5b50565b6000813590506142648161423e565b92915050565b6000602082840312156142805761427f6136e2565b5b600061428e84828501614255565b91505092915050565b60006142a2826139c1565b9050919050565b60006142b482614297565b9050919050565b6142c4816142a9565b82525050565b60006020820190506142df60008301846142bb565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061432c57607f821691505b602082108114156143405761433f6142e5565b5b50919050565b7f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b60006143a2602c836137b2565b91506143ad82614346565b604082019050919050565b600060208201905081810360008301526143d181614395565b9050919050565b7f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b60006144346021836137b2565b915061443f826143d8565b604082019050919050565b6000602082019050818103600083015261446381614427565b9050919050565b7f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760008201527f6e6572206e6f7220617070726f76656420666f7220616c6c0000000000000000602082015250565b60006144c66038836137b2565b91506144d18261446a565b604082019050919050565b600060208201905081810360008301526144f5816144b9565b9050919050565b7f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60008201527f776e6572206e6f7220617070726f766564000000000000000000000000000000602082015250565b60006145586031836137b2565b9150614563826144fc565b604082019050919050565b600060208201905081810360008301526145878161454b565b9050919050565b7f455243373231456e756d657261626c653a206f776e657220696e646578206f7560008201527f74206f6620626f756e6473000000000000000000000000000000000000000000602082015250565b60006145ea602b836137b2565b91506145f58261458e565b604082019050919050565b60006020820190508181036000830152614619816145dd565b9050919050565b60008151905061462f8161386c565b92915050565b60006020828403121561464b5761464a6136e2565b5b600061465984828501614620565b91505092915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b6000614698601f836137b2565b91506146a382614662565b602082019050919050565b600060208201905081810360008301526146c78161468b565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061470882613862565b915061471383613862565b925082821015614726576147256146ce565b5b828203905092915050565b7f536f6c64206f7574000000000000000000000000000000000000000000000000600082015250565b60006147676008836137b2565b915061477282614731565b602082019050919050565b600060208201905081810360008301526147968161475a565b9050919050565b60006147a882613862565b91506147b383613862565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156147ec576147eb6146ce565b5b828202905092915050565b7f496e73756666696369656e74207061796d656e74000000000000000000000000600082015250565b600061482d6014836137b2565b9150614838826147f7565b602082019050919050565b6000602082019050818103600083015261485c81614820565b9050919050565b600061486e82613862565b915061487983613862565b9250827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038211156148ae576148ad6146ce565b5b828201905092915050565b60006148c482613862565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156148f7576148f66146ce565b5b600182019050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006149386020836137b2565b915061494382614902565b602082019050919050565b600060208201905081810360008301526149678161492b565b9050919050565b7f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60008201527f7574206f6620626f756e64730000000000000000000000000000000000000000602082015250565b60006149ca602c836137b2565b91506149d58261496e565b604082019050919050565b600060208201905081810360008301526149f9816149bd565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600081519050614a3e8161423e565b92915050565b600060208284031215614a5a57614a596136e2565b5b6000614a6884828501614a2f565b91505092915050565b6000614a7c826138e5565b9050919050565b614a8c81614a71565b8114614a9757600080fd5b50565b600081519050614aa981614a83565b92915050565b600060208284031215614ac557614ac46136e2565b5b6000614ad384828501614a9a565b91505092915050565b7f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460008201527f656e7420746f6b656e0000000000000000000000000000000000000000000000602082015250565b6000614b386029836137b2565b9150614b4382614adc565b604082019050919050565b60006020820190508181036000830152614b6781614b2b565b9050919050565b7f4552433732313a2062616c616e636520717565727920666f7220746865207a6560008201527f726f206164647265737300000000000000000000000000000000000000000000602082015250565b6000614bca602a836137b2565b9150614bd582614b6e565b604082019050919050565b60006020820190508181036000830152614bf981614bbd565b9050919050565b600082825260208201905092915050565b6000614c1c826137a7565b614c268185614c00565b9350614c368185602086016137c3565b614c3f816137f6565b840191505092915050565b614c5381613862565b82525050565b60006040830160008301518482036000860152614c768282614c11565b9150506020830151614c8b6020860182614c4a565b508091505092915050565b6000604082019050614cab600083018561398d565b8181036020830152614cbd8184614c59565b90509392505050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b60006040830160008301518482036000860152614d0f8282614c11565b9150506020830151614d246020860182614c4a565b508091505092915050565b6000614d3b8383614cf2565b905092915050565b6000602082019050919050565b6000614d5b82614cc6565b614d658185614cd1565b935083602082028501614d7785614ce2565b8060005b85811015614db35784840389528151614d948582614d2f565b9450614d9f83614d43565b925060208a01995050600181019050614d7b565b50829750879550505050505092915050565b60006040830160008301518482036000860152614de28282614c11565b91505060208301518482036020860152614dfc8282614d50565b9150508091505092915050565b6000604082019050614e1e600083018561398d565b8181036020830152614e308184614dc5565b90509392505050565b7f4552433732313a20617070726f766520746f2063616c6c657200000000000000600082015250565b6000614e6f6019836137b2565b9150614e7a82614e39565b602082019050919050565b60006020820190508181036000830152614e9e81614e62565b9050919050565b7f546f6b656e20646f65736e277420657869737400000000000000000000000000600082015250565b6000614edb6013836137b2565b9150614ee682614ea5565b602082019050919050565b60006020820190508181036000830152614f0a81614ece565b9050919050565b600081905092915050565b7f7b00000000000000000000000000000000000000000000000000000000000000600082015250565b6000614f52600183614f11565b9150614f5d82614f1c565b600182019050919050565b7f226e616d65223a20220000000000000000000000000000000000000000000000600082015250565b6000614f9e600983614f11565b9150614fa982614f68565b600982019050919050565b6000614fbf826137a7565b614fc98185614f11565b9350614fd98185602086016137c3565b80840191505092915050565b7f2023000000000000000000000000000000000000000000000000000000000000600082015250565b600061501b600283614f11565b915061502682614fe5565b600282019050919050565b7f222c000000000000000000000000000000000000000000000000000000000000600082015250565b6000615067600283614f11565b915061507282615031565b600282019050919050565b7f22696d616765223a2022646174613a696d6167652f7376672b786d6c3b62617360008201527f6536342c00000000000000000000000000000000000000000000000000000000602082015250565b60006150d9602483614f11565b91506150e48261507d565b602482019050919050565b7f50484e325a79423361575230614430694d5451774d434967614756705a32683060008201527f505349784e4441774969423462577875637a30696148523063446f764c33643360208201527f647935334d793576636d63760000000000000000000000000000000000000000604082015250565b6000615171604c83614f11565b915061517c826150ef565b604c82019050919050565b7f4d6a41774d43397a646d6369494868746247357a4f6e68736157357250534a6f60008201527f644852774f693876643364334c6e637a4c6d39795a7938784f546b354c33687360208201527f61573572496a3438636d566a0000000000000000000000000000000000000000604082015250565b6000615209604c83614f11565b915061521482615187565b604c82019050919050565b7f6443423361575230614430694d5451774d434967614756705a3268305053497860008201527f4e4441774969427a64486c735a5430695a6d6c73624470795a32496f4d43777760208201527f4c4441704f334e30636d39720000000000000000000000000000000000000000604082015250565b60006152a1604c83614f11565b91506152ac8261521f565b604c82019050919050565b7f5a53313361576c6b644767364d4349674c7a34384c334e325a7a343d222c0000600082015250565b60006152ed601e83614f11565b91506152f8826152b7565b601e82019050919050565b7f2261747472696275746573223a205b0000000000000000000000000000000000600082015250565b6000615339600f83614f11565b915061534482615303565b600f82019050919050565b600061535a82614f45565b915061536582614f91565b91506153718285614fb4565b915061537c8261500e565b91506153888284614fb4565b91506153938261505a565b915061539e826150cc565b91506153a982615164565b91506153b4826151fc565b91506153bf82615294565b91506153ca826152e0565b91506153d58261532c565b91508190509392505050565b6000815190506153f0816140ae565b92915050565b60006020828403121561540c5761540b6136e2565b5b600061541a848285016153e1565b91505092915050565b60006154366154318461411a565b613bf5565b90508281526020810184848401111561545257615451613c4b565b5b61545d8482856137c3565b509392505050565b600082601f83011261547a57615479613b90565b5b815161548a848260208601615423565b91505092915050565b6000602082840312156154a9576154a86136e2565b5b600082015167ffffffffffffffff8111156154c7576154c66136e7565b5b6154d384828501615465565b91505092915050565b600081519050919050565b600081905092915050565b60006154fd826154dc565b61550781856154e7565b93506155178185602086016137c3565b80840191505092915050565b7f7b2276616c7565223a202254686520776f726c6420697320626574746572207760008201527f69746820796f7520696e206974227d0000000000000000000000000000000000602082015250565b600061557f602f83614f11565b915061558a82615523565b602f82019050919050565b60006155a182856154f2565b91506155ac82615572565b91506155b882846154f2565b91508190509392505050565b7f7b2276616c7565223a20224157474d493f227d00000000000000000000000000600082015250565b60006155fa601383614f11565b9150615605826155c4565b601382019050919050565b600061561c82846154f2565b9150615627826155ed565b915081905092915050565b7f5d00000000000000000000000000000000000000000000000000000000000000600082015250565b6000615668600183614f11565b915061567382615632565b600182019050919050565b7f7d00000000000000000000000000000000000000000000000000000000000000600082015250565b60006156b4600183614f11565b91506156bf8261567e565b600182019050919050565b60006156d682846154f2565b91506156e18261565b565b91506156ec826156a7565b915081905092915050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c000000600082015250565b600061572d601d83614f11565b9150615738826156f7565b601d82019050919050565b600061574e82615720565b915061575a8284614fb4565b915081905092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006157c16026836137b2565b91506157cc82615765565b604082019050919050565b600060208201905081810360008301526157f0816157b4565b9050919050565b7f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860008201527f697374656e7420746f6b656e0000000000000000000000000000000000000000602082015250565b6000615853602c836137b2565b915061585e826157f7565b604082019050919050565b6000602082019050818103600083015261588281615846565b9050919050565b7f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960008201527f73206e6f74206f776e0000000000000000000000000000000000000000000000602082015250565b60006158e56029836137b2565b91506158f082615889565b604082019050919050565b60006020820190508181036000830152615914816158d8565b9050919050565b7f4552433732313a207472616e7366657220746f20746865207a65726f2061646460008201527f7265737300000000000000000000000000000000000000000000000000000000602082015250565b60006159776024836137b2565b91506159828261591b565b604082019050919050565b600060208201905081810360008301526159a68161596a565b9050919050565b7f5061757361626c653a206e6f7420706175736564000000000000000000000000600082015250565b60006159e36014836137b2565b91506159ee826159ad565b602082019050919050565b60006020820190508181036000830152615a12816159d6565b9050919050565b7f5061757361626c653a2070617573656400000000000000000000000000000000600082015250565b6000615a4f6010836137b2565b9150615a5a82615a19565b602082019050919050565b60006020820190508181036000830152615a7e81615a42565b9050919050565b7f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560008201527f63656976657220696d706c656d656e7465720000000000000000000000000000602082015250565b6000615ae16032836137b2565b9150615aec82615a85565b604082019050919050565b60006020820190508181036000830152615b1081615ad4565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000615b5182613862565b9150615b5c83613862565b925082615b6c57615b6b615b17565b5b828204905092915050565b6000615b8282613862565b9150615b8d83613862565b925082615b9d57615b9c615b17565b5b828206905092915050565b600082825260208201905092915050565b6000615bc4826154dc565b615bce8185615ba8565b9350615bde8185602086016137c3565b615be7816137f6565b840191505092915050565b6000608082019050615c0760008301876138f7565b615c1460208301866138f7565b615c21604083018561398d565b8181036060830152615c338184615bb9565b905095945050505050565b600081519050615c4d81613718565b92915050565b600060208284031215615c6957615c686136e2565b5b6000615c7784828501615c3e565b91505092915050565b7f4552433732315061757361626c653a20746f6b656e207472616e73666572207760008201527f68696c6520706175736564000000000000000000000000000000000000000000602082015250565b6000615cdc602b836137b2565b9150615ce782615c80565b604082019050919050565b60006020820190508181036000830152615d0b81615ccf565b9050919050565b7f4552433732313a206d696e7420746f20746865207a65726f2061646472657373600082015250565b6000615d486020836137b2565b9150615d5382615d12565b602082019050919050565b60006020820190508181036000830152615d7781615d3b565b9050919050565b7f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000600082015250565b6000615db4601c836137b2565b9150615dbf82615d7e565b602082019050919050565b60006020820190508181036000830152615de381615da7565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212205fc5c8265fb8fc07c2b26cdf8270eb45ab16aacebdeb179ace2494903ad87e5864736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c100000000000000000000000000000000000000000000000000000000000026f1000000000000000000000000be02b9ee0d4c0c13ea622fa82411033cf369dd50000000000000000000000000000000000000000000000000000000000000000c426c61636b205371756172650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b424c41434b535155415245000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : name (string): Black Square
Arg [1] : symbol (string): BLACKSQUARE
Arg [2] : openSeaProxyRegistry (address): 0xa5409ec958C83C3f309868babACA7c86DCB077c1
Arg [3] : maxTokens (uint256): 9969
Arg [4] : _paymentSplitter (address): 0xbe02b9Ee0d4c0c13ea622Fa82411033cF369dD50
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [2] : 000000000000000000000000a5409ec958c83c3f309868babaca7c86dcb077c1
Arg [3] : 00000000000000000000000000000000000000000000000000000000000026f1
Arg [4] : 000000000000000000000000be02b9ee0d4c0c13ea622fa82411033cf369dd50
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000c
Arg [6] : 426c61636b205371756172650000000000000000000000000000000000000000
Arg [7] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [8] : 424c41434b535155415245000000000000000000000000000000000000000000
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.