NFT
Overview
TokenID
2451
Total Transfers
-
Market
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract
Loading...
Loading
Loading...
Loading
Loading...
Loading
# | Exchange | Pair | Price | 24H Volume | % Volume |
---|
Contract Name:
FloorGen3
Compiler Version
v0.8.9+commit.e5eed63a
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2022-01-22 */ // File: @openzeppelin/contracts/utils/Counters.sol // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) pragma solidity ^0.8.0; /** * @title Counters * @author Matt Condon (@shrugs) * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number * of elements in a mapping, issuing ERC721 ids, or counting request ids. * * Include with `using Counters for Counters.Counter;` */ library Counters { struct Counter { // This variable should never be directly accessed by users of the library: interactions must be restricted to // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add // this feature: see https://github.com/ethereum/solidity/issues/4637 uint256 _value; // default: 0 } function current(Counter storage counter) internal view returns (uint256) { return counter._value; } function increment(Counter storage counter) internal { unchecked { counter._value += 1; } } function decrement(Counter storage counter) internal { uint256 value = counter._value; require(value > 0, "Counter: decrement overflow"); unchecked { counter._value = value - 1; } } function reset(Counter storage counter) internal { counter._value = 0; } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts v4.4.1 (utils/Strings.sol) 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); } } // File: @openzeppelin/contracts/utils/cryptography/ECDSA.sol // OpenZeppelin Contracts v4.4.1 (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } else if (error == RecoverError.InvalidSignatureV) { revert("ECDSA: invalid signature 'v' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { // Check the signature length // - case 65: r,s,v signature (standard) // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._ if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else if (signature.length == 64) { bytes32 r; bytes32 vs; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. assembly { r := mload(add(signature, 0x20)) vs := mload(add(signature, 0x40)) } return tryRecover(hash, r, vs); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address, RecoverError) { bytes32 s; uint8 v; assembly { s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff) v := add(shr(255, vs), 27) } return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover( bytes32 hash, bytes32 r, bytes32 vs ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } if (v != 27 && v != 28) { return (address(0), RecoverError.InvalidSignatureV); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { // 32 is the length in bytes of hash, // enforced by the type signature above return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); } } // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } // File: @openzeppelin/contracts/utils/introspection/IERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } // File: @openzeppelin/contracts/utils/introspection/ERC165.sol // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } } // File: @openzeppelin/contracts/token/ERC721/IERC721.sol // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, 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; } // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol // OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol) pragma solidity ^0.8.0; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Metadata is IERC721 { /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); } // File: @openzeppelin/contracts/security/ReentrancyGuard.sol // OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { // 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; } } // File: @openzeppelin/contracts/utils/Address.sol // OpenZeppelin Contracts v4.4.1 (utils/Address.sol) 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); } } } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: @openzeppelin/contracts/utils/Context.sol // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } } // File: @openzeppelin/contracts/token/ERC721/ERC721.sol // OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: 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 { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: 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 Approve `operator` to operate on all of `owner` tokens * * Emits a {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev 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 {} } // File: @openzeppelin/contracts/finance/PaymentSplitter.sol // OpenZeppelin Contracts v4.4.1 (finance/PaymentSplitter.sol) pragma solidity ^0.8.0; /** * @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. * * NOTE: This contract assumes that ERC20 tokens will behave similarly to native tokens (Ether). Rebasing tokens, and * tokens that apply fees during transfers, are likely to not be supported as expected. If in doubt, we encourage you * to run tests before sending real value to this contract. */ contract PaymentSplitter is Context { event PayeeAdded(address account, uint256 shares); event PaymentReleased(address to, uint256 amount); event ERC20PaymentReleased(IERC20 indexed token, 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; mapping(IERC20 => uint256) private _erc20TotalReleased; mapping(IERC20 => mapping(address => uint256)) private _erc20Released; /** * @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 total amount of `token` already released. `token` should be the address of an IERC20 * contract. */ function totalReleased(IERC20 token) public view returns (uint256) { return _erc20TotalReleased[token]; } /** * @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 amount of `token` tokens already released to a payee. `token` should be the address of an * IERC20 contract. */ function released(IERC20 token, address account) public view returns (uint256) { return _erc20Released[token][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 = _pendingPayment(account, totalReceived, released(account)); require(payment != 0, "PaymentSplitter: account is not due payment"); _released[account] += payment; _totalReleased += payment; Address.sendValue(account, payment); emit PaymentReleased(account, payment); } /** * @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their * percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20 * contract. */ function release(IERC20 token, address account) public virtual { require(_shares[account] > 0, "PaymentSplitter: account has no shares"); uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token); uint256 payment = _pendingPayment(account, totalReceived, released(token, account)); require(payment != 0, "PaymentSplitter: account is not due payment"); _erc20Released[token][account] += payment; _erc20TotalReleased[token] += payment; SafeERC20.safeTransfer(token, account, payment); emit ERC20PaymentReleased(token, account, payment); } /** * @dev internal logic for computing the pending payment of an `account` given the token historical balances and * already released amounts. */ function _pendingPayment( address account, uint256 totalReceived, uint256 alreadyReleased ) private view returns (uint256) { return (totalReceived * _shares[account]) / _totalShares - alreadyReleased; } /** * @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_); } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev 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 { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: contracts/EIP712Claimable.sol //SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; contract EIP712Claimable is Ownable { using ECDSA for bytes32; // The key used to sign whitelist signatures. // We will check to ensure that the key that signed the signature // is this one that we expect. address claimSigningKey = address(0); // Domain Separator is the EIP-712 defined structure that defines what contract // and chain these signatures can be used for. This ensures people can't take // a signature used to mint on one contract and use it for another, or a signature // from testnet to replay on mainnet. // It has to be created in the constructor so we can dynamically grab the chainId. // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#definition-of-domainseparator bytes32 public DOMAIN_SEPARATOR; // The typehash for the data type specified in the structured data // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#rationale-for-typehash // This should match whats in the client side whitelist signing code // https://github.com/msfeldstein/EIP712-whitelisting/blob/main/test/signWhitelist.ts#L22 bytes32 public constant MINTER_TYPEHASH = keccak256("Minter(address wallet,uint256 count)"); constructor() { // This should match whats in the client side whitelist signing code // https://github.com/msfeldstein/EIP712-whitelisting/blob/main/test/signWhitelist.ts#L12 DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256( "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" ), // This should match the domain you set in your client side signing. keccak256(bytes("ClaimToken")), keccak256(bytes("1")), block.chainid, address(this) ) ); } function setClaimSigningAddress(address newSigningKey) public onlyOwner { claimSigningKey = newSigningKey; } modifier requiresClaim(bytes calldata signature, uint256 count) { require(claimSigningKey != address(0), "claiming not enabled"); // Verify EIP-712 signature by recreating the data structure // that we signed on the client side, and then using that to recover // the address that signed the signature for this data. bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, keccak256(abi.encode( MINTER_TYPEHASH, msg.sender, count)) ) ); // Use the recover method to see what address was used to create // the signature on this data. // Note that if the digest doesn't exactly match what was signed we'll // get a random recovered address. address recoveredAddress = digest.recover(signature); require(recoveredAddress == claimSigningKey, "Invalid Signature"); _; } } // File: contracts/floor_gen3.sol // ███╗ ███╗ █████╗ ██████╗ ███████╗ ██╗ ██╗██╗████████╗██╗ ██╗ ███╗ ███╗ █████╗ ███████╗ ██████╗ ███╗ ██╗ // ████╗ ████║██╔══██╗██╔══██╗██╔════╝ ██║ ██║██║╚══██╔══╝██║ ██║ ████╗ ████║██╔══██╗██╔════╝██╔═══██╗████╗ ██║ // ██╔████╔██║███████║██║ ██║█████╗ ██║ █╗ ██║██║ ██║ ███████║ ██╔████╔██║███████║███████╗██║ ██║██╔██╗ ██║ // ██║╚██╔╝██║██╔══██║██║ ██║██╔══╝ ██║███╗██║██║ ██║ ██╔══██║ ██║╚██╔╝██║██╔══██║╚════██║██║ ██║██║╚██╗██║ // ██║ ╚═╝ ██║██║ ██║██████╔╝███████╗ ╚███╔███╔╝██║ ██║ ██║ ██║ ██║ ╚═╝ ██║██║ ██║███████║╚██████╔╝██║ ╚████║ // ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═══╝ pragma solidity ^0.8.9; contract FloorGen3 is ERC721, ReentrancyGuard, Ownable, EIP712Claimable{ using Counters for Counters.Counter; uint256 public PRICE; uint256 public MAX_SUPPLY; uint256 public MAX_RESERVED_SUPPLY; uint256 public MAX_PUBLIC_SUPPLY; uint256 public MAX_PER_WALLET; uint256 public MAX_MULTIMINT; Counters.Counter private supplyCounter; Counters.Counter private reservedSupplyCounter; PaymentSplitter private _splitter; constructor ( string memory tokenName, string memory tokenSymbol, string memory customBaseURI_, address[] memory payees, uint256[] memory shares, uint256 _tokenPrice, uint256 _tokensForSale, uint256 _tokensReserved) ERC721(tokenName, tokenSymbol) { customBaseURI = customBaseURI_; PRICE = _tokenPrice; MAX_SUPPLY = _tokensForSale; MAX_RESERVED_SUPPLY = _tokensReserved; MAX_PUBLIC_SUPPLY = MAX_SUPPLY - MAX_RESERVED_SUPPLY; MAX_PER_WALLET = 20; MAX_MULTIMINT = 5; _splitter = new PaymentSplitter(payees, shares); } /** MINTING **/ function mint(uint256 count) public payable nonReentrant { require(saleIsActive, "Sale not active"); require(totalPublicSupply() + count - 1 < MAX_PUBLIC_SUPPLY, "Exceeds max supply"); require(count - 1 < MAX_MULTIMINT, "Trying to mint too many at a time"); require( msg.value >= PRICE * count, "Insufficient payment" ); if (allowedMintCount(msg.sender) > count) { updateMintCount(msg.sender, count); } else { revert("Minting limit exceeded"); } for (uint256 i = 0; i < count; i++) { supplyCounter.increment(); _safeMint(msg.sender, totalSupply()); } payable(_splitter).transfer(msg.value); } function ownerMint(uint256 count, address recipient) external onlyOwner() { require(totalReservedSupply() + count - 1 < MAX_RESERVED_SUPPLY, "Exceeds max reserved supply"); require(totalSupply() + count - 1 < MAX_SUPPLY , "Exceeds max supply"); for (uint256 i = 0; i < count; i++) { reservedSupplyCounter.increment(); _safeMint(recipient, totalSupply()); } } function totalSupply() public view returns (uint256) { return supplyCounter.current() + reservedSupplyCounter.current(); } function totalPublicSupply() public view returns (uint256) { return supplyCounter.current(); } function totalReservedSupply() public view returns (uint256) { return reservedSupplyCounter.current(); } /** ACTIVATION **/ bool public saleIsActive = true; function flipSaleState() external onlyOwner { saleIsActive = !saleIsActive; } /** ADMIN **/ function setPrice(uint256 _tokenPrice) external onlyOwner { PRICE = _tokenPrice; } function setMultiMint(uint256 _maxMultimint) external onlyOwner { MAX_MULTIMINT = _maxMultimint; } function setMaxPerWallet(uint256 _maxPerWallet) external onlyOwner { MAX_PER_WALLET = _maxPerWallet; } /** MINTING LIMITS **/ mapping(address => uint256) private mintCountMap; function allowedMintCount(address minter) public view returns (uint256) { return MAX_PER_WALLET - mintCountMap[minter]; } function updateMintCount(address minter, uint256 count) private { mintCountMap[minter] += count; } /** Claiming **/ mapping(address => uint256) private claimCounts; bool public claimingIsActive = true; function flipClaimState() external onlyOwner { claimingIsActive = !claimingIsActive; } function tokensClaimed(address minter) public view returns (uint256) { return claimCounts[minter]; } function checkClaimlist(uint256 count, bytes calldata signature) public view requiresClaim(signature, count) returns (bool) { return true; } function hasUnclaimedTokens(address minter) public view returns (bool) { return claimCounts[minter] == 0; } function updateClaimCount(address minter, uint256 count) private { claimCounts[minter] += count; } function claimTokens(uint256 count, bytes calldata signature) public payable requiresClaim(signature, count) nonReentrant { require(claimingIsActive, "Claiming not active"); require(totalReservedSupply() + count - 1 < MAX_RESERVED_SUPPLY, "Exceeds max reserved supply"); require(totalSupply() + count - 1 < MAX_SUPPLY , "Exceeds max supply"); if (hasUnclaimedTokens(msg.sender)) { updateClaimCount(msg.sender, count); } else { revert("You have already claimed all your tokens"); } for (uint256 i = 0; i < count; i++) { reservedSupplyCounter.increment(); _safeMint(msg.sender, totalSupply()); } } /** OWNERSHIP **/ // WARNING: This function is not expensive, it should not be called from within the contract!!! function tokensOfOwner(address _owner) external view returns(uint256[] memory ownerTokens) { uint256 tokenCount = balanceOf(_owner); if (tokenCount == 0) { return new uint256[](1); } else { uint256[] memory result = new uint256[](tokenCount); uint256 totalTokens = totalSupply(); uint256 resultIndex = 0; uint256 tokenId; for (tokenId = 1; tokenId <= totalTokens; tokenId++) { if (ownerOf(tokenId) == _owner) { result[resultIndex] = tokenId; resultIndex++; } } return result; } } /** URI HANDLING **/ string private customBaseURI; function baseTokenURI() public view returns (string memory) { return customBaseURI; } function setBaseURI(string memory customBaseURI_) external onlyOwner { customBaseURI = customBaseURI_; } function _baseURI() internal view virtual override returns (string memory) { return customBaseURI; } /** PAYOUT **/ function release(address payable account) public virtual onlyOwner { _splitter.release(account); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"},{"internalType":"string","name":"customBaseURI_","type":"string"},{"internalType":"address[]","name":"payees","type":"address[]"},{"internalType":"uint256[]","name":"shares","type":"uint256[]"},{"internalType":"uint256","name":"_tokenPrice","type":"uint256"},{"internalType":"uint256","name":"_tokensForSale","type":"uint256"},{"internalType":"uint256","name":"_tokensReserved","type":"uint256"}],"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":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_MULTIMINT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PER_WALLET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PUBLIC_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_RESERVED_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"allowedMintCount","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":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"checkClaimlist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"claimTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"claimingIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flipClaimState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flipSaleState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"hasUnclaimedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"count","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"ownerMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"account","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"saleIsActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"customBaseURI_","type":"string"}],"name":"setBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newSigningKey","type":"address"}],"name":"setClaimSigningAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxPerWallet","type":"uint256"}],"name":"setMaxPerWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxMultimint","type":"uint256"}],"name":"setMultiMint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenPrice","type":"uint256"}],"name":"setPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"tokensClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"tokensOfOwner","outputs":[{"internalType":"uint256[]","name":"ownerTokens","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPublicSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalReservedSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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"}]
Contract Creation Code
6080604052600880546001600160a01b03191690556012805460ff60a01b1916600160a01b1790556015805460ff191660011790553480156200004157600080fd5b5060405162004ba838038062004ba883398101604081905262000064916200051c565b8751889088906200007d90600090602085019062000278565b5080516200009390600190602084019062000278565b5050600160065550620000a63362000226565b604080518082018252600a81526921b630b4b6aa37b5b2b760b11b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f918101919091527f1a5ffc51a62587b65b913137cec30fb0c9d9d6a475b2e58ca97b8b470cb94172918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160408051601f198184030181529190528051602091820120600955865162000191916016919089019062000278565b50600a839055600b829055600c819055620001ad81836200061a565b600d556014600e556005600f5560405185908590620001cc9062000307565b620001d992919062000640565b604051809103906000f080158015620001f6573d6000803e3d6000fd5b50601280546001600160a01b0319166001600160a01b039290921691909117905550620007059650505050505050565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b8280546200028690620006c8565b90600052602060002090601f016020900481019282620002aa5760008555620002f5565b82601f10620002c557805160ff1916838001178555620002f5565b82800160010185558215620002f5579182015b82811115620002f5578251825591602001919060010190620002d8565b506200030392915062000315565b5090565b61123d806200396b83390190565b5b8082111562000303576000815560010162000316565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200036d576200036d6200032c565b604052919050565b600082601f8301126200038757600080fd5b81516001600160401b03811115620003a357620003a36200032c565b6020620003b9601f8301601f1916820162000342565b8281528582848701011115620003ce57600080fd5b60005b83811015620003ee578581018301518282018401528201620003d1565b83811115620004005760008385840101525b5095945050505050565b60006001600160401b038211156200042657620004266200032c565b5060051b60200190565b600082601f8301126200044257600080fd5b815160206200045b62000455836200040a565b62000342565b82815260059290921b840181019181810190868411156200047b57600080fd5b8286015b84811015620004af5780516001600160a01b0381168114620004a15760008081fd5b83529183019183016200047f565b509695505050505050565b600082601f830112620004cc57600080fd5b81516020620004df62000455836200040a565b82815260059290921b84018101918181019086841115620004ff57600080fd5b8286015b84811015620004af578051835291830191830162000503565b600080600080600080600080610100898b0312156200053a57600080fd5b88516001600160401b03808211156200055257600080fd5b620005608c838d0162000375565b995060208b01519150808211156200057757600080fd5b620005858c838d0162000375565b985060408b01519150808211156200059c57600080fd5b620005aa8c838d0162000375565b975060608b0151915080821115620005c157600080fd5b620005cf8c838d0162000430565b965060808b0151915080821115620005e657600080fd5b50620005f58b828c01620004ba565b94505060a0890151925060c0890151915060e089015190509295985092959890939650565b6000828210156200063b57634e487b7160e01b600052601160045260246000fd5b500390565b604080825283519082018190526000906020906060840190828701845b82811015620006845781516001600160a01b0316845292840192908401906001016200065d565b5050508381038285015284518082528583019183019060005b81811015620006bb578351835292840192918401916001016200069d565b5090979650505050505050565b600181811c90821680620006dd57607f821691505b60208210811415620006ff57634e487b7160e01b600052602260045260246000fd5b50919050565b61325680620007156000396000f3fe6080604052600436106102fd5760003560e01c8063715018a61161018f578063bb660c0a116100e1578063e268e4d31161008a578063eb8d244411610064578063eb8d244414610844578063f2fde38b14610865578063fa4d280c1461088557600080fd5b8063e268e4d3146107c6578063e6a5931e146107e6578063e985e9c5146107fb57600080fd5b8063d52c57e0116100bb578063d52c57e01461077b578063d547cfb71461079b578063dfe0ce18146107b057600080fd5b8063bb660c0a1461071b578063bece913b1461073b578063c87b56dd1461075b57600080fd5b806395d89b4111610143578063b3feb36d1161011d578063b3feb36d146106ae578063b88d4fde146106e5578063b8fc10511461070557600080fd5b806395d89b4114610666578063a0712d681461067b578063a22cb4651461068e57600080fd5b80638d859f3e116101745780638d859f3e146106125780638da5cb5b1461062857806391b7f5ed1461064657600080fd5b8063715018a6146105d05780638462151c146105e557600080fd5b80632a47f7991161025357806355f804b3116101fc578063674d13c8116101d6578063674d13c8146105865780636d60e6c11461059b57806370a08231146105b057600080fd5b806355f804b314610510578063624601b6146105305780636352211e1461056657600080fd5b80633644e5151161022d5780633644e515146104ba57806342842e0e146104d057806350001a92146104f057600080fd5b80632a47f7991461047957806332cb6b0c1461048f57806334918dfd146104a557600080fd5b8063095ea7b3116102b557806318160ddd1161028f57806318160ddd14610424578063191655871461043957806323b872dd1461045957600080fd5b8063095ea7b3146103cd5780630f2cdd6c146103ed57806314d8bbf11461041157600080fd5b806307688939116102e6578063076889391461035957806307cf3a771461037b578063081812fc1461039557600080fd5b806301ffc9a71461030257806306fdde0314610337575b600080fd5b34801561030e57600080fd5b5061032261031d366004612c74565b6108b9565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b5061034c610956565b60405161032e9190612ce9565b34801561036557600080fd5b50610379610374366004612d11565b6109e8565b005b34801561038757600080fd5b506015546103229060ff1681565b3480156103a157600080fd5b506103b56103b0366004612d2e565b610a57565b6040516001600160a01b03909116815260200161032e565b3480156103d957600080fd5b506103796103e8366004612d47565b610aec565b3480156103f957600080fd5b50610403600e5481565b60405190815260200161032e565b61037961041f366004612d73565b610c1e565b34801561043057600080fd5b50610403611012565b34801561044557600080fd5b50610379610454366004612d11565b61102f565b34801561046557600080fd5b50610379610474366004612def565b6110f2565b34801561048557600080fd5b50610403600d5481565b34801561049b57600080fd5b50610403600b5481565b3480156104b157600080fd5b50610379611179565b3480156104c657600080fd5b5061040360095481565b3480156104dc57600080fd5b506103796104eb366004612def565b6111fd565b3480156104fc57600080fd5b5061037961050b366004612d2e565b611218565b34801561051c57600080fd5b5061037961052b366004612ebc565b611265565b34801561053c57600080fd5b5061040361054b366004612d11565b6001600160a01b031660009081526014602052604090205490565b34801561057257600080fd5b506103b5610581366004612d2e565b6112c4565b34801561059257600080fd5b5061040361134f565b3480156105a757600080fd5b5061037961135a565b3480156105bc57600080fd5b506104036105cb366004612d11565b6113b6565b3480156105dc57600080fd5b50610379611450565b3480156105f157600080fd5b50610605610600366004612d11565b6114a4565b60405161032e9190612f05565b34801561061e57600080fd5b50610403600a5481565b34801561063457600080fd5b506007546001600160a01b03166103b5565b34801561065257600080fd5b50610379610661366004612d2e565b6115ae565b34801561067257600080fd5b5061034c6115fb565b610379610689366004612d2e565b61160a565b34801561069a57600080fd5b506103796106a9366004612f49565b6118de565b3480156106ba57600080fd5b506103226106c9366004612d11565b6001600160a01b03166000908152601460205260409020541590565b3480156106f157600080fd5b50610379610700366004612f87565b6118e9565b34801561071157600080fd5b50610403600f5481565b34801561072757600080fd5b50610403610736366004612d11565b611977565b34801561074757600080fd5b50610322610756366004612d73565b61199d565b34801561076757600080fd5b5061034c610776366004612d2e565b611b49565b34801561078757600080fd5b50610379610796366004613007565b611c32565b3480156107a757600080fd5b5061034c611d84565b3480156107bc57600080fd5b50610403600c5481565b3480156107d257600080fd5b506103796107e1366004612d2e565b611d93565b3480156107f257600080fd5b50610403611de0565b34801561080757600080fd5b5061032261081636600461302c565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b34801561085057600080fd5b5060125461032290600160a01b900460ff1681565b34801561087157600080fd5b50610379610880366004612d11565b611deb565b34801561089157600080fd5b506104037f77eb6d3bbe7602208cc36937114029465cec3988228851754080f2c59c06cdca81565b60006001600160e01b031982167f80ac58cd00000000000000000000000000000000000000000000000000000000148061091c57506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061095057507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b6060600080546109659061305a565b80601f01602080910402602001604051908101604052809291908181526020018280546109919061305a565b80156109de5780601f106109b3576101008083540402835291602001916109de565b820191906000526020600020905b8154815290600101906020018083116109c157829003601f168201915b5050505050905090565b6007546001600160a01b03163314610a355760405162461bcd60e51b8152602060048201819052602482015260008051602061320183398151915260448201526064015b60405180910390fd5b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600260205260408120546001600160a01b0316610ad05760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a2c565b506000908152600460205260409020546001600160a01b031690565b6000610af7826112c4565b9050806001600160a01b0316836001600160a01b03161415610b815760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610a2c565b336001600160a01b0382161480610b9d5750610b9d8133610816565b610c0f5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610a2c565b610c198383611ebb565b505050565b6008548290829085906001600160a01b0316610c7c5760405162461bcd60e51b815260206004820152601460248201527f636c61696d696e67206e6f7420656e61626c65640000000000000000000000006044820152606401610a2c565b600954604080517f77eb6d3bbe7602208cc36937114029465cec3988228851754080f2c59c06cdca60208201523391810191909152606081018390526000919060800160405160208183030381529060405280519060200120604051602001610cfc92919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090506000610d5885858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508693925050611f299050565b6008549091506001600160a01b03808316911614610db85760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964205369676e61747572650000000000000000000000000000006044820152606401610a2c565b60026006541415610e0b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a2c565b600260065560155460ff16610e625760405162461bcd60e51b815260206004820152601360248201527f436c61696d696e67206e6f7420616374697665000000000000000000000000006044820152606401610a2c565b600c54600189610e7061134f565b610e7a91906130a5565b610e8491906130bd565b10610ed15760405162461bcd60e51b815260206004820152601b60248201527f45786365656473206d617820726573657276656420737570706c7900000000006044820152606401610a2c565b600b54600189610edf611012565b610ee991906130a5565b610ef391906130bd565b10610f355760405162461bcd60e51b815260206004820152601260248201527145786365656473206d617820737570706c7960701b6044820152606401610a2c565b33600090815260146020526040902054610f5857610f533389611f45565b610fc6565b60405162461bcd60e51b815260206004820152602860248201527f596f75206861766520616c726561647920636c61696d656420616c6c20796f7560448201527f7220746f6b656e730000000000000000000000000000000000000000000000006064820152608401610a2c565b60005b8881101561100257610fdf601180546001019055565b610ff033610feb611012565b611f76565b80610ffa816130d4565b915050610fc9565b5050600160065550505050505050565b600061101d60115490565b60105461102a91906130a5565b905090565b6007546001600160a01b031633146110775760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b6012546040517f191655870000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015290911690631916558790602401600060405180830381600087803b1580156110d757600080fd5b505af11580156110eb573d6000803e3d6000fd5b5050505050565b6110fc3382611f90565b61116e5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610a2c565b610c19838383612087565b6007546001600160a01b031633146111c15760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b601280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8116600160a01b9182900460ff1615909102179055565b610c19838383604051806020016040528060008152506118e9565b6007546001600160a01b031633146112605760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b600f55565b6007546001600160a01b031633146112ad5760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b80516112c0906016906020840190612bc5565b5050565b6000818152600260205260408120546001600160a01b0316806109505760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610a2c565b600061102a60115490565b6007546001600160a01b031633146113a25760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b6015805460ff19811660ff90911615179055565b60006001600160a01b0382166114345760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610a2c565b506001600160a01b031660009081526003602052604090205490565b6007546001600160a01b031633146114985760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b6114a26000612254565b565b606060006114b1836113b6565b9050806114de5760408051600180825281830190925290602080830190803683370190505b509392505050565b60008167ffffffffffffffff8111156114f9576114f9612e30565b604051908082528060200260200182016040528015611522578160200160208202803683370190505b509050600061152f611012565b9050600060015b82811161159d57866001600160a01b0316611550826112c4565b6001600160a01b0316141561158b5780848381518110611572576115726130ef565b602090810291909101015281611587816130d4565b9250505b80611595816130d4565b915050611536565b509195945050505050565b50919050565b6007546001600160a01b031633146115f65760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b600a55565b6060600180546109659061305a565b6002600654141561165d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a2c565b6002600655601254600160a01b900460ff166116bb5760405162461bcd60e51b815260206004820152600f60248201527f53616c65206e6f742061637469766500000000000000000000000000000000006044820152606401610a2c565b600d546001826116c9611de0565b6116d391906130a5565b6116dd91906130bd565b1061171f5760405162461bcd60e51b815260206004820152601260248201527145786365656473206d617820737570706c7960701b6044820152606401610a2c565b600f5461172d6001836130bd565b106117a05760405162461bcd60e51b815260206004820152602160248201527f547279696e6720746f206d696e7420746f6f206d616e7920617420612074696d60448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610a2c565b80600a546117ae9190613105565b3410156117fd5760405162461bcd60e51b815260206004820152601460248201527f496e73756666696369656e74207061796d656e740000000000000000000000006044820152606401610a2c565b8061180733611977565b111561181c5761181733826122a6565b611864565b60405162461bcd60e51b815260206004820152601660248201527f4d696e74696e67206c696d6974206578636565646564000000000000000000006044820152606401610a2c565b60005b8181101561189b5761187d601080546001019055565b61188933610feb611012565b80611893816130d4565b915050611867565b506012546040516001600160a01b03909116903480156108fc02916000818181858888f193505050501580156118d5573d6000803e3d6000fd5b50506001600655565b6112c03383836122ce565b6118f33383611f90565b6119655760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610a2c565b6119718484848461239d565b50505050565b6001600160a01b038116600090815260136020526040812054600e5461095091906130bd565b6008546000908390839086906001600160a01b03166119fe5760405162461bcd60e51b815260206004820152601460248201527f636c61696d696e67206e6f7420656e61626c65640000000000000000000000006044820152606401610a2c565b600954604080517f77eb6d3bbe7602208cc36937114029465cec3988228851754080f2c59c06cdca60208201523391810191909152606081018390526000919060800160405160208183030381529060405280519060200120604051602001611a7e92919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090506000611ada85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508693925050611f299050565b6008549091506001600160a01b03808316911614611b3a5760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964205369676e61747572650000000000000000000000000000006044820152606401610a2c565b50600198975050505050505050565b6000818152600260205260409020546060906001600160a01b0316611bd65760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006064820152608401610a2c565b6000611be0611d84565b90506000815111611c005760405180602001604052806000815250611c2b565b80611c0a8461241b565b604051602001611c1b929190613124565b6040516020818303038152906040525b9392505050565b6007546001600160a01b03163314611c7a5760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b600c54600183611c8861134f565b611c9291906130a5565b611c9c91906130bd565b10611ce95760405162461bcd60e51b815260206004820152601b60248201527f45786365656473206d617820726573657276656420737570706c7900000000006044820152606401610a2c565b600b54600183611cf7611012565b611d0191906130a5565b611d0b91906130bd565b10611d4d5760405162461bcd60e51b815260206004820152601260248201527145786365656473206d617820737570706c7960701b6044820152606401610a2c565b60005b82811015610c1957611d66601180546001019055565b611d7282610feb611012565b80611d7c816130d4565b915050611d50565b6060601680546109659061305a565b6007546001600160a01b03163314611ddb5760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b600e55565b600061102a60105490565b6007546001600160a01b03163314611e335760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b6001600160a01b038116611eaf5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a2c565b611eb881612254565b50565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611ef0826112c4565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806000611f38858561254d565b915091506114d6816125bd565b6001600160a01b03821660009081526014602052604081208054839290611f6d9084906130a5565b90915550505050565b6112c0828260405180602001604052806000815250612778565b6000818152600260205260408120546001600160a01b03166120095760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a2c565b6000612014836112c4565b9050806001600160a01b0316846001600160a01b0316148061204f5750836001600160a01b031661204484610a57565b6001600160a01b0316145b8061207f57506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b031661209a826112c4565b6001600160a01b0316146121165760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e00000000000000000000000000000000000000000000006064820152608401610a2c565b6001600160a01b0382166121915760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610a2c565b61219c600082611ebb565b6001600160a01b03831660009081526003602052604081208054600192906121c59084906130bd565b90915550506001600160a01b03821660009081526003602052604081208054600192906121f39084906130a5565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03821660009081526013602052604081208054839290611f6d9084906130a5565b816001600160a01b0316836001600160a01b031614156123305760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a2c565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6123a8848484612087565b6123b4848484846127f6565b6119715760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610a2c565b60608161245b57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612485578061246f816130d4565b915061247e9050600a83613169565b915061245f565b60008167ffffffffffffffff8111156124a0576124a0612e30565b6040519080825280601f01601f1916602001820160405280156124ca576020820181803683370190505b5090505b841561207f576124df6001836130bd565b91506124ec600a8661317d565b6124f79060306130a5565b60f81b81838151811061250c5761250c6130ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612546600a86613169565b94506124ce565b6000808251604114156125845760208301516040840151606085015160001a6125788782858561294e565b945094505050506125b6565b8251604014156125ae57602083015160408401516125a3868383612a3b565b9350935050506125b6565b506000905060025b9250929050565b60008160048111156125d1576125d1613191565b14156125da5750565b60018160048111156125ee576125ee613191565b141561263c5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a2c565b600281600481111561265057612650613191565b141561269e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a2c565b60038160048111156126b2576126b2613191565b141561270b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a2c565b600481600481111561271f5761271f613191565b1415611eb85760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610a2c565b6127828383612a83565b61278f60008484846127f6565b610c195760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610a2c565b60006001600160a01b0384163b1561294357604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061283a9033908990889088906004016131a7565b602060405180830381600087803b15801561285457600080fd5b505af1925050508015612884575060408051601f3d908101601f19168201909252612881918101906131e3565b60015b612929573d8080156128b2576040519150601f19603f3d011682016040523d82523d6000602084013e6128b7565b606091505b5080516129215760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610a2c565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061207f565b506001949350505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156129855750600090506003612a32565b8460ff16601b1415801561299d57508460ff16601c14155b156129ae5750600090506004612a32565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612a02573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612a2b57600060019250925050612a32565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831660ff84901c601b01612a758782888561294e565b935093505050935093915050565b6001600160a01b038216612ad95760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a2c565b6000818152600260205260409020546001600160a01b031615612b3e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a2c565b6001600160a01b0382166000908152600360205260408120805460019290612b679084906130a5565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054612bd19061305a565b90600052602060002090601f016020900481019282612bf35760008555612c39565b82601f10612c0c57805160ff1916838001178555612c39565b82800160010185558215612c39579182015b82811115612c39578251825591602001919060010190612c1e565b50612c45929150612c49565b5090565b5b80821115612c455760008155600101612c4a565b6001600160e01b031981168114611eb857600080fd5b600060208284031215612c8657600080fd5b8135611c2b81612c5e565b60005b83811015612cac578181015183820152602001612c94565b838111156119715750506000910152565b60008151808452612cd5816020860160208601612c91565b601f01601f19169290920160200192915050565b602081526000611c2b6020830184612cbd565b6001600160a01b0381168114611eb857600080fd5b600060208284031215612d2357600080fd5b8135611c2b81612cfc565b600060208284031215612d4057600080fd5b5035919050565b60008060408385031215612d5a57600080fd5b8235612d6581612cfc565b946020939093013593505050565b600080600060408486031215612d8857600080fd5b83359250602084013567ffffffffffffffff80821115612da757600080fd5b818601915086601f830112612dbb57600080fd5b813581811115612dca57600080fd5b876020828501011115612ddc57600080fd5b6020830194508093505050509250925092565b600080600060608486031215612e0457600080fd5b8335612e0f81612cfc565b92506020840135612e1f81612cfc565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115612e6157612e61612e30565b604051601f8501601f19908116603f01168101908282118183101715612e8957612e89612e30565b81604052809350858152868686011115612ea257600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215612ece57600080fd5b813567ffffffffffffffff811115612ee557600080fd5b8201601f81018413612ef657600080fd5b61207f84823560208401612e46565b6020808252825182820181905260009190848201906040850190845b81811015612f3d57835183529284019291840191600101612f21565b50909695505050505050565b60008060408385031215612f5c57600080fd5b8235612f6781612cfc565b915060208301358015158114612f7c57600080fd5b809150509250929050565b60008060008060808587031215612f9d57600080fd5b8435612fa881612cfc565b93506020850135612fb881612cfc565b925060408501359150606085013567ffffffffffffffff811115612fdb57600080fd5b8501601f81018713612fec57600080fd5b612ffb87823560208401612e46565b91505092959194509250565b6000806040838503121561301a57600080fd5b823591506020830135612f7c81612cfc565b6000806040838503121561303f57600080fd5b823561304a81612cfc565b91506020830135612f7c81612cfc565b600181811c9082168061306e57607f821691505b602082108114156115a857634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082198211156130b8576130b861308f565b500190565b6000828210156130cf576130cf61308f565b500390565b60006000198214156130e8576130e861308f565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600081600019048311821515161561311f5761311f61308f565b500290565b60008351613136818460208801612c91565b83519083019061314a818360208801612c91565b01949350505050565b634e487b7160e01b600052601260045260246000fd5b60008261317857613178613153565b500490565b60008261318c5761318c613153565b500690565b634e487b7160e01b600052602160045260246000fd5b60006001600160a01b038087168352808616602084015250836040830152608060608301526131d96080830184612cbd565b9695505050505050565b6000602082840312156131f557600080fd5b8151611c2b81612c5e56fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220711ea2a14a65486e3e39ee169e841aca3d320cd1e59ffc508d332948560752c864736f6c6343000809003360806040526040516200123d3803806200123d83398101604081905262000026916200042e565b8051825114620000985760405162461bcd60e51b815260206004820152603260248201527f5061796d656e7453706c69747465723a2070617965657320616e6420736861726044820152710cae640d8cadccee8d040dad2e6dac2e8c6d60731b60648201526084015b60405180910390fd5b6000825111620000eb5760405162461bcd60e51b815260206004820152601a60248201527f5061796d656e7453706c69747465723a206e6f2070617965657300000000000060448201526064016200008f565b60005b82518110156200015757620001428382815181106200011157620001116200050c565b60200260200101518383815181106200012e576200012e6200050c565b60200260200101516200016060201b60201c565b806200014e8162000538565b915050620000ee565b50505062000571565b6001600160a01b038216620001cd5760405162461bcd60e51b815260206004820152602c60248201527f5061796d656e7453706c69747465723a206163636f756e74206973207468652060448201526b7a65726f206164647265737360a01b60648201526084016200008f565b600081116200021f5760405162461bcd60e51b815260206004820152601d60248201527f5061796d656e7453706c69747465723a2073686172657320617265203000000060448201526064016200008f565b6001600160a01b038216600090815260026020526040902054156200029b5760405162461bcd60e51b815260206004820152602b60248201527f5061796d656e7453706c69747465723a206163636f756e7420616c726561647960448201526a206861732073686172657360a81b60648201526084016200008f565b60048054600181019091557f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b0180546001600160a01b0319166001600160a01b0384169081179091556000908152600260205260408120829055546200030390829062000556565b600055604080516001600160a01b0384168152602081018390527f40c340f65e17194d14ddddb073d3c9f888e3cb52b5aae0c6c7706b4fbc905fac910160405180910390a15050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b03811182821017156200038d576200038d6200034c565b604052919050565b60006001600160401b03821115620003b157620003b16200034c565b5060051b60200190565b600082601f830112620003cd57600080fd5b81516020620003e6620003e08362000395565b62000362565b82815260059290921b840181019181810190868411156200040657600080fd5b8286015b848110156200042357805183529183019183016200040a565b509695505050505050565b600080604083850312156200044257600080fd5b82516001600160401b03808211156200045a57600080fd5b818501915085601f8301126200046f57600080fd5b8151602062000482620003e08362000395565b82815260059290921b84018101918181019089841115620004a257600080fd5b948201945b83861015620004d95785516001600160a01b0381168114620004c95760008081fd5b82529482019490820190620004a7565b91880151919650909350505080821115620004f357600080fd5b506200050285828601620003bb565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006000198214156200054f576200054f62000522565b5060010190565b600082198211156200056c576200056c62000522565b500190565b610cbc80620005816000396000f3fe60806040526004361061009a5760003560e01c80638b83209b11610069578063ce7c2ac21161004e578063ce7c2ac214610202578063d79779b214610238578063e33b7de31461026e57600080fd5b80638b83209b146101945780639852595c146101cc57600080fd5b806319165587146100e85780633a98ef391461010a578063406072a91461012e57806348b750441461017457600080fd5b366100e3577f6ef95f06320e7a25a04a175ca677b7052bdd97131872c2192525a629f51be77033604080516001600160a01b0390921682523460208301520160405180910390a1005b600080fd5b3480156100f457600080fd5b50610108610103366004610ac1565b610283565b005b34801561011657600080fd5b506000545b6040519081526020015b60405180910390f35b34801561013a57600080fd5b5061011b610149366004610ade565b6001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b34801561018057600080fd5b5061010861018f366004610ade565b610439565b3480156101a057600080fd5b506101b46101af366004610b17565b6106bd565b6040516001600160a01b039091168152602001610125565b3480156101d857600080fd5b5061011b6101e7366004610ac1565b6001600160a01b031660009081526003602052604090205490565b34801561020e57600080fd5b5061011b61021d366004610ac1565b6001600160a01b031660009081526002602052604090205490565b34801561024457600080fd5b5061011b610253366004610ac1565b6001600160a01b031660009081526005602052604090205490565b34801561027a57600080fd5b5060015461011b565b6001600160a01b0381166000908152600260205260409020546102fc5760405162461bcd60e51b815260206004820152602660248201527f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060448201526573686172657360d01b60648201526084015b60405180910390fd5b600061030760015490565b6103119047610b46565b9050600061033e8383610339866001600160a01b031660009081526003602052604090205490565b6106ed565b9050806103a15760405162461bcd60e51b815260206004820152602b60248201527f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060448201526a191d59481c185e5b595b9d60aa1b60648201526084016102f3565b6001600160a01b038316600090815260036020526040812080548392906103c9908490610b46565b9250508190555080600160008282546103e29190610b46565b909155506103f290508382610732565b604080516001600160a01b0385168152602081018390527fdf20fd1e76bc69d672e4814fafb2c449bba3a5369d8359adf9e05e6fde87b056910160405180910390a1505050565b6001600160a01b0381166000908152600260205260409020546104ad5760405162461bcd60e51b815260206004820152602660248201527f5061796d656e7453706c69747465723a206163636f756e7420686173206e6f2060448201526573686172657360d01b60648201526084016102f3565b6001600160a01b0382166000908152600560205260408120546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038516906370a082319060240160206040518083038186803b15801561051e57600080fd5b505afa158015610532573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105569190610b5e565b6105609190610b46565b90506000610599838361033987876001600160a01b03918216600090815260066020908152604080832093909416825291909152205490565b9050806105fc5760405162461bcd60e51b815260206004820152602b60248201527f5061796d656e7453706c69747465723a206163636f756e74206973206e6f742060448201526a191d59481c185e5b595b9d60aa1b60648201526084016102f3565b6001600160a01b03808516600090815260066020908152604080832093871683529290529081208054839290610633908490610b46565b90915550506001600160a01b03841660009081526005602052604081208054839290610660908490610b46565b909155506106719050848483610850565b604080516001600160a01b038581168252602082018490528616917f3be5b7a71e84ed12875d241991c70855ac5817d847039e17a9d895c1ceb0f18a910160405180910390a250505050565b6000600482815481106106d2576106d2610b77565b6000918252602090912001546001600160a01b031692915050565b600080546001600160a01b0385168252600260205260408220548391906107149086610b8d565b61071e9190610bac565b6107289190610bce565b90505b9392505050565b804710156107825760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016102f3565b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146107cf576040519150601f19603f3d011682016040523d82523d6000602084013e6107d4565b606091505b505090508061084b5760405162461bcd60e51b815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016102f3565b505050565b604080516001600160a01b03848116602483015260448083018590528351808403909101815260649092018352602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905283518085019094528084527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65649084015261084b9286929160009161090e91851690849061099e565b80519091501561084b578080602001905181019061092c9190610be5565b61084b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016102f3565b6060610728848460008585843b6109f75760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102f3565b600080866001600160a01b03168587604051610a139190610c37565b60006040518083038185875af1925050503d8060008114610a50576040519150601f19603f3d011682016040523d82523d6000602084013e610a55565b606091505b5091509150610a65828286610a70565b979650505050505050565b60608315610a7f57508161072b565b825115610a8f5782518084602001fd5b8160405162461bcd60e51b81526004016102f39190610c53565b6001600160a01b0381168114610abe57600080fd5b50565b600060208284031215610ad357600080fd5b813561072b81610aa9565b60008060408385031215610af157600080fd5b8235610afc81610aa9565b91506020830135610b0c81610aa9565b809150509250929050565b600060208284031215610b2957600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b60008219821115610b5957610b59610b30565b500190565b600060208284031215610b7057600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b6000816000190483118215151615610ba757610ba7610b30565b500290565b600082610bc957634e487b7160e01b600052601260045260246000fd5b500490565b600082821015610be057610be0610b30565b500390565b600060208284031215610bf757600080fd5b8151801515811461072b57600080fd5b60005b83811015610c22578181015183820152602001610c0a565b83811115610c31576000848401525b50505050565b60008251610c49818460208701610c07565b9190910192915050565b6020815260008251806020840152610c72816040850160208701610c07565b601f01601f1916919091016040019291505056fea26469706673582212201a625fb95daf53a8a3417c91b6b961971e5f9717a1285dde6af49c778327936464736f6c634300080900330000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000002c68af0bb1400000000000000000000000000000000000000000000000000000000000000000bb800000000000000000000000000000000000000000000000000000000000002ee000000000000000000000000000000000000000000000000000000000000000b466c6f6f722047656e20330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008464c4f4f52494949000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005368747470733a2f2f697066732e6d616465776974686d61736f6e2e636f6d2f697066732f516d5835707372596757437251776e6e4d3344746d6d7048696d68626f70656f53424c74414e4b364345615969352f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000391fd74d878489981015635959c7c970e13ad057000000000000000000000000d640c898b0902bd02f69de0fe8d0bd560956db760000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005a
Deployed Bytecode
0x6080604052600436106102fd5760003560e01c8063715018a61161018f578063bb660c0a116100e1578063e268e4d31161008a578063eb8d244411610064578063eb8d244414610844578063f2fde38b14610865578063fa4d280c1461088557600080fd5b8063e268e4d3146107c6578063e6a5931e146107e6578063e985e9c5146107fb57600080fd5b8063d52c57e0116100bb578063d52c57e01461077b578063d547cfb71461079b578063dfe0ce18146107b057600080fd5b8063bb660c0a1461071b578063bece913b1461073b578063c87b56dd1461075b57600080fd5b806395d89b4111610143578063b3feb36d1161011d578063b3feb36d146106ae578063b88d4fde146106e5578063b8fc10511461070557600080fd5b806395d89b4114610666578063a0712d681461067b578063a22cb4651461068e57600080fd5b80638d859f3e116101745780638d859f3e146106125780638da5cb5b1461062857806391b7f5ed1461064657600080fd5b8063715018a6146105d05780638462151c146105e557600080fd5b80632a47f7991161025357806355f804b3116101fc578063674d13c8116101d6578063674d13c8146105865780636d60e6c11461059b57806370a08231146105b057600080fd5b806355f804b314610510578063624601b6146105305780636352211e1461056657600080fd5b80633644e5151161022d5780633644e515146104ba57806342842e0e146104d057806350001a92146104f057600080fd5b80632a47f7991461047957806332cb6b0c1461048f57806334918dfd146104a557600080fd5b8063095ea7b3116102b557806318160ddd1161028f57806318160ddd14610424578063191655871461043957806323b872dd1461045957600080fd5b8063095ea7b3146103cd5780630f2cdd6c146103ed57806314d8bbf11461041157600080fd5b806307688939116102e6578063076889391461035957806307cf3a771461037b578063081812fc1461039557600080fd5b806301ffc9a71461030257806306fdde0314610337575b600080fd5b34801561030e57600080fd5b5061032261031d366004612c74565b6108b9565b60405190151581526020015b60405180910390f35b34801561034357600080fd5b5061034c610956565b60405161032e9190612ce9565b34801561036557600080fd5b50610379610374366004612d11565b6109e8565b005b34801561038757600080fd5b506015546103229060ff1681565b3480156103a157600080fd5b506103b56103b0366004612d2e565b610a57565b6040516001600160a01b03909116815260200161032e565b3480156103d957600080fd5b506103796103e8366004612d47565b610aec565b3480156103f957600080fd5b50610403600e5481565b60405190815260200161032e565b61037961041f366004612d73565b610c1e565b34801561043057600080fd5b50610403611012565b34801561044557600080fd5b50610379610454366004612d11565b61102f565b34801561046557600080fd5b50610379610474366004612def565b6110f2565b34801561048557600080fd5b50610403600d5481565b34801561049b57600080fd5b50610403600b5481565b3480156104b157600080fd5b50610379611179565b3480156104c657600080fd5b5061040360095481565b3480156104dc57600080fd5b506103796104eb366004612def565b6111fd565b3480156104fc57600080fd5b5061037961050b366004612d2e565b611218565b34801561051c57600080fd5b5061037961052b366004612ebc565b611265565b34801561053c57600080fd5b5061040361054b366004612d11565b6001600160a01b031660009081526014602052604090205490565b34801561057257600080fd5b506103b5610581366004612d2e565b6112c4565b34801561059257600080fd5b5061040361134f565b3480156105a757600080fd5b5061037961135a565b3480156105bc57600080fd5b506104036105cb366004612d11565b6113b6565b3480156105dc57600080fd5b50610379611450565b3480156105f157600080fd5b50610605610600366004612d11565b6114a4565b60405161032e9190612f05565b34801561061e57600080fd5b50610403600a5481565b34801561063457600080fd5b506007546001600160a01b03166103b5565b34801561065257600080fd5b50610379610661366004612d2e565b6115ae565b34801561067257600080fd5b5061034c6115fb565b610379610689366004612d2e565b61160a565b34801561069a57600080fd5b506103796106a9366004612f49565b6118de565b3480156106ba57600080fd5b506103226106c9366004612d11565b6001600160a01b03166000908152601460205260409020541590565b3480156106f157600080fd5b50610379610700366004612f87565b6118e9565b34801561071157600080fd5b50610403600f5481565b34801561072757600080fd5b50610403610736366004612d11565b611977565b34801561074757600080fd5b50610322610756366004612d73565b61199d565b34801561076757600080fd5b5061034c610776366004612d2e565b611b49565b34801561078757600080fd5b50610379610796366004613007565b611c32565b3480156107a757600080fd5b5061034c611d84565b3480156107bc57600080fd5b50610403600c5481565b3480156107d257600080fd5b506103796107e1366004612d2e565b611d93565b3480156107f257600080fd5b50610403611de0565b34801561080757600080fd5b5061032261081636600461302c565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b34801561085057600080fd5b5060125461032290600160a01b900460ff1681565b34801561087157600080fd5b50610379610880366004612d11565b611deb565b34801561089157600080fd5b506104037f77eb6d3bbe7602208cc36937114029465cec3988228851754080f2c59c06cdca81565b60006001600160e01b031982167f80ac58cd00000000000000000000000000000000000000000000000000000000148061091c57506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061095057507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b6060600080546109659061305a565b80601f01602080910402602001604051908101604052809291908181526020018280546109919061305a565b80156109de5780601f106109b3576101008083540402835291602001916109de565b820191906000526020600020905b8154815290600101906020018083116109c157829003601f168201915b5050505050905090565b6007546001600160a01b03163314610a355760405162461bcd60e51b8152602060048201819052602482015260008051602061320183398151915260448201526064015b60405180910390fd5b600880546001600160a01b0319166001600160a01b0392909216919091179055565b6000818152600260205260408120546001600160a01b0316610ad05760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a2c565b506000908152600460205260409020546001600160a01b031690565b6000610af7826112c4565b9050806001600160a01b0316836001600160a01b03161415610b815760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f72000000000000000000000000000000000000000000000000000000000000006064820152608401610a2c565b336001600160a01b0382161480610b9d5750610b9d8133610816565b610c0f5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c00000000000000006064820152608401610a2c565b610c198383611ebb565b505050565b6008548290829085906001600160a01b0316610c7c5760405162461bcd60e51b815260206004820152601460248201527f636c61696d696e67206e6f7420656e61626c65640000000000000000000000006044820152606401610a2c565b600954604080517f77eb6d3bbe7602208cc36937114029465cec3988228851754080f2c59c06cdca60208201523391810191909152606081018390526000919060800160405160208183030381529060405280519060200120604051602001610cfc92919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090506000610d5885858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508693925050611f299050565b6008549091506001600160a01b03808316911614610db85760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964205369676e61747572650000000000000000000000000000006044820152606401610a2c565b60026006541415610e0b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a2c565b600260065560155460ff16610e625760405162461bcd60e51b815260206004820152601360248201527f436c61696d696e67206e6f7420616374697665000000000000000000000000006044820152606401610a2c565b600c54600189610e7061134f565b610e7a91906130a5565b610e8491906130bd565b10610ed15760405162461bcd60e51b815260206004820152601b60248201527f45786365656473206d617820726573657276656420737570706c7900000000006044820152606401610a2c565b600b54600189610edf611012565b610ee991906130a5565b610ef391906130bd565b10610f355760405162461bcd60e51b815260206004820152601260248201527145786365656473206d617820737570706c7960701b6044820152606401610a2c565b33600090815260146020526040902054610f5857610f533389611f45565b610fc6565b60405162461bcd60e51b815260206004820152602860248201527f596f75206861766520616c726561647920636c61696d656420616c6c20796f7560448201527f7220746f6b656e730000000000000000000000000000000000000000000000006064820152608401610a2c565b60005b8881101561100257610fdf601180546001019055565b610ff033610feb611012565b611f76565b80610ffa816130d4565b915050610fc9565b5050600160065550505050505050565b600061101d60115490565b60105461102a91906130a5565b905090565b6007546001600160a01b031633146110775760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b6012546040517f191655870000000000000000000000000000000000000000000000000000000081526001600160a01b03838116600483015290911690631916558790602401600060405180830381600087803b1580156110d757600080fd5b505af11580156110eb573d6000803e3d6000fd5b5050505050565b6110fc3382611f90565b61116e5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610a2c565b610c19838383612087565b6007546001600160a01b031633146111c15760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b601280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8116600160a01b9182900460ff1615909102179055565b610c19838383604051806020016040528060008152506118e9565b6007546001600160a01b031633146112605760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b600f55565b6007546001600160a01b031633146112ad5760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b80516112c0906016906020840190612bc5565b5050565b6000818152600260205260408120546001600160a01b0316806109505760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e00000000000000000000000000000000000000000000006064820152608401610a2c565b600061102a60115490565b6007546001600160a01b031633146113a25760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b6015805460ff19811660ff90911615179055565b60006001600160a01b0382166114345760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f2061646472657373000000000000000000000000000000000000000000006064820152608401610a2c565b506001600160a01b031660009081526003602052604090205490565b6007546001600160a01b031633146114985760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b6114a26000612254565b565b606060006114b1836113b6565b9050806114de5760408051600180825281830190925290602080830190803683370190505b509392505050565b60008167ffffffffffffffff8111156114f9576114f9612e30565b604051908082528060200260200182016040528015611522578160200160208202803683370190505b509050600061152f611012565b9050600060015b82811161159d57866001600160a01b0316611550826112c4565b6001600160a01b0316141561158b5780848381518110611572576115726130ef565b602090810291909101015281611587816130d4565b9250505b80611595816130d4565b915050611536565b509195945050505050565b50919050565b6007546001600160a01b031633146115f65760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b600a55565b6060600180546109659061305a565b6002600654141561165d5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610a2c565b6002600655601254600160a01b900460ff166116bb5760405162461bcd60e51b815260206004820152600f60248201527f53616c65206e6f742061637469766500000000000000000000000000000000006044820152606401610a2c565b600d546001826116c9611de0565b6116d391906130a5565b6116dd91906130bd565b1061171f5760405162461bcd60e51b815260206004820152601260248201527145786365656473206d617820737570706c7960701b6044820152606401610a2c565b600f5461172d6001836130bd565b106117a05760405162461bcd60e51b815260206004820152602160248201527f547279696e6720746f206d696e7420746f6f206d616e7920617420612074696d60448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610a2c565b80600a546117ae9190613105565b3410156117fd5760405162461bcd60e51b815260206004820152601460248201527f496e73756666696369656e74207061796d656e740000000000000000000000006044820152606401610a2c565b8061180733611977565b111561181c5761181733826122a6565b611864565b60405162461bcd60e51b815260206004820152601660248201527f4d696e74696e67206c696d6974206578636565646564000000000000000000006044820152606401610a2c565b60005b8181101561189b5761187d601080546001019055565b61188933610feb611012565b80611893816130d4565b915050611867565b506012546040516001600160a01b03909116903480156108fc02916000818181858888f193505050501580156118d5573d6000803e3d6000fd5b50506001600655565b6112c03383836122ce565b6118f33383611f90565b6119655760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f7665640000000000000000000000000000006064820152608401610a2c565b6119718484848461239d565b50505050565b6001600160a01b038116600090815260136020526040812054600e5461095091906130bd565b6008546000908390839086906001600160a01b03166119fe5760405162461bcd60e51b815260206004820152601460248201527f636c61696d696e67206e6f7420656e61626c65640000000000000000000000006044820152606401610a2c565b600954604080517f77eb6d3bbe7602208cc36937114029465cec3988228851754080f2c59c06cdca60208201523391810191909152606081018390526000919060800160405160208183030381529060405280519060200120604051602001611a7e92919061190160f01b81526002810192909252602282015260420190565b6040516020818303038152906040528051906020012090506000611ada85858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508693925050611f299050565b6008549091506001600160a01b03808316911614611b3a5760405162461bcd60e51b815260206004820152601160248201527f496e76616c6964205369676e61747572650000000000000000000000000000006044820152606401610a2c565b50600198975050505050505050565b6000818152600260205260409020546060906001600160a01b0316611bd65760405162461bcd60e51b815260206004820152602f60248201527f4552433732314d657461646174613a2055524920717565727920666f72206e6f60448201527f6e6578697374656e7420746f6b656e00000000000000000000000000000000006064820152608401610a2c565b6000611be0611d84565b90506000815111611c005760405180602001604052806000815250611c2b565b80611c0a8461241b565b604051602001611c1b929190613124565b6040516020818303038152906040525b9392505050565b6007546001600160a01b03163314611c7a5760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b600c54600183611c8861134f565b611c9291906130a5565b611c9c91906130bd565b10611ce95760405162461bcd60e51b815260206004820152601b60248201527f45786365656473206d617820726573657276656420737570706c7900000000006044820152606401610a2c565b600b54600183611cf7611012565b611d0191906130a5565b611d0b91906130bd565b10611d4d5760405162461bcd60e51b815260206004820152601260248201527145786365656473206d617820737570706c7960701b6044820152606401610a2c565b60005b82811015610c1957611d66601180546001019055565b611d7282610feb611012565b80611d7c816130d4565b915050611d50565b6060601680546109659061305a565b6007546001600160a01b03163314611ddb5760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b600e55565b600061102a60105490565b6007546001600160a01b03163314611e335760405162461bcd60e51b815260206004820181905260248201526000805160206132018339815191526044820152606401610a2c565b6001600160a01b038116611eaf5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a2c565b611eb881612254565b50565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611ef0826112c4565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806000611f38858561254d565b915091506114d6816125bd565b6001600160a01b03821660009081526014602052604081208054839290611f6d9084906130a5565b90915550505050565b6112c0828260405180602001604052806000815250612778565b6000818152600260205260408120546001600160a01b03166120095760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201526b34b9ba32b73a103a37b5b2b760a11b6064820152608401610a2c565b6000612014836112c4565b9050806001600160a01b0316846001600160a01b0316148061204f5750836001600160a01b031661204484610a57565b6001600160a01b0316145b8061207f57506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b949350505050565b826001600160a01b031661209a826112c4565b6001600160a01b0316146121165760405162461bcd60e51b815260206004820152602960248201527f4552433732313a207472616e73666572206f6620746f6b656e2074686174206960448201527f73206e6f74206f776e00000000000000000000000000000000000000000000006064820152608401610a2c565b6001600160a01b0382166121915760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610a2c565b61219c600082611ebb565b6001600160a01b03831660009081526003602052604081208054600192906121c59084906130bd565b90915550506001600160a01b03821660009081526003602052604081208054600192906121f39084906130a5565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b0386811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b600780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03821660009081526013602052604081208054839290611f6d9084906130a5565b816001600160a01b0316836001600160a01b031614156123305760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a2c565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6123a8848484612087565b6123b4848484846127f6565b6119715760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610a2c565b60608161245b57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115612485578061246f816130d4565b915061247e9050600a83613169565b915061245f565b60008167ffffffffffffffff8111156124a0576124a0612e30565b6040519080825280601f01601f1916602001820160405280156124ca576020820181803683370190505b5090505b841561207f576124df6001836130bd565b91506124ec600a8661317d565b6124f79060306130a5565b60f81b81838151811061250c5761250c6130ef565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350612546600a86613169565b94506124ce565b6000808251604114156125845760208301516040840151606085015160001a6125788782858561294e565b945094505050506125b6565b8251604014156125ae57602083015160408401516125a3868383612a3b565b9350935050506125b6565b506000905060025b9250929050565b60008160048111156125d1576125d1613191565b14156125da5750565b60018160048111156125ee576125ee613191565b141561263c5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610a2c565b600281600481111561265057612650613191565b141561269e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610a2c565b60038160048111156126b2576126b2613191565b141561270b5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610a2c565b600481600481111561271f5761271f613191565b1415611eb85760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610a2c565b6127828383612a83565b61278f60008484846127f6565b610c195760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610a2c565b60006001600160a01b0384163b1561294357604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061283a9033908990889088906004016131a7565b602060405180830381600087803b15801561285457600080fd5b505af1925050508015612884575060408051601f3d908101601f19168201909252612881918101906131e3565b60015b612929573d8080156128b2576040519150601f19603f3d011682016040523d82523d6000602084013e6128b7565b606091505b5080516129215760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b6064820152608401610a2c565b805181602001fd5b6001600160e01b031916630a85bd0160e11b14905061207f565b506001949350505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156129855750600090506003612a32565b8460ff16601b1415801561299d57508460ff16601c14155b156129ae5750600090506004612a32565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612a02573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612a2b57600060019250925050612a32565b9150600090505b94509492505050565b6000807f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831660ff84901c601b01612a758782888561294e565b935093505050935093915050565b6001600160a01b038216612ad95760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a2c565b6000818152600260205260409020546001600160a01b031615612b3e5760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a2c565b6001600160a01b0382166000908152600360205260408120805460019290612b679084906130a5565b909155505060008181526002602052604080822080546001600160a01b0319166001600160a01b03861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b828054612bd19061305a565b90600052602060002090601f016020900481019282612bf35760008555612c39565b82601f10612c0c57805160ff1916838001178555612c39565b82800160010185558215612c39579182015b82811115612c39578251825591602001919060010190612c1e565b50612c45929150612c49565b5090565b5b80821115612c455760008155600101612c4a565b6001600160e01b031981168114611eb857600080fd5b600060208284031215612c8657600080fd5b8135611c2b81612c5e565b60005b83811015612cac578181015183820152602001612c94565b838111156119715750506000910152565b60008151808452612cd5816020860160208601612c91565b601f01601f19169290920160200192915050565b602081526000611c2b6020830184612cbd565b6001600160a01b0381168114611eb857600080fd5b600060208284031215612d2357600080fd5b8135611c2b81612cfc565b600060208284031215612d4057600080fd5b5035919050565b60008060408385031215612d5a57600080fd5b8235612d6581612cfc565b946020939093013593505050565b600080600060408486031215612d8857600080fd5b83359250602084013567ffffffffffffffff80821115612da757600080fd5b818601915086601f830112612dbb57600080fd5b813581811115612dca57600080fd5b876020828501011115612ddc57600080fd5b6020830194508093505050509250925092565b600080600060608486031215612e0457600080fd5b8335612e0f81612cfc565b92506020840135612e1f81612cfc565b929592945050506040919091013590565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff80841115612e6157612e61612e30565b604051601f8501601f19908116603f01168101908282118183101715612e8957612e89612e30565b81604052809350858152868686011115612ea257600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215612ece57600080fd5b813567ffffffffffffffff811115612ee557600080fd5b8201601f81018413612ef657600080fd5b61207f84823560208401612e46565b6020808252825182820181905260009190848201906040850190845b81811015612f3d57835183529284019291840191600101612f21565b50909695505050505050565b60008060408385031215612f5c57600080fd5b8235612f6781612cfc565b915060208301358015158114612f7c57600080fd5b809150509250929050565b60008060008060808587031215612f9d57600080fd5b8435612fa881612cfc565b93506020850135612fb881612cfc565b925060408501359150606085013567ffffffffffffffff811115612fdb57600080fd5b8501601f81018713612fec57600080fd5b612ffb87823560208401612e46565b91505092959194509250565b6000806040838503121561301a57600080fd5b823591506020830135612f7c81612cfc565b6000806040838503121561303f57600080fd5b823561304a81612cfc565b91506020830135612f7c81612cfc565b600181811c9082168061306e57607f821691505b602082108114156115a857634e487b7160e01b600052602260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082198211156130b8576130b861308f565b500190565b6000828210156130cf576130cf61308f565b500390565b60006000198214156130e8576130e861308f565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600081600019048311821515161561311f5761311f61308f565b500290565b60008351613136818460208801612c91565b83519083019061314a818360208801612c91565b01949350505050565b634e487b7160e01b600052601260045260246000fd5b60008261317857613178613153565b500490565b60008261318c5761318c613153565b500690565b634e487b7160e01b600052602160045260246000fd5b60006001600160a01b038087168352808616602084015250836040830152608060608301526131d96080830184612cbd565b9695505050505050565b6000602082840312156131f557600080fd5b8151611c2b81612c5e56fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a2646970667358221220711ea2a14a65486e3e39ee169e841aca3d320cd1e59ffc508d332948560752c864736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000002c68af0bb1400000000000000000000000000000000000000000000000000000000000000000bb800000000000000000000000000000000000000000000000000000000000002ee000000000000000000000000000000000000000000000000000000000000000b466c6f6f722047656e20330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008464c4f4f52494949000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005368747470733a2f2f697066732e6d616465776974686d61736f6e2e636f6d2f697066732f516d5835707372596757437251776e6e4d3344746d6d7048696d68626f70656f53424c74414e4b364345615969352f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000391fd74d878489981015635959c7c970e13ad057000000000000000000000000d640c898b0902bd02f69de0fe8d0bd560956db760000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000005a
-----Decoded View---------------
Arg [0] : tokenName (string): Floor Gen 3
Arg [1] : tokenSymbol (string): FLOORIII
Arg [2] : customBaseURI_ (string): https://ipfs.madewithmason.com/ipfs/QmX5psrYgWCrQwnnM3DtmmpHimhbopeoSBLtANK6CEaYi5/
Arg [3] : payees (address[]): 0x391Fd74D878489981015635959c7C970E13ad057,0xd640C898B0902bD02f69dE0FE8d0bd560956DB76
Arg [4] : shares (uint256[]): 10,90
Arg [5] : _tokenPrice (uint256): 200000000000000000
Arg [6] : _tokensForSale (uint256): 3000
Arg [7] : _tokensReserved (uint256): 750
-----Encoded View---------------
22 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000180
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000200
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000260
Arg [5] : 00000000000000000000000000000000000000000000000002c68af0bb140000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000bb8
Arg [7] : 00000000000000000000000000000000000000000000000000000000000002ee
Arg [8] : 000000000000000000000000000000000000000000000000000000000000000b
Arg [9] : 466c6f6f722047656e2033000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000008
Arg [11] : 464c4f4f52494949000000000000000000000000000000000000000000000000
Arg [12] : 0000000000000000000000000000000000000000000000000000000000000053
Arg [13] : 68747470733a2f2f697066732e6d616465776974686d61736f6e2e636f6d2f69
Arg [14] : 7066732f516d5835707372596757437251776e6e4d3344746d6d7048696d6862
Arg [15] : 6f70656f53424c74414e4b364345615969352f00000000000000000000000000
Arg [16] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [17] : 000000000000000000000000391fd74d878489981015635959c7c970e13ad057
Arg [18] : 000000000000000000000000d640c898b0902bd02f69de0fe8d0bd560956db76
Arg [19] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [20] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [21] : 000000000000000000000000000000000000000000000000000000000000005a
Deployed Bytecode Sourcemap
69642:6034:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;41891:305;;;;;;;;;;-1:-1:-1;41891:305:0;;;;;:::i;:::-;;:::i;:::-;;;611:14:1;;604:22;586:41;;574:2;559:18;41891:305:0;;;;;;;;42836:100;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;66514:122::-;;;;;;;;;;-1:-1:-1;66514:122:0;;;;;:::i;:::-;;:::i;:::-;;73092:35;;;;;;;;;;-1:-1:-1;73092:35:0;;;;;;;;44395:221;;;;;;;;;;-1:-1:-1;44395:221:0;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;2149:55:1;;;2131:74;;2119:2;2104:18;44395:221:0;1985:226:1;43918:411:0;;;;;;;;;;-1:-1:-1;43918:411:0;;;;;:::i;:::-;;:::i;69891:29::-;;;;;;;;;;;;;;;;;;;2682:25:1;;;2670:2;2655:18;69891:29:0;2536:177:1;73735:671:0;;;;;;:::i;:::-;;:::i;71826:130::-;;;;;;;;;;;;;:::i;75567:106::-;;;;;;;;;;-1:-1:-1;75567:106:0;;;;;:::i;:::-;;:::i;45145:339::-;;;;;;;;;;-1:-1:-1;45145:339:0;;;;;:::i;:::-;;:::i;69854:32::-;;;;;;;;;;;;;;;;69785:25;;;;;;;;;;;;;;;;72250:85;;;;;;;;;;;;;:::i;65342:31::-;;;;;;;;;;;;;;;;45555:185;;;;;;;;;;-1:-1:-1;45555:185:0;;;;;:::i;:::-;;:::i;72456:106::-;;;;;;;;;;-1:-1:-1;72456:106:0;;;;;:::i;:::-;;:::i;75315:112::-;;;;;;;;;;-1:-1:-1;75315:112:0;;;;;:::i;:::-;;:::i;73234:108::-;;;;;;;;;;-1:-1:-1;73234:108:0;;;;;:::i;:::-;-1:-1:-1;;;;;73317:19:0;73294:7;73317:19;;;:11;:19;;;;;;;73234:108;42530:239;;;;;;;;;;-1:-1:-1;42530:239:0;;;;;:::i;:::-;;:::i;72070:112::-;;;;;;;;;;;;;:::i;73134:94::-;;;;;;;;;;;;;:::i;42260:208::-;;;;;;;;;;-1:-1:-1;42260:208:0;;;;;:::i;:::-;;:::i;63647:103::-;;;;;;;;;;;;;:::i;74535:614::-;;;;;;;;;;-1:-1:-1;74535:614:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;69760:20::-;;;;;;;;;;;;;;;;62996:87;;;;;;;;;;-1:-1:-1;63069:6:0;;-1:-1:-1;;;;;63069:6:0;62996:87;;72360:90;;;;;;;;;;-1:-1:-1;72360:90:0;;;;;:::i;:::-;;:::i;43005:104::-;;;;;;;;;;;;;:::i;70726:691::-;;;;;;:::i;:::-;;:::i;44688:155::-;;;;;;;;;;-1:-1:-1;44688:155:0;;;;;:::i;:::-;;:::i;73502:115::-;;;;;;;;;;-1:-1:-1;73502:115:0;;;;;:::i;:::-;-1:-1:-1;;;;;73587:19:0;73567:4;73587:19;;;:11;:19;;;;;;:24;;73502:115;45811:328;;;;;;;;;;-1:-1:-1;45811:328:0;;;;;:::i;:::-;;:::i;69925:28::-;;;;;;;;;;;;;;;;72767:129;;;;;;;;;;-1:-1:-1;72767:129:0;;;;;:::i;:::-;;:::i;73348:148::-;;;;;;;;;;-1:-1:-1;73348:148:0;;;;;:::i;:::-;;:::i;43180:334::-;;;;;;;;;;-1:-1:-1;43180:334:0;;;;;:::i;:::-;;:::i;71423:397::-;;;;;;;;;;-1:-1:-1;71423:397:0;;;;;:::i;:::-;;:::i;75216:93::-;;;;;;;;;;;;;:::i;69815:34::-;;;;;;;;;;;;;;;;72568:110;;;;;;;;;;-1:-1:-1;72568:110:0;;;;;:::i;:::-;;:::i;71962:102::-;;;;;;;;;;;;;:::i;44914:164::-;;;;;;;;;;-1:-1:-1;44914:164:0;;;;;:::i;:::-;-1:-1:-1;;;;;45035:25:0;;;45011:4;45035:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;44914:164;72212:31;;;;;;;;;;-1:-1:-1;72212:31:0;;;;-1:-1:-1;;;72212:31:0;;;;;;63905:201;;;;;;;;;;-1:-1:-1;63905:201:0;;;;;:::i;:::-;;:::i;65715:100::-;;;;;;;;;;;;65766:49;65715:100;;41891:305;41993:4;-1:-1:-1;;;;;;42030:40:0;;42045:25;42030:40;;:105;;-1:-1:-1;;;;;;;42087:48:0;;42102:33;42087:48;42030:105;:158;;;-1:-1:-1;16092:25:0;-1:-1:-1;;;;;;16077:40:0;;;42152:36;42010:178;41891:305;-1:-1:-1;;41891:305:0:o;42836:100::-;42890:13;42923:5;42916:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;42836:100;:::o;66514:122::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;;;;;;;;;66597:15:::1;:31:::0;;-1:-1:-1;;;;;;66597:31:0::1;-1:-1:-1::0;;;;;66597:31:0;;;::::1;::::0;;;::::1;::::0;;66514:122::o;44395:221::-;44471:7;47738:16;;;:7;:16;;;;;;-1:-1:-1;;;;;47738:16:0;44491:73;;;;-1:-1:-1;;;44491:73:0;;9143:2:1;44491:73:0;;;9125:21:1;9182:2;9162:18;;;9155:30;9221:34;9201:18;;;9194:62;-1:-1:-1;;;9272:18:1;;;9265:42;9324:19;;44491:73:0;8941:408:1;44491:73:0;-1:-1:-1;44584:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;44584:24:0;;44395:221::o;43918:411::-;43999:13;44015:23;44030:7;44015:14;:23::i;:::-;43999:39;;44063:5;-1:-1:-1;;;;;44057:11:0;:2;-1:-1:-1;;;;;44057:11:0;;;44049:57;;;;-1:-1:-1;;;44049:57:0;;9556:2:1;44049:57:0;;;9538:21:1;9595:2;9575:18;;;9568:30;9634:34;9614:18;;;9607:62;9705:3;9685:18;;;9678:31;9726:19;;44049:57:0;9354:397:1;44049:57:0;40365:10;-1:-1:-1;;;;;44141:21:0;;;;:62;;-1:-1:-1;44166:37:0;44183:5;40365:10;44914:164;:::i;44166:37::-;44119:168;;;;-1:-1:-1;;;44119:168:0;;9958:2:1;44119:168:0;;;9940:21:1;9997:2;9977:18;;;9970:30;10036:34;10016:18;;;10009:62;10107:26;10087:18;;;10080:54;10151:19;;44119:168:0;9756:420:1;44119:168:0;44300:21;44309:2;44313:7;44300:8;:21::i;:::-;43988:341;43918:411;;:::o;73735:671::-;66727:15;;73826:9;;;;73837:5;;-1:-1:-1;;;;;66727:15:0;66719:62;;;;-1:-1:-1;;;66719:62:0;;10383:2:1;66719:62:0;;;10365:21:1;10422:2;10402:18;;;10395:30;10461:22;10441:18;;;10434:50;10501:18;;66719:62:0;10181:344:1;66719:62:0;67110:16;;67155:110;;;65766:49;67155:110;;;10732:25:1;67226:10:0;10773:18:1;;;10766:83;;;;10865:18;;;10858:34;;;67005:14:0;;67110:16;10705:18:1;;67155:110:0;;;;;;;;;;;;67145:121;;;;;;67046:235;;;;;;;;-1:-1:-1;;;11161:79:1;;11265:1;11256:11;;11249:27;;;;11301:2;11292:12;;11285:28;11338:2;11329:12;;10903:444;67046:235:0;;;;;;;;;;;;;67022:270;;;;;;67005:287;;67541:24;67568:25;67583:9;;67568:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67568:6:0;;:25;-1:-1:-1;;67568:14:0;:25;-1:-1:-1;67568:25:0:i;:::-;67632:15;;67541:52;;-1:-1:-1;;;;;;67612:35:0;;;67632:15;;67612:35;67604:65;;;;-1:-1:-1;;;67604:65:0;;11554:2:1;67604:65:0;;;11536:21:1;11593:2;11573:18;;;11566:30;11632:19;11612:18;;;11605:47;11669:18;;67604:65:0;11352:341:1;67604:65:0;23619:1:::1;24217:7;;:19;;24209:63;;;::::0;-1:-1:-1;;;24209:63:0;;11900:2:1;24209:63:0::1;::::0;::::1;11882:21:1::0;11939:2;11919:18;;;11912:30;11978:33;11958:18;;;11951:61;12029:18;;24209:63:0::1;11698:355:1::0;24209:63:0::1;23619:1;24350:7;:18:::0;73873:16:::2;::::0;::::2;;73865:48;;;::::0;-1:-1:-1;;;73865:48:0;;12260:2:1;73865:48:0::2;::::0;::::2;12242:21:1::0;12299:2;12279:18;;;12272:30;12338:21;12318:18;;;12311:49;12377:18;;73865:48:0::2;12058:343:1::0;73865:48:0::2;73964:19;;73960:1;73952:5;73928:21;:19;:21::i;:::-;:29;;;;:::i;:::-;:33;;;;:::i;:::-;:55;73920:95;;;::::0;-1:-1:-1;;;73920:95:0;;13060:2:1;73920:95:0::2;::::0;::::2;13042:21:1::0;13099:2;13079:18;;;13072:30;13138:29;13118:18;;;13111:57;13185:18;;73920:95:0::2;12858:351:1::0;73920:95:0::2;74058:10;;74054:1;74046:5;74030:13;:11;:13::i;:::-;:21;;;;:::i;:::-;:25;;;;:::i;:::-;:38;74022:70;;;::::0;-1:-1:-1;;;74022:70:0;;13416:2:1;74022:70:0::2;::::0;::::2;13398:21:1::0;13455:2;13435:18;;;13428:30;-1:-1:-1;;;13474:18:1;;;13467:48;13532:18;;74022:70:0::2;13214:342:1::0;74022:70:0::2;74124:10;73567:4:::0;73587:19;;;:11;:19;;;;;;74101:161:::2;;74146:35;74163:10;74175:5;74146:16;:35::i;:::-;74101:161;;;74204:50;::::0;-1:-1:-1;;;74204:50:0;;13763:2:1;74204:50:0::2;::::0;::::2;13745:21:1::0;13802:2;13782:18;;;13775:30;13841:34;13821:18;;;13814:62;13912:10;13892:18;;;13885:38;13940:19;;74204:50:0::2;13561:404:1::0;74101:161:0::2;74275:9;74270:131;74294:5;74290:1;:9;74270:131;;;74315:33;:21;1083:19:::0;;1101:1;1083:19;;;994:127;74315:33:::2;74357:36;74367:10;74379:13;:11;:13::i;:::-;74357:9;:36::i;:::-;74301:3:::0;::::2;::::0;::::2;:::i;:::-;;;;74270:131;;;-1:-1:-1::0;;23575:1:0::1;24529:7;:22:::0;-1:-1:-1;;;;;;;73735:671:0:o;71826:130::-;71870:7;71919:31;:21;964:14;;872:114;71919:31;71893:13;964:14;71893:57;;;;:::i;:::-;71886:64;;71826:130;:::o;75567:106::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;75641:9:::1;::::0;:26:::1;::::0;;;;-1:-1:-1;;;;;2149:55:1;;;75641:26:0::1;::::0;::::1;2131:74:1::0;75641:9:0;;::::1;::::0;:17:::1;::::0;2104:18:1;;75641:26:0::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;75567:106:::0;:::o;45145:339::-;45340:41;40365:10;45373:7;45340:18;:41::i;:::-;45332:103;;;;-1:-1:-1;;;45332:103:0;;14559:2:1;45332:103:0;;;14541:21:1;14598:2;14578:18;;;14571:30;14637:34;14617:18;;;14610:62;14708:19;14688:18;;;14681:47;14745:19;;45332:103:0;14357:413:1;45332:103:0;45448:28;45458:4;45464:2;45468:7;45448:9;:28::i;72250:85::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;72317:12:::1;::::0;;72301:28;;::::1;-1:-1:-1::0;;;72317:12:0;;;::::1;;;72316:13;72301:28:::0;;::::1;;::::0;;72250:85::o;45555:185::-;45693:39;45710:4;45716:2;45720:7;45693:39;;;;;;;;;;;;:16;:39::i;72456:106::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;72527:13:::1;:29:::0;72456:106::o;75315:112::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;75391:30;;::::1;::::0;:13:::1;::::0;:30:::1;::::0;::::1;::::0;::::1;:::i;:::-;;75315:112:::0;:::o;42530:239::-;42602:7;42638:16;;;:7;:16;;;;;;-1:-1:-1;;;;;42638:16:0;42673:19;42665:73;;;;-1:-1:-1;;;42665:73:0;;14977:2:1;42665:73:0;;;14959:21:1;15016:2;14996:18;;;14989:30;15055:34;15035:18;;;15028:62;15126:11;15106:18;;;15099:39;15155:19;;42665:73:0;14775:405:1;72070:112:0;72122:7;72145:31;:21;964:14;;872:114;73134:94;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;73206:16:::1;::::0;;-1:-1:-1;;73186:36:0;::::1;73206:16;::::0;;::::1;73205:17;73186:36;::::0;;73134:94::o;42260:208::-;42332:7;-1:-1:-1;;;;;42360:19:0;;42352:74;;;;-1:-1:-1;;;42352:74:0;;15387:2:1;42352:74:0;;;15369:21:1;15426:2;15406:18;;;15399:30;15465:34;15445:18;;;15438:62;15536:12;15516:18;;;15509:40;15566:19;;42352:74:0;15185:406:1;42352:74:0;-1:-1:-1;;;;;;42444:16:0;;;;;:9;:16;;;;;;;42260:208::o;63647:103::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;63712:30:::1;63739:1;63712:18;:30::i;:::-;63647:103::o:0;74535:614::-;74596:28;74633:18;74654:17;74664:6;74654:9;:17::i;:::-;74633:38;-1:-1:-1;74684:15:0;74680:464;;74717:16;;;74731:1;74717:16;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;74717:16:0;-1:-1:-1;74710:23:0;74535:614;-1:-1:-1;;;74535:614:0:o;74680:464::-;74756:23;74796:10;74782:25;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;74782:25:0;;74756:51;;74816:19;74838:13;:11;:13::i;:::-;74816:35;-1:-1:-1;74860:19:0;74933:1;74918:195;74947:11;74936:7;:22;74918:195;;75008:6;-1:-1:-1;;;;;74988:26:0;:16;74996:7;74988;:16::i;:::-;-1:-1:-1;;;;;74988:26:0;;74984:120;;;75053:7;75031:6;75038:11;75031:19;;;;;;;;:::i;:::-;;;;;;;;;;:29;75077:13;;;;:::i;:::-;;;;74984:120;74960:9;;;;:::i;:::-;;;;74918:195;;;-1:-1:-1;75130:6:0;;74535:614;-1:-1:-1;;;;;74535:614:0:o;74680:464::-;74626:523;74535:614;;;:::o;72360:90::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;72425:5:::1;:19:::0;72360:90::o;43005:104::-;43061:13;43094:7;43087:14;;;;;:::i;70726:691::-;23619:1;24217:7;;:19;;24209:63;;;;-1:-1:-1;;;24209:63:0;;11900:2:1;24209:63:0;;;11882:21:1;11939:2;11919:18;;;11912:30;11978:33;11958:18;;;11951:61;12029:18;;24209:63:0;11698:355:1;24209:63:0;23619:1;24350:7;:18;70798:12:::1;::::0;-1:-1:-1;;;70798:12:0;::::1;;;70790:40;;;::::0;-1:-1:-1;;;70790:40:0;;15987:2:1;70790:40:0::1;::::0;::::1;15969:21:1::0;16026:2;16006:18;;;15999:30;16065:17;16045:18;;;16038:45;16100:18;;70790:40:0::1;15785:339:1::0;70790:40:0::1;70879:17;;70875:1;70867:5;70845:19;:17;:19::i;:::-;:27;;;;:::i;:::-;:31;;;;:::i;:::-;:51;70837:82;;;::::0;-1:-1:-1;;;70837:82:0;;13416:2:1;70837:82:0::1;::::0;::::1;13398:21:1::0;13455:2;13435:18;;;13428:30;-1:-1:-1;;;13474:18:1;;;13467:48;13532:18;;70837:82:0::1;13214:342:1::0;70837:82:0::1;70946:13;::::0;70934:9:::1;70942:1;70934:5:::0;:9:::1;:::i;:::-;:25;70926:71;;;::::0;-1:-1:-1;;;70926:71:0;;16331:2:1;70926:71:0::1;::::0;::::1;16313:21:1::0;16370:2;16350:18;;;16343:30;16409:34;16389:18;;;16382:62;16480:3;16460:18;;;16453:31;16501:19;;70926:71:0::1;16129:397:1::0;70926:71:0::1;71041:5;71033;;:13;;;;:::i;:::-;71020:9;:26;;71004:73;;;::::0;-1:-1:-1;;;71004:73:0;;16906:2:1;71004:73:0::1;::::0;::::1;16888:21:1::0;16945:2;16925:18;;;16918:30;16984:22;16964:18;;;16957:50;17024:18;;71004:73:0::1;16704:344:1::0;71004:73:0::1;71121:5;71090:28;71107:10;71090:16;:28::i;:::-;:36;71086:148;;;71137:34;71153:10;71165:5;71137:15;:34::i;:::-;71086:148;;;71194:32;::::0;-1:-1:-1;;;71194:32:0;;17255:2:1;71194:32:0::1;::::0;::::1;17237:21:1::0;17294:2;17274:18;;;17267:30;17333:24;17313:18;;;17306:52;17375:18;;71194:32:0::1;17053:346:1::0;71086:148:0::1;71247:9;71242:123;71266:5;71262:1;:9;71242:123;;;71287:25;:13;1083:19:::0;;1101:1;1083:19;;;994:127;71287:25:::1;71321:36;71331:10;71343:13;:11;:13::i;71321:36::-;71273:3:::0;::::1;::::0;::::1;:::i;:::-;;;;71242:123;;;-1:-1:-1::0;71381:9:0::1;::::0;71373:38:::1;::::0;-1:-1:-1;;;;;71381:9:0;;::::1;::::0;71401::::1;71373:38:::0;::::1;;;::::0;71381:9:::1;71373:38:::0;71381:9;71373:38;71401:9;71381;71373:38;::::1;;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;23575:1:0;24529:7;:22;70726:691::o;44688:155::-;44783:52;40365:10;44816:8;44826;44783:18;:52::i;45811:328::-;45986:41;40365:10;46019:7;45986:18;:41::i;:::-;45978:103;;;;-1:-1:-1;;;45978:103:0;;14559:2:1;45978:103:0;;;14541:21:1;14598:2;14578:18;;;14571:30;14637:34;14617:18;;;14610:62;14708:19;14688:18;;;14681:47;14745:19;;45978:103:0;14357:413:1;45978:103:0;46092:39;46106:4;46112:2;46116:7;46125:5;46092:13;:39::i;:::-;45811:328;;;;:::o;72767:129::-;-1:-1:-1;;;;;72870:20:0;;72830:7;72870:20;;;:12;:20;;;;;;72853:14;;:37;;72870:20;72853:37;:::i;73348:148::-;66727:15;;73466:4;;73439:9;;;;73450:5;;-1:-1:-1;;;;;66727:15:0;66719:62;;;;-1:-1:-1;;;66719:62:0;;10383:2:1;66719:62:0;;;10365:21:1;10422:2;10402:18;;;10395:30;10461:22;10441:18;;;10434:50;10501:18;;66719:62:0;10181:344:1;66719:62:0;67110:16;;67155:110;;;65766:49;67155:110;;;10732:25:1;67226:10:0;10773:18:1;;;10766:83;;;;10865:18;;;10858:34;;;67005:14:0;;67110:16;10705:18:1;;67155:110:0;;;;;;;;;;;;67145:121;;;;;;67046:235;;;;;;;;-1:-1:-1;;;11161:79:1;;11265:1;11256:11;;11249:27;;;;11301:2;11292:12;;11285:28;11338:2;11329:12;;10903:444;67046:235:0;;;;;;;;;;;;;67022:270;;;;;;67005:287;;67541:24;67568:25;67583:9;;67568:25;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;67568:6:0;;:25;-1:-1:-1;;67568:14:0;:25;-1:-1:-1;67568:25:0:i;:::-;67632:15;;67541:52;;-1:-1:-1;;;;;;67612:35:0;;;67632:15;;67612:35;67604:65;;;;-1:-1:-1;;;67604:65:0;;11554:2:1;67604:65:0;;;11536:21:1;11593:2;11573:18;;;11566:30;11632:19;11612:18;;;11605:47;11669:18;;67604:65:0;11352:341:1;67604:65:0;-1:-1:-1;73486:4:0::1;::::0;73348:148;-1:-1:-1;;;;;;;;73348:148:0:o;43180:334::-;47714:4;47738:16;;;:7;:16;;;;;;43253:13;;-1:-1:-1;;;;;47738:16:0;43279:76;;;;-1:-1:-1;;;43279:76:0;;17606:2:1;43279:76:0;;;17588:21:1;17645:2;17625:18;;;17618:30;17684:34;17664:18;;;17657:62;17755:17;17735:18;;;17728:45;17790:19;;43279:76:0;17404:411:1;43279:76:0;43368:21;43392:10;:8;:10::i;:::-;43368:34;;43444:1;43426:7;43420:21;:25;:86;;;;;;;;;;;;;;;;;43472:7;43481:18;:7;:16;:18::i;:::-;43455:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;43420:86;43413:93;43180:334;-1:-1:-1;;;43180:334:0:o;71423:397::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;71548:19:::1;;71544:1;71536:5;71512:21;:19;:21::i;:::-;:29;;;;:::i;:::-;:33;;;;:::i;:::-;:55;71504:95;;;::::0;-1:-1:-1;;;71504:95:0;;13060:2:1;71504:95:0::1;::::0;::::1;13042:21:1::0;13099:2;13079:18;;;13072:30;13138:29;13118:18;;;13111:57;13185:18;;71504:95:0::1;12858:351:1::0;71504:95:0::1;71642:10;;71638:1;71630:5;71614:13;:11;:13::i;:::-;:21;;;;:::i;:::-;:25;;;;:::i;:::-;:38;71606:70;;;::::0;-1:-1:-1;;;71606:70:0;;13416:2:1;71606:70:0::1;::::0;::::1;13398:21:1::0;13455:2;13435:18;;;13428:30;-1:-1:-1;;;13474:18:1;;;13467:48;13532:18;;71606:70:0::1;13214:342:1::0;71606:70:0::1;71690:9;71685:130;71709:5;71705:1;:9;71685:130;;;71730:33;:21;1083:19:::0;;1101:1;1083:19;;;994:127;71730:33:::1;71772:35;71782:9;71793:13;:11;:13::i;71772:35::-;71716:3:::0;::::1;::::0;::::1;:::i;:::-;;;;71685:130;;75216:93:::0;75261:13;75290;75283:20;;;;;:::i;72568:110::-;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;72642:14:::1;:30:::0;72568:110::o;71962:102::-;72012:7;72035:23;:13;964:14;;872:114;63905:201;63069:6;;-1:-1:-1;;;;;63069:6:0;40365:10;63216:23;63208:68;;;;-1:-1:-1;;;63208:68:0;;8782:2:1;63208:68:0;;;8764:21:1;;;8801:18;;;8794:30;-1:-1:-1;;;;;;;;;;;8840:18:1;;;8833:62;8912:18;;63208:68:0;8580:356:1;63208:68:0;-1:-1:-1;;;;;63994:22:0;::::1;63986:73;;;::::0;-1:-1:-1;;;63986:73:0;;18497:2:1;63986:73:0::1;::::0;::::1;18479:21:1::0;18536:2;18516:18;;;18509:30;18575:34;18555:18;;;18548:62;18646:8;18626:18;;;18619:36;18672:19;;63986:73:0::1;18295:402:1::0;63986:73:0::1;64070:28;64089:8;64070:18;:28::i;:::-;63905:201:::0;:::o;51631:174::-;51706:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;51706:29:0;-1:-1:-1;;;;;51706:29:0;;;;;;;;:24;;51760:23;51706:24;51760:14;:23::i;:::-;-1:-1:-1;;;;;51751:46:0;;;;;;;;;;;51631:174;;:::o;7991:231::-;8069:7;8090:17;8109:18;8131:27;8142:4;8148:9;8131:10;:27::i;:::-;8089:69;;;;8169:18;8181:5;8169:11;:18::i;73623:106::-;-1:-1:-1;;;;;73695:19:0;;;;;;:11;:19;;;;;:28;;73718:5;;73695:19;:28;;73718:5;;73695:28;:::i;:::-;;;;-1:-1:-1;;;;73623:106:0:o;48633:110::-;48709:26;48719:2;48723:7;48709:26;;;;;;;;;;;;:9;:26::i;47943:348::-;48036:4;47738:16;;;:7;:16;;;;;;-1:-1:-1;;;;;47738:16:0;48053:73;;;;-1:-1:-1;;;48053:73:0;;18904:2:1;48053:73:0;;;18886:21:1;18943:2;18923:18;;;18916:30;18982:34;18962:18;;;18955:62;-1:-1:-1;;;19033:18:1;;;19026:42;19085:19;;48053:73:0;18702:408:1;48053:73:0;48137:13;48153:23;48168:7;48153:14;:23::i;:::-;48137:39;;48206:5;-1:-1:-1;;;;;48195:16:0;:7;-1:-1:-1;;;;;48195:16:0;;:51;;;;48239:7;-1:-1:-1;;;;;48215:31:0;:20;48227:7;48215:11;:20::i;:::-;-1:-1:-1;;;;;48215:31:0;;48195:51;:87;;;-1:-1:-1;;;;;;45035:25:0;;;45011:4;45035:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;48250:32;48187:96;47943:348;-1:-1:-1;;;;47943:348:0:o;50935:578::-;51094:4;-1:-1:-1;;;;;51067:31:0;:23;51082:7;51067:14;:23::i;:::-;-1:-1:-1;;;;;51067:31:0;;51059:85;;;;-1:-1:-1;;;51059:85:0;;19317:2:1;51059:85:0;;;19299:21:1;19356:2;19336:18;;;19329:30;19395:34;19375:18;;;19368:62;19466:11;19446:18;;;19439:39;19495:19;;51059:85:0;19115:405:1;51059:85:0;-1:-1:-1;;;;;51163:16:0;;51155:65;;;;-1:-1:-1;;;51155:65:0;;19727:2:1;51155:65:0;;;19709:21:1;19766:2;19746:18;;;19739:30;19805:34;19785:18;;;19778:62;19876:6;19856:18;;;19849:34;19900:19;;51155:65:0;19525:400:1;51155:65:0;51337:29;51354:1;51358:7;51337:8;:29::i;:::-;-1:-1:-1;;;;;51379:15:0;;;;;;:9;:15;;;;;:20;;51398:1;;51379:15;:20;;51398:1;;51379:20;:::i;:::-;;;;-1:-1:-1;;;;;;;51410:13:0;;;;;;:9;:13;;;;;:18;;51427:1;;51410:13;:18;;51427:1;;51410:18;:::i;:::-;;;;-1:-1:-1;;51439:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;51439:21:0;-1:-1:-1;;;;;51439:21:0;;;;;;;;;51478:27;;51439:16;;51478:27;;;;;;;50935:578;;;:::o;64266:191::-;64359:6;;;-1:-1:-1;;;;;64376:17:0;;;-1:-1:-1;;;;;;64376:17:0;;;;;;;64409:40;;64359:6;;;64376:17;64359:6;;64409:40;;64340:16;;64409:40;64329:128;64266:191;:::o;72902:106::-;-1:-1:-1;;;;;72973:20:0;;;;;;:12;:20;;;;;:29;;72997:5;;72973:20;:29;;72997:5;;72973:29;:::i;51947:315::-;52102:8;-1:-1:-1;;;;;52093:17:0;:5;-1:-1:-1;;;;;52093:17:0;;;52085:55;;;;-1:-1:-1;;;52085:55:0;;20132:2:1;52085:55:0;;;20114:21:1;20171:2;20151:18;;;20144:30;20210:27;20190:18;;;20183:55;20255:18;;52085:55:0;19930:349:1;52085:55:0;-1:-1:-1;;;;;52151:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;52151:46:0;;;;;;;;;;52213:41;;586::1;;;52213::0;;559:18:1;52213:41:0;;;;;;;51947:315;;;:::o;47021:::-;47178:28;47188:4;47194:2;47198:7;47178:9;:28::i;:::-;47225:48;47248:4;47254:2;47258:7;47267:5;47225:22;:48::i;:::-;47217:111;;;;-1:-1:-1;;;47217:111:0;;20486:2:1;47217:111:0;;;20468:21:1;20525:2;20505:18;;;20498:30;20564:34;20544:18;;;20537:62;-1:-1:-1;;;20615:18:1;;;20608:48;20673:19;;47217:111:0;20284:414:1;1830:723:0;1886:13;2107:10;2103:53;;-1:-1:-1;;2134:10:0;;;;;;;;;;;;;;;;;;1830:723::o;2103:53::-;2181:5;2166:12;2222:78;2229:9;;2222:78;;2255:8;;;;:::i;:::-;;-1:-1:-1;2278:10:0;;-1:-1:-1;2286:2:0;2278:10;;:::i;:::-;;;2222:78;;;2310:19;2342:6;2332:17;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2332:17:0;;2310:39;;2360:154;2367:10;;2360:154;;2394:11;2404:1;2394:11;;:::i;:::-;;-1:-1:-1;2463:10:0;2471:2;2463:5;:10;:::i;:::-;2450:24;;:2;:24;:::i;:::-;2437:39;;2420:6;2427;2420:14;;;;;;;;:::i;:::-;;;;:56;;;;;;;;;;-1:-1:-1;2491:11:0;2500:2;2491:11;;:::i;:::-;;;2360:154;;5881:1308;5962:7;5971:12;6196:9;:16;6216:2;6196:22;6192:990;;;6492:4;6477:20;;6471:27;6542:4;6527:20;;6521:27;6600:4;6585:20;;6579:27;6235:9;6571:36;6643:25;6654:4;6571:36;6471:27;6521;6643:10;:25::i;:::-;6636:32;;;;;;;;;6192:990;6690:9;:16;6710:2;6690:22;6686:496;;;6965:4;6950:20;;6944:27;7016:4;7001:20;;6995:27;7058:23;7069:4;6944:27;6995;7058:10;:23::i;:::-;7051:30;;;;;;;;6686:496;-1:-1:-1;7130:1:0;;-1:-1:-1;7134:35:0;6686:496;5881:1308;;;;;:::o;4152:643::-;4230:20;4221:5;:29;;;;;;;;:::i;:::-;;4217:571;;;4152:643;:::o;4217:571::-;4328:29;4319:5;:38;;;;;;;;:::i;:::-;;4315:473;;;4374:34;;-1:-1:-1;;;4374:34:0;;21525:2:1;4374:34:0;;;21507:21:1;21564:2;21544:18;;;21537:30;21603:26;21583:18;;;21576:54;21647:18;;4374:34:0;21323:348:1;4315:473:0;4439:35;4430:5;:44;;;;;;;;:::i;:::-;;4426:362;;;4491:41;;-1:-1:-1;;;4491:41:0;;21878:2:1;4491:41:0;;;21860:21:1;21917:2;21897:18;;;21890:30;21956:33;21936:18;;;21929:61;22007:18;;4491:41:0;21676:355:1;4426:362:0;4563:30;4554:5;:39;;;;;;;;:::i;:::-;;4550:238;;;4610:44;;-1:-1:-1;;;4610:44:0;;22238:2:1;4610:44:0;;;22220:21:1;22277:2;22257:18;;;22250:30;22316:34;22296:18;;;22289:62;-1:-1:-1;;;22367:18:1;;;22360:32;22409:19;;4610:44:0;22036:398:1;4550:238:0;4685:30;4676:5;:39;;;;;;;;:::i;:::-;;4672:116;;;4732:44;;-1:-1:-1;;;4732:44:0;;22641:2:1;4732:44:0;;;22623:21:1;22680:2;22660:18;;;22653:30;22719:34;22699:18;;;22692:62;-1:-1:-1;;;22770:18:1;;;22763:32;22812:19;;4732:44:0;22439:398:1;48970:321:0;49100:18;49106:2;49110:7;49100:5;:18::i;:::-;49151:54;49182:1;49186:2;49190:7;49199:5;49151:22;:54::i;:::-;49129:154;;;;-1:-1:-1;;;49129:154:0;;20486:2:1;49129:154:0;;;20468:21:1;20525:2;20505:18;;;20498:30;20564:34;20544:18;;;20537:62;-1:-1:-1;;;20615:18:1;;;20608:48;20673:19;;49129:154:0;20284:414:1;52827:799:0;52982:4;-1:-1:-1;;;;;53003:13:0;;25709:20;25757:8;52999:620;;53039:72;;-1:-1:-1;;;53039:72:0;;-1:-1:-1;;;;;53039:36:0;;;;;:72;;40365:10;;53090:4;;53096:7;;53105:5;;53039:72;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;53039:72:0;;;;;;;;-1:-1:-1;;53039:72:0;;;;;;;;;;;;:::i;:::-;;;53035:529;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;53281:13:0;;53277:272;;53324:60;;-1:-1:-1;;;53324:60:0;;20486:2:1;53324:60:0;;;20468:21:1;20525:2;20505:18;;;20498:30;20564:34;20544:18;;;20537:62;-1:-1:-1;;;20615:18:1;;;20608:48;20673:19;;53324:60:0;20284:414:1;53277:272:0;53499:6;53493:13;53484:6;53480:2;53476:15;53469:38;53035:529;-1:-1:-1;;;;;;53162:51:0;-1:-1:-1;;;53162:51:0;;-1:-1:-1;53155:58:0;;52999:620;-1:-1:-1;53603:4:0;52827:799;;;;;;:::o;9490:1632::-;9621:7;;10555:66;10542:79;;10538:163;;;-1:-1:-1;10654:1:0;;-1:-1:-1;10658:30:0;10638:51;;10538:163;10715:1;:7;;10720:2;10715:7;;:18;;;;;10726:1;:7;;10731:2;10726:7;;10715:18;10711:102;;;-1:-1:-1;10766:1:0;;-1:-1:-1;10770:30:0;10750:51;;10711:102;10927:24;;;10910:14;10927:24;;;;;;;;;23840:25:1;;;23913:4;23901:17;;23881:18;;;23874:45;;;;23935:18;;;23928:34;;;23978:18;;;23971:34;;;10927:24:0;;23812:19:1;;10927:24:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;10927:24:0;;-1:-1:-1;;10927:24:0;;;-1:-1:-1;;;;;;;10966:20:0;;10962:103;;11019:1;11023:29;11003:50;;;;;;;10962:103;11085:6;-1:-1:-1;11093:20:0;;-1:-1:-1;9490:1632:0;;;;;;;;:::o;8485:391::-;8599:7;;8708:66;8700:75;;8802:3;8798:12;;;8812:2;8794:21;8843:25;8854:4;8794:21;8863:1;8700:75;8843:10;:25::i;:::-;8836:32;;;;;;8485:391;;;;;;:::o;49627:382::-;-1:-1:-1;;;;;49707:16:0;;49699:61;;;;-1:-1:-1;;;49699:61:0;;24218:2:1;49699:61:0;;;24200:21:1;;;24237:18;;;24230:30;24296:34;24276:18;;;24269:62;24348:18;;49699:61:0;24016:356:1;49699:61:0;47714:4;47738:16;;;:7;:16;;;;;;-1:-1:-1;;;;;47738:16:0;:30;49771:58;;;;-1:-1:-1;;;49771:58:0;;24579:2:1;49771:58:0;;;24561:21:1;24618:2;24598:18;;;24591:30;24657;24637:18;;;24630:58;24705:18;;49771:58:0;24377:352:1;49771:58:0;-1:-1:-1;;;;;49900:13:0;;;;;;:9;:13;;;;;:18;;49917:1;;49900:13;:18;;49917:1;;49900:18;:::i;:::-;;;;-1:-1:-1;;49929:16:0;;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;49929:21:0;-1:-1:-1;;;;;49929:21:0;;;;;;;;49968:33;;49929:16;;;49968:33;;49929:16;;49968:33;49627:382;;:::o;-1:-1:-1:-;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:177:1;-1:-1:-1;;;;;;92:5:1;88:78;81:5;78:89;68:117;;181:1;178;171:12;196:245;254:6;307:2;295:9;286:7;282:23;278:32;275:52;;;323:1;320;313:12;275:52;362:9;349:23;381:30;405:5;381:30;:::i;638:258::-;710:1;720:113;734:6;731:1;728:13;720:113;;;810:11;;;804:18;791:11;;;784:39;756:2;749:10;720:113;;;851:6;848:1;845:13;842:48;;;-1:-1:-1;;886:1:1;868:16;;861:27;638:258::o;901:::-;943:3;981:5;975:12;1008:6;1003:3;996:19;1024:63;1080:6;1073:4;1068:3;1064:14;1057:4;1050:5;1046:16;1024:63;:::i;:::-;1141:2;1120:15;-1:-1:-1;;1116:29:1;1107:39;;;;1148:4;1103:50;;901:258;-1:-1:-1;;901:258:1:o;1164:220::-;1313:2;1302:9;1295:21;1276:4;1333:45;1374:2;1363:9;1359:18;1351:6;1333:45;:::i;1389:154::-;-1:-1:-1;;;;;1468:5:1;1464:54;1457:5;1454:65;1444:93;;1533:1;1530;1523:12;1548:247;1607:6;1660:2;1648:9;1639:7;1635:23;1631:32;1628:52;;;1676:1;1673;1666:12;1628:52;1715:9;1702:23;1734:31;1759:5;1734:31;:::i;1800:180::-;1859:6;1912:2;1900:9;1891:7;1887:23;1883:32;1880:52;;;1928:1;1925;1918:12;1880:52;-1:-1:-1;1951:23:1;;1800:180;-1:-1:-1;1800:180:1:o;2216:315::-;2284:6;2292;2345:2;2333:9;2324:7;2320:23;2316:32;2313:52;;;2361:1;2358;2351:12;2313:52;2400:9;2387:23;2419:31;2444:5;2419:31;:::i;:::-;2469:5;2521:2;2506:18;;;;2493:32;;-1:-1:-1;;;2216:315:1:o;2718:659::-;2797:6;2805;2813;2866:2;2854:9;2845:7;2841:23;2837:32;2834:52;;;2882:1;2879;2872:12;2834:52;2918:9;2905:23;2895:33;;2979:2;2968:9;2964:18;2951:32;3002:18;3043:2;3035:6;3032:14;3029:34;;;3059:1;3056;3049:12;3029:34;3097:6;3086:9;3082:22;3072:32;;3142:7;3135:4;3131:2;3127:13;3123:27;3113:55;;3164:1;3161;3154:12;3113:55;3204:2;3191:16;3230:2;3222:6;3219:14;3216:34;;;3246:1;3243;3236:12;3216:34;3291:7;3286:2;3277:6;3273:2;3269:15;3265:24;3262:37;3259:57;;;3312:1;3309;3302:12;3259:57;3343:2;3339;3335:11;3325:21;;3365:6;3355:16;;;;;2718:659;;;;;:::o;3642:456::-;3719:6;3727;3735;3788:2;3776:9;3767:7;3763:23;3759:32;3756:52;;;3804:1;3801;3794:12;3756:52;3843:9;3830:23;3862:31;3887:5;3862:31;:::i;:::-;3912:5;-1:-1:-1;3969:2:1;3954:18;;3941:32;3982:33;3941:32;3982:33;:::i;:::-;3642:456;;4034:7;;-1:-1:-1;;;4088:2:1;4073:18;;;;4060:32;;3642:456::o;4285:184::-;-1:-1:-1;;;4334:1:1;4327:88;4434:4;4431:1;4424:15;4458:4;4455:1;4448:15;4474:632;4539:5;4569:18;4610:2;4602:6;4599:14;4596:40;;;4616:18;;:::i;:::-;4691:2;4685:9;4659:2;4745:15;;-1:-1:-1;;4741:24:1;;;4767:2;4737:33;4733:42;4721:55;;;4791:18;;;4811:22;;;4788:46;4785:72;;;4837:18;;:::i;:::-;4877:10;4873:2;4866:22;4906:6;4897:15;;4936:6;4928;4921:22;4976:3;4967:6;4962:3;4958:16;4955:25;4952:45;;;4993:1;4990;4983:12;4952:45;5043:6;5038:3;5031:4;5023:6;5019:17;5006:44;5098:1;5091:4;5082:6;5074;5070:19;5066:30;5059:41;;;;4474:632;;;;;:::o;5111:451::-;5180:6;5233:2;5221:9;5212:7;5208:23;5204:32;5201:52;;;5249:1;5246;5239:12;5201:52;5289:9;5276:23;5322:18;5314:6;5311:30;5308:50;;;5354:1;5351;5344:12;5308:50;5377:22;;5430:4;5422:13;;5418:27;-1:-1:-1;5408:55:1;;5459:1;5456;5449:12;5408:55;5482:74;5548:7;5543:2;5530:16;5525:2;5521;5517:11;5482:74;:::i;5567:632::-;5738:2;5790:21;;;5860:13;;5763:18;;;5882:22;;;5709:4;;5738:2;5961:15;;;;5935:2;5920:18;;;5709:4;6004:169;6018:6;6015:1;6012:13;6004:169;;;6079:13;;6067:26;;6148:15;;;;6113:12;;;;6040:1;6033:9;6004:169;;;-1:-1:-1;6190:3:1;;5567:632;-1:-1:-1;;;;;;5567:632:1:o;6204:416::-;6269:6;6277;6330:2;6318:9;6309:7;6305:23;6301:32;6298:52;;;6346:1;6343;6336:12;6298:52;6385:9;6372:23;6404:31;6429:5;6404:31;:::i;:::-;6454:5;-1:-1:-1;6511:2:1;6496:18;;6483:32;6553:15;;6546:23;6534:36;;6524:64;;6584:1;6581;6574:12;6524:64;6607:7;6597:17;;;6204:416;;;;;:::o;6625:795::-;6720:6;6728;6736;6744;6797:3;6785:9;6776:7;6772:23;6768:33;6765:53;;;6814:1;6811;6804:12;6765:53;6853:9;6840:23;6872:31;6897:5;6872:31;:::i;:::-;6922:5;-1:-1:-1;6979:2:1;6964:18;;6951:32;6992:33;6951:32;6992:33;:::i;:::-;7044:7;-1:-1:-1;7098:2:1;7083:18;;7070:32;;-1:-1:-1;7153:2:1;7138:18;;7125:32;7180:18;7169:30;;7166:50;;;7212:1;7209;7202:12;7166:50;7235:22;;7288:4;7280:13;;7276:27;-1:-1:-1;7266:55:1;;7317:1;7314;7307:12;7266:55;7340:74;7406:7;7401:2;7388:16;7383:2;7379;7375:11;7340:74;:::i;:::-;7330:84;;;6625:795;;;;;;;:::o;7425:315::-;7493:6;7501;7554:2;7542:9;7533:7;7529:23;7525:32;7522:52;;;7570:1;7567;7560:12;7522:52;7606:9;7593:23;7583:33;;7666:2;7655:9;7651:18;7638:32;7679:31;7704:5;7679:31;:::i;7745:388::-;7813:6;7821;7874:2;7862:9;7853:7;7849:23;7845:32;7842:52;;;7890:1;7887;7880:12;7842:52;7929:9;7916:23;7948:31;7973:5;7948:31;:::i;:::-;7998:5;-1:-1:-1;8055:2:1;8040:18;;8027:32;8068:33;8027:32;8068:33;:::i;8138:437::-;8217:1;8213:12;;;;8260;;;8281:61;;8335:4;8327:6;8323:17;8313:27;;8281:61;8388:2;8380:6;8377:14;8357:18;8354:38;8351:218;;;-1:-1:-1;;;8422:1:1;8415:88;8526:4;8523:1;8516:15;8554:4;8551:1;8544:15;12406:184;-1:-1:-1;;;12455:1:1;12448:88;12555:4;12552:1;12545:15;12579:4;12576:1;12569:15;12595:128;12635:3;12666:1;12662:6;12659:1;12656:13;12653:39;;;12672:18;;:::i;:::-;-1:-1:-1;12708:9:1;;12595:128::o;12728:125::-;12768:4;12796:1;12793;12790:8;12787:34;;;12801:18;;:::i;:::-;-1:-1:-1;12838:9:1;;12728:125::o;13970:135::-;14009:3;-1:-1:-1;;14030:17:1;;14027:43;;;14050:18;;:::i;:::-;-1:-1:-1;14097:1:1;14086:13;;13970:135::o;15596:184::-;-1:-1:-1;;;15645:1:1;15638:88;15745:4;15742:1;15735:15;15769:4;15766:1;15759:15;16531:168;16571:7;16637:1;16633;16629:6;16625:14;16622:1;16619:21;16614:1;16607:9;16600:17;16596:45;16593:71;;;16644:18;;:::i;:::-;-1:-1:-1;16684:9:1;;16531:168::o;17820:470::-;17999:3;18037:6;18031:13;18053:53;18099:6;18094:3;18087:4;18079:6;18075:17;18053:53;:::i;:::-;18169:13;;18128:16;;;;18191:57;18169:13;18128:16;18225:4;18213:17;;18191:57;:::i;:::-;18264:20;;17820:470;-1:-1:-1;;;;17820:470:1:o;20703:184::-;-1:-1:-1;;;20752:1:1;20745:88;20852:4;20849:1;20842:15;20876:4;20873:1;20866:15;20892:120;20932:1;20958;20948:35;;20963:18;;:::i;:::-;-1:-1:-1;20997:9:1;;20892:120::o;21017:112::-;21049:1;21075;21065:35;;21080:18;;:::i;:::-;-1:-1:-1;21114:9:1;;21017:112::o;21134:184::-;-1:-1:-1;;;21183:1:1;21176:88;21283:4;21280:1;21273:15;21307:4;21304:1;21297:15;22842:512;23036:4;-1:-1:-1;;;;;23146:2:1;23138:6;23134:15;23123:9;23116:34;23198:2;23190:6;23186:15;23181:2;23170:9;23166:18;23159:43;;23238:6;23233:2;23222:9;23218:18;23211:34;23281:3;23276:2;23265:9;23261:18;23254:31;23302:46;23343:3;23332:9;23328:19;23320:6;23302:46;:::i;:::-;23294:54;22842:512;-1:-1:-1;;;;;;22842:512:1:o;23359:249::-;23428:6;23481:2;23469:9;23460:7;23456:23;23452:32;23449:52;;;23497:1;23494;23487:12;23449:52;23529:9;23523:16;23548:30;23572:5;23548:30;:::i
Swarm Source
ipfs://1a625fb95daf53a8a3417c91b6b961971e5f9717a1285dde6af49c7783279364
Loading...
Loading
Loading...
Loading
[ 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.