More Info
Private Name Tags
ContractCreator
TokenTracker
Latest 25 from a total of 15,062 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Safe Transfer Fr... | 70227171 | 10 days ago | IN | 0 POL | 0.00103075 | ||||
Claim Prize | 70144289 | 12 days ago | IN | 0 POL | 0.00230987 | ||||
Claim Prize | 69762525 | 21 days ago | IN | 0 POL | 0.00356522 | ||||
Claim Prize | 69762499 | 21 days ago | IN | 0 POL | 0.00367501 | ||||
Set Approval For... | 69646881 | 24 days ago | IN | 0 POL | 0.00231335 | ||||
Safe Transfer Fr... | 69358775 | 31 days ago | IN | 0 POL | 0.0009975 | ||||
Set Approval For... | 69280761 | 33 days ago | IN | 0 POL | 0.00145476 | ||||
Claim Prize | 68702319 | 48 days ago | IN | 0 POL | 0.00223536 | ||||
Claim Prize | 68701966 | 48 days ago | IN | 0 POL | 0.00223536 | ||||
Transfer From | 68635937 | 49 days ago | IN | 0 POL | 0.00700328 | ||||
Claim Prize | 68488920 | 53 days ago | IN | 0 POL | 0.02035267 | ||||
Safe Transfer Fr... | 68306320 | 57 days ago | IN | 0 POL | 0.00112533 | ||||
Claim Prize | 68173544 | 61 days ago | IN | 0 POL | 0.00230987 | ||||
Claim Prize | 67746655 | 72 days ago | IN | 0 POL | 0.00689122 | ||||
Claim Prize | 67746650 | 72 days ago | IN | 0 POL | 0.00679408 | ||||
Claim Prize | 67735315 | 72 days ago | IN | 0 POL | 0.00223638 | ||||
Claim Prize | 67716594 | 72 days ago | IN | 0 POL | 0.00230994 | ||||
Change Base Cost | 67630254 | 75 days ago | IN | 0 POL | 0.00105151 | ||||
Buy Scratch Tick... | 67603442 | 75 days ago | IN | 0 POL | 0.01354496 | ||||
Buy Scratch Tick... | 67602984 | 75 days ago | IN | 0 POL | 0.00504328 | ||||
Safe Transfer Fr... | 67579335 | 76 days ago | IN | 0 POL | 0.00281807 | ||||
Buy Scratch Tick... | 67567493 | 76 days ago | IN | 0 POL | 0.00520732 | ||||
Buy Scratch Tick... | 67559956 | 76 days ago | IN | 0 POL | 0.00500459 | ||||
Claim Prize | 67554462 | 77 days ago | IN | 0 POL | 0.00258659 | ||||
Buy Scratch Tick... | 67554425 | 77 days ago | IN | 0 POL | 0.00576787 |
Loading...
Loading
Contract Name:
ScratchVRF
Compiler Version
v0.8.21+commit.d9974bed
Contract Source Code (Solidity)
/** *Submitted for verification at polygonscan.com on 2023-11-29 */ // SPDX-License-Identifier: -- BCOM -- // File: contracts/helpers/PrizeTiers.sol pragma solidity =0.8.21; contract PrizeTiers { PrizeTier[] public prizeTiers; struct PrizeTier { uint256 drawEdgeA; uint256 drawEdgeB; uint256 winAmount; } uint256 constant public PRECISION_FACTOR = 1E18; /** * RNG between 1 and 1000 values * RNG = 1 wins Jackpot (1,000,000) * RNG between A and B pays X tokens */ constructor() { prizeTiers.push( PrizeTier({ drawEdgeA: 800, drawEdgeB: 1000, winAmount: toWei(1_00) }) ); prizeTiers.push( PrizeTier({ drawEdgeA: 280, drawEdgeB: 799, winAmount: toWei(5_00) }) ); prizeTiers.push( PrizeTier({ drawEdgeA: 80, drawEdgeB: 279, winAmount: toWei(1_000) }) ); prizeTiers.push( PrizeTier({ drawEdgeA: 30, drawEdgeB: 79, winAmount: toWei(5_000) }) ); prizeTiers.push( PrizeTier({ drawEdgeA: 10, drawEdgeB: 29, winAmount: toWei(10_000) }) ); prizeTiers.push( PrizeTier({ drawEdgeA: 4, drawEdgeB: 9, winAmount: toWei(50_000) }) ); prizeTiers.push( PrizeTier({ drawEdgeA: 2, drawEdgeB: 3, winAmount: toWei(100_000) }) ); prizeTiers.push( PrizeTier({ drawEdgeA: 1, drawEdgeB: 1, winAmount: toWei(1_000_000) }) ); } function toWei( uint256 _amount ) public pure returns (uint256) { return _amount * PRECISION_FACTOR; } } // File: @openzeppelin/contracts/utils/math/Math.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv( uint256 x, uint256 y, uint256 denominator, Rounding rounding ) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10**64) { value /= 10**64; result += 64; } if (value >= 10**32) { value /= 10**32; result += 32; } if (value >= 10**16) { value /= 10**16; result += 16; } if (value >= 10**8) { value /= 10**8; result += 8; } if (value >= 10**4) { value /= 10**4; result += 4; } if (value >= 10**2) { value /= 10**2; result += 2; } if (value >= 10**1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0); } } } // File: @openzeppelin/contracts/utils/Strings.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol) pragma solidity ^0.8.0; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } } // File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); } // File: @openzeppelin/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 (last updated v4.8.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); } // File: @openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC721/extensions/IERC721Enumerable.sol) pragma solidity ^0.8.0; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://eips.ethereum.org/EIPS/eip-721 */ interface IERC721Enumerable is IERC721 { /** * @dev Returns the total amount of tokens stored by the contract. */ function totalSupply() external view returns (uint256); /** * @dev Returns a token ID owned by `owner` at a given `index` of its token list. * Use along with {balanceOf} to enumerate all of ``owner``'s tokens. */ function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256); /** * @dev Returns a token ID at a given `index` of all the tokens stored by the contract. * Use along with {totalSupply} to enumerate all tokens. */ function tokenByIndex(uint256 index) external view returns (uint256); } // File: @openzeppelin/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/utils/Address.sol // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } // File: @openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); } // File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol // OpenZeppelin Contracts (last updated v4.8.0) (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)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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: contracts/helpers/TokenHelper.sol pragma solidity =0.8.21; interface ILinkToken is IERC20 { function transferAndCall( address _to, uint256 _value, bytes calldata _data ) external returns (bool success); } contract TokenHelper { using SafeERC20 for IERC20; /** * @notice Allows to transfer tokens * from this contract to a receiver. */ function _giveTokens( IERC20 _token, address _receiver, uint256 _amount ) internal { _token.safeTransfer( _receiver, _amount ); } /** * @notice Allows to transfer tokens * from the caller to this contract. */ function _takeTokens( IERC20 _token, uint256 _amount ) internal { _token.safeTransferFrom( msg.sender, address(this), _amount ); } } // 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 (last updated v4.8.0) (token/ERC721/ERC721.sol) pragma solidity ^0.8.0; /** * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including * the Metadata extension, but not including the Enumerable extension, which is available separately as * {ERC721Enumerable}. */ contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { using Address for address; using Strings for uint256; // Token name string private _name; // Token symbol string private _symbol; // Mapping from token ID to owner address mapping(uint256 => address) private _owners; // Mapping owner address to token count mapping(address => uint256) private _balances; // Mapping from token ID to approved address mapping(uint256 => address) private _tokenApprovals; // Mapping from owner to operator approvals mapping(address => mapping(address => bool)) private _operatorApprovals; /** * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC721Metadata).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721-balanceOf}. */ function balanceOf(address owner) public view virtual override returns (uint256) { require(owner != address(0), "ERC721: address zero is not a valid owner"); return _balances[owner]; } /** * @dev See {IERC721-ownerOf}. */ function ownerOf(uint256 tokenId) public view virtual override returns (address) { address owner = _ownerOf(tokenId); require(owner != address(0), "ERC721: invalid token ID"); return owner; } /** * @dev See {IERC721Metadata-name}. */ function name() public view virtual override returns (string memory) { return _name; } /** * @dev See {IERC721Metadata-symbol}. */ function symbol() public view virtual override returns (string memory) { return _symbol; } /** * @dev See {IERC721Metadata-tokenURI}. */ function tokenURI(uint256 tokenId) public view virtual override returns (string memory) { _requireMinted(tokenId); string memory baseURI = _baseURI(); return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : ""; } /** * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overridden in child contracts. */ function _baseURI() internal view virtual returns (string memory) { return ""; } /** * @dev See {IERC721-approve}. */ function approve(address to, uint256 tokenId) public virtual override { address owner = ERC721.ownerOf(tokenId); require(to != owner, "ERC721: approval to current owner"); require( _msgSender() == owner || isApprovedForAll(owner, _msgSender()), "ERC721: approve caller is not token owner or approved for all" ); _approve(to, tokenId); } /** * @dev See {IERC721-getApproved}. */ function getApproved(uint256 tokenId) public view virtual override returns (address) { _requireMinted(tokenId); return _tokenApprovals[tokenId]; } /** * @dev See {IERC721-setApprovalForAll}. */ function setApprovalForAll(address operator, bool approved) public virtual override { _setApprovalForAll(_msgSender(), operator, approved); } /** * @dev See {IERC721-isApprovedForAll}. */ function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev See {IERC721-transferFrom}. */ function transferFrom( address from, address to, uint256 tokenId ) public virtual override { //solhint-disable-next-line max-line-length require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _transfer(from, to, tokenId); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId ) public virtual override { safeTransferFrom(from, to, tokenId, ""); } /** * @dev See {IERC721-safeTransferFrom}. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes memory data ) public virtual override { require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved"); _safeTransfer(from, to, tokenId, data); } /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * `data` is additional data, it has no specified format and it is sent in call to `to`. * * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. * implement alternative mechanisms to perform token transfer, such as signature-based. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeTransfer( address from, address to, uint256 tokenId, bytes memory data ) internal virtual { _transfer(from, to, tokenId); require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer"); } /** * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist */ function _ownerOf(uint256 tokenId) internal view virtual returns (address) { return _owners[tokenId]; } /** * @dev Returns whether `tokenId` exists. * * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. * * Tokens start existing when they are minted (`_mint`), * and stop existing when they are burned (`_burn`). */ function _exists(uint256 tokenId) internal view virtual returns (bool) { return _ownerOf(tokenId) != address(0); } /** * @dev Returns whether `spender` is allowed to manage `tokenId`. * * Requirements: * * - `tokenId` must exist. */ function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) { address owner = ERC721.ownerOf(tokenId); return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender); } /** * @dev Safely mints `tokenId` and transfers it to `to`. * * Requirements: * * - `tokenId` must not exist. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function _safeMint(address to, uint256 tokenId) internal virtual { _safeMint(to, tokenId, ""); } /** * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. */ function _safeMint( address to, uint256 tokenId, bytes memory data ) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); } /** * @dev Mints `tokenId` and transfers it to `to`. * * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible * * Requirements: * * - `tokenId` must not exist. * - `to` cannot be the zero address. * * Emits a {Transfer} event. */ function _mint(address to, uint256 tokenId) internal virtual { require(to != address(0), "ERC721: mint to the zero address"); require(!_exists(tokenId), "ERC721: token already minted"); _beforeTokenTransfer(address(0), to, tokenId, 1); // Check that tokenId was not minted by `_beforeTokenTransfer` hook require(!_exists(tokenId), "ERC721: token already minted"); unchecked { // Will not overflow unless all 2**256 token ids are minted to the same owner. // Given that tokens are minted one by one, it is impossible in practice that // this ever happens. Might change if we allow batch minting. // The ERC fails to describe this case. _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(address(0), to, tokenId); _afterTokenTransfer(address(0), to, tokenId, 1); } /** * @dev Destroys `tokenId`. * The approval is cleared when the token is burned. * This is an internal function that does not check if the sender is authorized to operate on the token. * * Requirements: * * - `tokenId` must exist. * * Emits a {Transfer} event. */ function _burn(uint256 tokenId) internal virtual { address owner = ERC721.ownerOf(tokenId); _beforeTokenTransfer(owner, address(0), tokenId, 1); // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook owner = ERC721.ownerOf(tokenId); // Clear approvals delete _tokenApprovals[tokenId]; unchecked { // Cannot overflow, as that would require more tokens to be burned/transferred // out than the owner initially received through minting and transferring in. _balances[owner] -= 1; } delete _owners[tokenId]; emit Transfer(owner, address(0), tokenId); _afterTokenTransfer(owner, address(0), tokenId, 1); } /** * @dev Transfers `tokenId` from `from` to `to`. * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. * * Requirements: * * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * * Emits a {Transfer} event. */ function _transfer( address from, address to, uint256 tokenId ) internal virtual { require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); require(to != address(0), "ERC721: transfer to the zero address"); _beforeTokenTransfer(from, to, tokenId, 1); // Check that tokenId was not transferred by `_beforeTokenTransfer` hook require(ERC721.ownerOf(tokenId) == from, "ERC721: transfer from incorrect owner"); // Clear approvals from the previous owner delete _tokenApprovals[tokenId]; unchecked { // `_balances[from]` cannot overflow for the same reason as described in `_burn`: // `from`'s balance is the number of token held, which is at least one before the current // transfer. // `_balances[to]` could overflow in the conditions described in `_mint`. That would require // all 2**256 token ids to be minted, which in practice is impossible. _balances[from] -= 1; _balances[to] += 1; } _owners[tokenId] = to; emit Transfer(from, to, tokenId); _afterTokenTransfer(from, to, tokenId, 1); } /** * @dev Approve `to` to operate on `tokenId` * * Emits an {Approval} event. */ function _approve(address to, uint256 tokenId) internal virtual { _tokenApprovals[tokenId] = to; emit Approval(ERC721.ownerOf(tokenId), to, tokenId); } /** * @dev Approve `operator` to operate on all of `owner` tokens * * Emits an {ApprovalForAll} event. */ function _setApprovalForAll( address owner, address operator, bool approved ) internal virtual { require(owner != operator, "ERC721: approve to caller"); _operatorApprovals[owner][operator] = approved; emit ApprovalForAll(owner, operator, approved); } /** * @dev Reverts if the `tokenId` has not been minted yet. */ function _requireMinted(uint256 tokenId) internal view virtual { require(_exists(tokenId), "ERC721: invalid token ID"); } /** * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. * The call is not executed if the target address is not a contract. * * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param data bytes optional data to send along with the call * @return bool whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes memory data ) private returns (bool) { if (to.isContract()) { try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) { return retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { if (reason.length == 0) { revert("ERC721: transfer to non ERC721Receiver implementer"); } else { /// @solidity memory-safe-assembly assembly { revert(add(32, reason), mload(reason)) } } } } else { return true; } } /** * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. * - When `from` is zero, the tokens will be minted for `to`. * - When `to` is zero, ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer( address from, address to, uint256, /* firstTokenId */ uint256 batchSize ) internal virtual { if (batchSize > 1) { if (from != address(0)) { _balances[from] -= batchSize; } if (to != address(0)) { _balances[to] += batchSize; } } } /** * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. * * Calling conditions: * * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. * - When `from` is zero, the tokens were minted for `to`. * - When `to` is zero, ``from``'s tokens were burned. * - `from` and `to` are never both zero. * - `batchSize` is non-zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _afterTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual {} } // File: @openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/extensions/ERC721Enumerable.sol) pragma solidity ^0.8.0; /** * @dev This implements an optional extension of {ERC721} defined in the EIP that adds * enumerability of all the token ids in the contract as well as all token ids owned by each * account. */ abstract contract ERC721Enumerable is ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => mapping(uint256 => uint256)) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { return interfaceId == type(IERC721Enumerable).interfaceId || super.supportsInterface(interfaceId); } /** * @dev See {IERC721Enumerable-tokenOfOwnerByIndex}. */ function tokenOfOwnerByIndex(address owner, uint256 index) public view virtual override returns (uint256) { require(index < ERC721.balanceOf(owner), "ERC721Enumerable: owner index out of bounds"); return _ownedTokens[owner][index]; } /** * @dev See {IERC721Enumerable-totalSupply}. */ function totalSupply() public view virtual override returns (uint256) { return _allTokens.length; } /** * @dev See {IERC721Enumerable-tokenByIndex}. */ function tokenByIndex(uint256 index) public view virtual override returns (uint256) { require(index < ERC721Enumerable.totalSupply(), "ERC721Enumerable: global index out of bounds"); return _allTokens[index]; } /** * @dev See {ERC721-_beforeTokenTransfer}. */ function _beforeTokenTransfer( address from, address to, uint256 firstTokenId, uint256 batchSize ) internal virtual override { super._beforeTokenTransfer(from, to, firstTokenId, batchSize); if (batchSize > 1) { // Will only trigger during construction. Batch transferring (minting) is not available afterwards. revert("ERC721Enumerable: consecutive transfers not supported"); } uint256 tokenId = firstTokenId; if (from == address(0)) { _addTokenToAllTokensEnumeration(tokenId); } else if (from != to) { _removeTokenFromOwnerEnumeration(from, tokenId); } if (to == address(0)) { _removeTokenFromAllTokensEnumeration(tokenId); } else if (to != from) { _addTokenToOwnerEnumeration(to, tokenId); } } /** * @dev Private function to add a token to this extension's ownership-tracking data structures. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenToOwnerEnumeration(address to, uint256 tokenId) private { uint256 length = ERC721.balanceOf(to); _ownedTokens[to][length] = tokenId; _ownedTokensIndex[tokenId] = length; } /** * @dev Private function to add a token to this extension's token tracking data structures. * @param tokenId uint256 ID of the token to be added to the tokens list */ function _addTokenToAllTokensEnumeration(uint256 tokenId) private { _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Private function to remove a token from this extension's ownership-tracking data structures. Note that * while the token is not assigned a new owner, the `_ownedTokensIndex` mapping is _not_ updated: this allows for * gas optimizations e.g. when performing a transfer operation (avoiding double writes). * This has O(1) time complexity, but alters the order of the _ownedTokens array. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFromOwnerEnumeration(address from, uint256 tokenId) private { // To prevent a gap in from's tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = ERC721.balanceOf(from) - 1; uint256 tokenIndex = _ownedTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary if (tokenIndex != lastTokenIndex) { uint256 lastTokenId = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _ownedTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index } // This also deletes the contents at the last position of the array delete _ownedTokensIndex[tokenId]; delete _ownedTokens[from][lastTokenIndex]; } /** * @dev Private function to remove a token from this extension's token tracking data structures. * This has O(1) time complexity, but alters the order of the _allTokens array. * @param tokenId uint256 ID of the token to be removed from the tokens list */ function _removeTokenFromAllTokensEnumeration(uint256 tokenId) private { // To prevent a gap in the tokens array, we store the last token in the index of the token to delete, and // then delete the last slot (swap and pop). uint256 lastTokenIndex = _allTokens.length - 1; uint256 tokenIndex = _allTokensIndex[tokenId]; // When the token to delete is the last token, the swap operation is unnecessary. However, since this occurs so // rarely (when the last minted token is burnt) that we still do the swap here to avoid the gas cost of adding // an 'if' statement (like in _removeTokenFromOwnerEnumeration) uint256 lastTokenId = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token _allTokensIndex[lastTokenId] = tokenIndex; // Update the moved token's index // This also deletes the contents at the last position of the array delete _allTokensIndex[tokenId]; _allTokens.pop(); } } // File: contracts/CommonNFT.sol pragma solidity =0.8.21; error InvalidId(); abstract contract CommonNFT is ERC721Enumerable { string internal baseURI; mapping(uint256 => string) public tokenURIs; modifier onlyTokenOwner( uint256 _tokenId ) { require( ownerOf(_tokenId) == msg.sender, "CommonBase: INVALID_OWNER" ); _; } function isMinted( uint256 _tokenId ) external view returns(bool) { return _exists(_tokenId); } function ownedByAddress( address _owner ) external view returns (uint256[] memory) { uint256 ownerNFTCount = balanceOf( _owner ); uint256[] memory nftIds = new uint256[]( ownerNFTCount ); uint256 i; for (i; i < ownerNFTCount;) { nftIds[i] = tokenOfOwnerByIndex( _owner, i ); unchecked { ++i; } } return nftIds; } } // File: contracts/ScratchNFT.sol pragma solidity =0.8.21; error AlreadyClaimed(); abstract contract ScratchNFT is CommonNFT, PrizeTiers { using Strings for uint256; uint256 public latestTicketId; mapping(uint256 => bool) public claimed; mapping(uint256 => uint256) public prizes; mapping(uint256 => uint256) public editions; struct Drawing { uint256 drawId; address ticketReceiver; } mapping(uint256 => Drawing) public requestIdToDrawing; event SetClaimed( uint256 indexed ticketId ); event MintCompleted( uint256 indexed ticketId, uint256 indexed edition, address indexed recipient, uint256 prize ); event PrizeClaimed( uint256 indexed ticketId, address indexed receiver, uint256 amount ); function _mintTicket( uint256 _ticketId, uint256 _editionId, uint256 _prize, address _receiver ) internal { prizes[_ticketId] = _prize; editions[_ticketId] = _editionId; _mint( _receiver, _ticketId ); emit MintCompleted( _ticketId, _editionId, _receiver, _prize ); } function tokenURI( uint256 _ticketId ) public view override returns (string memory) { if (_exists(_ticketId) == false) { revert InvalidId(); } string memory claimDone = claimed[_ticketId] ? "true" : "false"; return string( abi.encodePacked( baseURI, _ticketId.toString(), "/", claimDone, ".json" ) ); } function _setClaimed( uint256 _ticketId ) internal { if (claimed[_ticketId] == true) { revert AlreadyClaimed(); } claimed[_ticketId] = true; emit SetClaimed( _ticketId ); } } // File: @openzeppelin/contracts/access/Ownable.sol // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } } // File: contracts/helpers/Pausable.sol pragma solidity =0.8.21; error ContractPaused(); error ContractNotPaused(); contract Pausable is Ownable { bool public paused; event Paused( address indexed caller, uint256 blocktime ); event Unpaused( address indexed caller, uint256 blocktime ); constructor() { paused = false; } modifier whenNotPaused() { if (paused == true) { revert ContractPaused(); } _; } modifier whenPaused() { if (paused == false) { revert ContractNotPaused(); } _; } function pauseContract() external onlyOwner whenNotPaused { paused = true; emit Paused( msg.sender, block.timestamp ); } function unpauseContract() external onlyOwner whenPaused { paused = false; emit Unpaused( msg.sender, block.timestamp ); } } // File: @chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol pragma solidity ^0.8.4; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. It ensures 2 things: * @dev 1. The fulfillment came from the VRFCoordinator * @dev 2. The consumer contract implements fulfillRandomWords. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constructor(<other arguments>, address _vrfCoordinator, address _link) * @dev VRFConsumerBase(_vrfCoordinator) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash). Create subscription, fund it * @dev and your consumer contract as a consumer of it (see VRFCoordinatorInterface * @dev subscription management functions). * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, * @dev callbackGasLimit, numWords), * @dev see (VRFCoordinatorInterface for a description of the arguments). * * @dev Once the VRFCoordinator has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomWords method. * * @dev The randomness argument to fulfillRandomWords is a set of random words * @dev generated from your requestId and the blockHash of the request. * * @dev If your contract could have concurrent requests open, you can use the * @dev requestId returned from requestRandomWords to track which response is associated * @dev with which randomness request. * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. It is for this reason that * @dev that you can signal to an oracle you'd like them to wait longer before * @dev responding to the request (however this is not enforced in the contract * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { error OnlyCoordinatorCanFulfill(address have, address want); address private immutable vrfCoordinator; /** * @param _vrfCoordinator address of VRFCoordinator contract */ constructor(address _vrfCoordinator) { vrfCoordinator = _vrfCoordinator; } /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomWords the VRF output expanded to the requested number of words */ function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { if (msg.sender != vrfCoordinator) { revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); } fulfillRandomWords(requestId, randomWords); } } // File: @chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol pragma solidity ^0.8.0; interface VRFCoordinatorV2Interface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns ( uint16, uint32, bytes32[] memory ); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the VRFCoordinator from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(COORDINATOR), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription(uint64 subId) external view returns ( uint96 balance, uint64 reqCount, address owner, address[] memory consumers ); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; /* * @notice Check to see if there exists a request commitment consumers * for all consumers and keyhashes for a given sub. * @param subId - ID of the subscription * @return true if there exists at least one unfulfilled request for the subscription, false * otherwise. */ function pendingRequestExists(uint64 subId) external view returns (bool); } // File: contracts/CommonVRF.sol pragma solidity =0.8.21; error InvalidCost(); error TooManyReceivers(); abstract contract CommonVRF is TokenHelper, Pausable, VRFConsumerBaseV2 { VRFCoordinatorV2Interface public immutable VRF_COORDINATOR; // Verse Token contract for service. IERC20 public immutable VERSE_TOKEN; // Link Token contract for top-up. ILinkToken public immutable LINK_TOKEN; // Generated on deployment or passed as argument. uint64 public immutable SUBSCRIPTION_ID; // Chainlink VRF Key Hash for RNG requests. bytes32 public immutable GAS_KEYHASH; // For free giveaways maximum receivers is 50. uint32 public constant MAX_LOOPS = 50; // Number of confirmations needed for RNG request. uint16 public constant CONFIRMATIONS_NEEDED = 3; // Higher value means more gas for callback. uint32 public constant CALLBACK_MAX_GAS = 2000000; // How much to charge for base service. uint256 public baseCost; // Keeps track of latest drawId to VRF. uint256 public latestDrawId; mapping(uint256 => uint256) public drawIdToRequestId; event DrawRequest( uint256 indexed drawId, uint256 indexed requestId, address indexed requestAddress ); event RequestFulfilled( uint256 indexed drawId, uint256 indexed requestId, uint256[] indexed resultValue ); event WithdrawTokens( address indexed receiver, uint256 indexed amount ); constructor( address _linkTokenAddress, address _verseTokenAddress, bytes32 _gasKeyHash, uint64 _subscriptionId, address _vrfCoordinatorV2Address ) VRFConsumerBaseV2( _vrfCoordinatorV2Address ) { VERSE_TOKEN = IERC20( _verseTokenAddress ); LINK_TOKEN = ILinkToken( _linkTokenAddress ); VRF_COORDINATOR = VRFCoordinatorV2Interface( _vrfCoordinatorV2Address ); SUBSCRIPTION_ID = _subscriptionId > 0 ? _subscriptionId : _createNewSubscription(); GAS_KEYHASH = _gasKeyHash; } function _createNewSubscription() private returns (uint64 newSubscriptionId) { newSubscriptionId = VRF_COORDINATOR.createSubscription(); VRF_COORDINATOR.addConsumer( newSubscriptionId, address(this) ); } function _requestRandomWords( uint32 _wordCount ) internal returns (uint256 requestId) { requestId = VRF_COORDINATOR.requestRandomWords( GAS_KEYHASH, SUBSCRIPTION_ID, CONFIRMATIONS_NEEDED, CALLBACK_MAX_GAS, _wordCount ); } /** * @notice Allows load {$LINK} tokens to subscription. * @dev Can be called with anyone, who wants to donate. * @param _linkAmount how much to load to subscription. */ function loadSubscription( uint256 _linkAmount ) external { _takeTokens( LINK_TOKEN, _linkAmount ); LINK_TOKEN.transferAndCall( address(VRF_COORDINATOR), _linkAmount, abi.encode(SUBSCRIPTION_ID) ); } function changeBaseCost( uint256 _newBaseCost ) external onlyOwner { if (_newBaseCost == 0) { revert InvalidCost(); } if (_newBaseCost == baseCost) { revert InvalidCost(); } baseCost = _newBaseCost; } /** * @notice Allows to withdraw any token from the contract. * @dev Only can be called by the contract owner. */ function withdrawTokens( IERC20 _token, uint256 _amount ) external onlyOwner { _giveTokens( _token, msg.sender, _amount ); emit WithdrawTokens( msg.sender, _amount ); } /** * @notice Allows to avoid modulo bias for RNG. * @param _entropy random value passed from VRF. * @param _upperBound maximum outcome for {_entropy}. */ function uniform( uint256 _entropy, uint256 _upperBound ) public pure returns (uint256) { uint256 min = (type(uint256).max - _upperBound + 1) % _upperBound; uint256 random = _entropy; while (true) { if (random >= min) { break; } random = uint256( keccak256( abi.encodePacked( random ) ) ); } return random % _upperBound + 1; } } // File: contracts/ScratchVRF.sol pragma solidity =0.8.21; error NotEnoughFunds(); contract ScratchVRF is ScratchNFT, CommonVRF { constructor( string memory _name, string memory _symbol, address _vrfCoordinatorV2Address, uint256 _ticketCost, address _linkTokenAddress, address _verseTokenAddress, bytes32 _gasKeyHash, uint64 _subscriptionId ) ERC721( _name, _symbol ) CommonVRF( _linkTokenAddress, _verseTokenAddress, _gasKeyHash, _subscriptionId, _vrfCoordinatorV2Address ) { baseCost = _ticketCost; } /** * @notice Allows to purchase scratch ticket as NFT. */ function buyScratchTicket() external whenNotPaused { _newScratchTicket( msg.sender ); } /** * @notice Allows to gift scratch ticket. * @param _receiver address for gifted NFT. */ function giftScratchTicket( address _receiver ) external whenNotPaused { _newScratchTicket( _receiver ); } function _newScratchTicket( address _receiver ) internal { _takeTokens( VERSE_TOKEN, baseCost ); _drawTicketRequest( _receiver ); } /** * @notice Allows to gift scratch ticket for free. * @dev Only can be called by the contract owner. * @param _receivers address for gifted NFTs. */ function giftForFree( address[] calldata _receivers ) external onlyOwner { uint256 i; uint256 loops = _receivers.length; if (loops > MAX_LOOPS) { revert TooManyReceivers(); } for (i; i < loops;) { _drawTicketRequest( _receivers[i] ); unchecked { ++i; } } } function _drawTicketRequest( address _receiver ) internal { uint256 requestId = _requestRandomWords({ _wordCount: 2 }); uint256 latestDrawId = _increaseLatestDrawId(); Drawing memory newDrawing = Drawing({ drawId: latestDrawId, ticketReceiver: _receiver }); drawIdToRequestId[latestDrawId] = requestId; requestIdToDrawing[requestId] = newDrawing; emit DrawRequest( latestDrawId, requestId, msg.sender ); } /** * @notice callback function for chainlink VRF. * @param _requestId id of the VRF request. * @param _randomWords array with random numbers. */ function fulfillRandomWords( uint256 _requestId, uint256[] memory _randomWords ) internal override { Drawing memory currentDraw = requestIdToDrawing[ _requestId ]; uint256 randomEdition = uniform( _randomWords[1], 10 ); uint256 randomNumber = uniform( _randomWords[0], 1_000 ); uint256 prize = _getPrizeTier( randomNumber ); uint256 latestTicketId = _increaseLatestTicketId(); _mintTicket( latestTicketId, randomEdition, prize, currentDraw.ticketReceiver ); emit RequestFulfilled( currentDraw.drawId, _requestId, _randomWords ); } function _increaseLatestTicketId() internal returns (uint256) { unchecked { return ++latestTicketId; } } function _increaseLatestDrawId() internal returns (uint256) { unchecked { return ++latestDrawId; } } function _getPrizeTier( uint256 _number ) internal view returns (uint256 prize) { uint256 i; uint256 loops = prizeTiers.length; for (i; i < loops;) { PrizeTier memory pt = prizeTiers[i]; if (_number >= pt.drawEdgeA && _number <= pt.drawEdgeB) { prize = pt.winAmount; return prize; } unchecked { ++i; } } } /** * @notice Allows claim prize for scratch NFT. * @param _ticketId of the scratch ticket NFT. */ function claimPrize( uint256 _ticketId ) external whenNotPaused onlyTokenOwner(_ticketId) { _setClaimed( _ticketId ); uint256 prizeWei = prizes[ _ticketId ]; uint256 balance = VERSE_TOKEN.balanceOf( address(this) ); if (balance < prizeWei) { revert NotEnoughFunds(); } _giveTokens( VERSE_TOKEN, msg.sender, prizeWei ); emit PrizeClaimed( _ticketId, msg.sender, prizeWei ); } function updateBaseURI( string calldata _newBaseURI ) external onlyOwner { baseURI = _newBaseURI; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_vrfCoordinatorV2Address","type":"address"},{"internalType":"uint256","name":"_ticketCost","type":"uint256"},{"internalType":"address","name":"_linkTokenAddress","type":"address"},{"internalType":"address","name":"_verseTokenAddress","type":"address"},{"internalType":"bytes32","name":"_gasKeyHash","type":"bytes32"},{"internalType":"uint64","name":"_subscriptionId","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyClaimed","type":"error"},{"inputs":[],"name":"ContractNotPaused","type":"error"},{"inputs":[],"name":"ContractPaused","type":"error"},{"inputs":[],"name":"InvalidCost","type":"error"},{"inputs":[],"name":"InvalidId","type":"error"},{"inputs":[],"name":"NotEnoughFunds","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"TooManyReceivers","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"drawId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"address","name":"requestAddress","type":"address"}],"name":"DrawRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"ticketId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"edition","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"prize","type":"uint256"}],"name":"MintCompleted","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":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"blocktime","type":"uint256"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"ticketId","type":"uint256"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PrizeClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"drawId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":true,"internalType":"uint256[]","name":"resultValue","type":"uint256[]"}],"name":"RequestFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"ticketId","type":"uint256"}],"name":"SetClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"blocktime","type":"uint256"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawTokens","type":"event"},{"inputs":[],"name":"CALLBACK_MAX_GAS","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CONFIRMATIONS_NEEDED","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GAS_KEYHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LINK_TOKEN","outputs":[{"internalType":"contract ILinkToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_LOOPS","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRECISION_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SUBSCRIPTION_ID","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VERSE_TOKEN","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VRF_COORDINATOR","outputs":[{"internalType":"contract VRFCoordinatorV2Interface","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseCost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyScratchTicket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newBaseCost","type":"uint256"}],"name":"changeBaseCost","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ticketId","type":"uint256"}],"name":"claimPrize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"drawIdToRequestId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"editions","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"_receivers","type":"address[]"}],"name":"giftForFree","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"}],"name":"giftScratchTicket","outputs":[],"stateMutability":"nonpayable","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":"_tokenId","type":"uint256"}],"name":"isMinted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestDrawId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestTicketId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_linkAmount","type":"uint256"}],"name":"loadSubscription","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"ownedByAddress","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"prizeTiers","outputs":[{"internalType":"uint256","name":"drawEdgeA","type":"uint256"},{"internalType":"uint256","name":"drawEdgeB","type":"uint256"},{"internalType":"uint256","name":"winAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"prizes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"requestIdToDrawing","outputs":[{"internalType":"uint256","name":"drawId","type":"uint256"},{"internalType":"address","name":"ticketReceiver","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"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":"_amount","type":"uint256"}],"name":"toWei","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_ticketId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokenURIs","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_entropy","type":"uint256"},{"internalType":"uint256","name":"_upperBound","type":"uint256"}],"name":"uniform","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"unpauseContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newBaseURI","type":"string"}],"name":"updateBaseURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101406040523480156200001257600080fd5b5060405162003fd838038062003fd8833981016040819052620000359162000614565b8383838389808d8d60006200004b83826200076b565b5060016200005a82826200076b565b505050600c604051806060016040528061032081526020016103e881526020016200008c6064620003cf60201b60201c565b90528154600181810184556000938452602093849020835160039093020191825583830151908201556040918201516002909101558051606081018252610118815261031f92810192909252600c91908101620000eb6101f4620003cf565b905281546001818101845560009384526020938490208351600390930201918255838301519082015560409182015160029091015580516060810182526050815261011792810192909252600c91908101620001496103e8620003cf565b90528154600181810184556000938452602093849020835160039093020191825583830151908201556040918201516002909101558051606081018252601e8152604f92810192909252600c91908101620001a6611388620003cf565b90528154600181810184556000938452602093849020835160039093020191825583830151908201556040918201516002909101558051606081018252600a8152601d92810192909252600c9190810162000203612710620003cf565b9052815460018181018455600093845260209384902083516003909302019182558383015190820155604091820151600290910155805160608101825260048152600992810192909252600c919081016200026061c350620003cf565b90528154600181810184556000938452602093849020835160039384029091019081558484015191810191909155604092830151600291820155825160608101845290815292830152600c91908101620002bd620186a0620003cf565b9052815460018181018455600093845260209384902083516003909302019182558383015182820155604092830151600290920191909155815160608101835281815292830152600c9190810162000318620f4240620003cf565b9052815460018082018455600093845260209384902083516003909302019182559282015192810192909255604001516002909101556200035933620003eb565b6012805460ff60a01b191690556001600160a01b0390811660805284811660c05285811660e052811660a0526001600160401b038216620003a4576200039e6200043d565b620003a6565b815b6001600160401b0316610100525050610120525050506013939093555062000882945050505050565b6000620003e5670de0b6b3a76400008362000837565b92915050565b601280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b600060a0516001600160a01b031663a21a23e46040518163ffffffff1660e01b81526004016020604051808303816000875af115801562000482573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004a891906200085d565b60a051604051631cd0704360e21b81526001600160401b03831660048201523060248201529192506001600160a01b031690637341c10c90604401600060405180830381600087803b158015620004fe57600080fd5b505af115801562000513573d6000803e3d6000fd5b5050505090565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200054257600080fd5b81516001600160401b03808211156200055f576200055f6200051a565b604051601f8301601f19908116603f011681019082821181831017156200058a576200058a6200051a565b81604052838152602092508683858801011115620005a757600080fd5b600091505b83821015620005cb5785820183015181830184015290820190620005ac565b600093810190920192909252949350505050565b80516001600160a01b0381168114620005f757600080fd5b919050565b80516001600160401b0381168114620005f757600080fd5b600080600080600080600080610100898b0312156200063257600080fd5b88516001600160401b03808211156200064a57600080fd5b620006588c838d0162000530565b995060208b01519150808211156200066f57600080fd5b506200067e8b828c0162000530565b9750506200068f60408a01620005df565b955060608901519450620006a660808a01620005df565b9350620006b660a08a01620005df565b925060c08901519150620006cd60e08a01620005fc565b90509295985092959890939650565b600181811c90821680620006f157607f821691505b6020821081036200071257634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200076657600081815260208120601f850160051c81016020861015620007415750805b601f850160051c820191505b8181101562000762578281556001016200074d565b5050505b505050565b81516001600160401b038111156200078757620007876200051a565b6200079f81620007988454620006dc565b8462000718565b602080601f831160018114620007d75760008415620007be5750858301515b600019600386901b1c1916600185901b17855562000762565b600085815260208120601f198616915b828110156200080857888601518255948401946001909101908401620007e7565b5085821015620008275787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b8082028115828204841417620003e557634e487b7160e01b600052601160045260246000fd5b6000602082840312156200087057600080fd5b6200087b82620005fc565b9392505050565b60805160a05160c05160e05161010051610120516136b96200091f6000396000818161067701526124fd015260008181610394015281816110c4015261252c01526000818161083f0152818161109001526110f3015260008181610570015281816115fb015281816116af0152611dd00152600081816103d40152818161111c0152612572015260008181610b090152610b6401526136b96000f3fe608060405234801561001057600080fd5b50600436106103625760003560e01c806370a08231116101c8578063b33712c511610104578063dbe7e3bd116100a2578063eccb3a4f1161007c578063eccb3a4f1461081a578063eedac3a61461083a578063f0d8195714610861578063f2fde38b1461087457600080fd5b8063dbe7e3bd146107a8578063e985e9c5146107cb578063eb2ab6b11461080757600080fd5b8063c87b56dd116100de578063c87b56dd14610758578063c8c523581461076b578063ccd34cd514610786578063d70981541461079557600080fd5b8063b33712c51461071d578063b608369214610725578063b88d4fde1461074557600080fd5b80638da5cb5b1161017157806395d89b411161014b57806395d89b41146106cf578063a22cb465146106d7578063a967dd84146106ea578063b2b8c65b1461070a57600080fd5b80638da5cb5b146106a2578063931688cb146106b357806393822557146106c657600080fd5b8063844c738c116101a2578063844c738c1461066957806387886e87146106725780638d6df0a31461069957600080fd5b806370a082311461063b578063715018a61461064e5780637285b53c1461065657600080fd5b80632f745c59116102a257806353e9cece116102405780636352211e1161021a5780636352211e146105fa57806364a9bd951461060d578063669dafe8146106155780636c8b703f1461062857600080fd5b806353e9cece146105a55780635afdc35d146105d35780635c975abb146105e657600080fd5b806342842e0e1161027c57806342842e0e14610550578063439766ce1461056357806347c0127e1461056b5780634f6ccce71461059257600080fd5b80632f745c591461052257806333c41a901461053557806337a2eb711461054857600080fd5b8063095ea7b31161030f57806318160ddd116102e957806318160ddd146104ca5780631fe543e3146104dc57806323b872dd146104ef578063279c806e1461050257600080fd5b8063095ea7b31461044b5780630d7210461461045e5780630eca343f146104ab57600080fd5b806306b091f91161034057806306b091f91461040e57806306fdde0314610423578063081812fc1461043857600080fd5b806301ffc9a714610367578063030932bb1461038f57806305f6a924146103cf575b600080fd5b61037a610375366004612def565b610887565b60405190151581526020015b60405180910390f35b6103b67f000000000000000000000000000000000000000000000000000000000000000081565b60405167ffffffffffffffff9091168152602001610386565b6103f67f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610386565b61042161041c366004612e28565b6108cb565b005b61042b61090f565b6040516103869190612ea4565b6103f6610446366004612eb7565b6109a1565b610421610459366004612e28565b6109c8565b61048e61046c366004612eb7565b601160205260009081526040902080546001909101546001600160a01b031682565b604080519283526001600160a01b03909116602083015201610386565b6104b5621e848081565b60405163ffffffff9091168152602001610386565b6008545b604051908152602001610386565b6104216104ea366004612f17565b610afe565b6104216104fd366004612fc9565b610b9f565b6104ce610510366004612eb7565b60106020526000908152604090205481565b6104ce610530366004612e28565b610c16565b61037a610543366004612eb7565b610cbe565b6104b5603281565b61042161055e366004612fc9565b610cdd565b610421610cf8565b6103f67f000000000000000000000000000000000000000000000000000000000000000081565b6104ce6105a0366004612eb7565b610d80565b6105b86105b3366004612eb7565b610e24565b60408051938452602084019290925290820152606001610386565b6104216105e136600461300a565b610e57565b60125461037a90600160a01b900460ff1681565b6103f6610608366004612eb7565b610e92565b610421610ef7565b6104ce610623366004612eb7565b610f31565b61042b610636366004612eb7565b610f45565b6104ce61064936600461300a565b610fdf565b610421611079565b610421610664366004612eb7565b61108b565b6104ce60145481565b6104ce7f000000000000000000000000000000000000000000000000000000000000000081565b6104ce600d5481565b6012546001600160a01b03166103f6565b6104216106c1366004613027565b6111af565b6104ce60135481565b61042b6111c4565b6104216106e53660046130a7565b6111d3565b6104ce6106f8366004612eb7565b60156020526000908152604090205481565b6104216107183660046130e0565b6111de565b61042161126c565b61073861073336600461300a565b6112fb565b6040516103869190613143565b610421610753366004613187565b611393565b61042b610766366004612eb7565b61140b565b610773600381565b60405161ffff9091168152602001610386565b6104ce670de0b6b3a764000081565b6104216107a3366004612eb7565b611522565b61037a6107b6366004612eb7565b600e6020526000908152604090205460ff1681565b61037a6107d936600461324b565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6104ce610815366004613279565b611712565b6104ce610828366004612eb7565b600f6020526000908152604090205481565b6103f67f000000000000000000000000000000000000000000000000000000000000000081565b61042161086f366004612eb7565b611787565b61042161088236600461300a565b6117d7565b60006001600160e01b031982167f780e9d630000000000000000000000000000000000000000000000000000000014806108c557506108c582611864565b92915050565b6108d36118ff565b6108de823383611959565b604051819033907f680f2e4f4032ebf1774e8cdbaddcb1b617a5a606411c8ca96257ada338d3833c90600090a35050565b60606000805461091e9061329b565b80601f016020809104026020016040519081016040528092919081815260200182805461094a9061329b565b80156109975780601f1061096c57610100808354040283529160200191610997565b820191906000526020600020905b81548152906001019060200180831161097a57829003601f168201915b5050505050905090565b60006109ac8261196d565b506000908152600460205260409020546001600160a01b031690565b60006109d382610e92565b9050806001600160a01b0316836001600160a01b031603610a615760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b336001600160a01b0382161480610a7d5750610a7d81336107d9565b610aef5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610a58565b610af983836119d1565b505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b91576040517f1cf993f40000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166024820152604401610a58565b610b9b8282611a3f565b5050565b610ba93382611b46565b610c0b5760405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201526c1c881bdc88185c1c1c9bdd9959609a1b6064820152608401610a58565b610af9838383611bc5565b6000610c2183610fdf565b8210610c955760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e64730000000000000000000000000000000000000000006064820152608401610a58565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6000818152600260205260408120546001600160a01b031615156108c5565b610af983838360405180602001604052806000815250611393565b610d006118ff565b601254600160a01b900460ff161515600103610d2f5760405163ab35696f60e01b815260040160405180910390fd5b6012805460ff60a01b1916600160a01b17905560405133907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d90610d769042815260200190565b60405180910390a2565b6000610d8b60085490565b8210610dff5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e647300000000000000000000000000000000000000006064820152608401610a58565b60088281548110610e1257610e126132d5565b90600052602060002001549050919050565b600c8181548110610e3457600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b601254600160a01b900460ff161515600103610e865760405163ab35696f60e01b815260040160405180910390fd5b610e8f81611dcb565b50565b6000818152600260205260408120546001600160a01b0316806108c55760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610a58565b601254600160a01b900460ff161515600103610f265760405163ab35696f60e01b815260040160405180910390fd5b610f2f33611dcb565b565b60006108c5670de0b6b3a764000083613301565b600b6020526000908152604090208054610f5e9061329b565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8a9061329b565b8015610fd75780601f10610fac57610100808354040283529160200191610fd7565b820191906000526020600020905b815481529060010190602001808311610fba57829003601f168201915b505050505081565b60006001600160a01b03821661105d5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610a58565b506001600160a01b031660009081526003602052604090205490565b6110816118ff565b610f2f6000611e00565b6110b57f000000000000000000000000000000000000000000000000000000000000000082611e52565b6040805167ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660208201526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001691634000aea0917f0000000000000000000000000000000000000000000000000000000000000000918591016040516020818303038152906040526040518463ffffffff1660e01b815260040161116c93929190613318565b6020604051808303816000875af115801561118b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9b9190613340565b6111b76118ff565b600a610af98284836133ab565b60606001805461091e9061329b565b610b9b338383611e67565b6111e66118ff565b6000816032811115611224576040517fc1e676e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808210156112665761125b848484818110611241576112416132d5565b9050602002016020810190611256919061300a565b611f35565b816001019150611224565b50505050565b6112746118ff565b601254600160a01b900460ff1615156000036112bc576040517fdcdde9dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6012805460ff60a01b1916905560405142815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c90602001610d76565b6060600061130883610fdf565b905060008167ffffffffffffffff81111561132557611325612ed0565b60405190808252806020026020018201604052801561134e578160200160208202803683370190505b50905060005b8281101561138b576113668582610c16565b828281518110611378576113786132d5565b6020908102919091010152600101611354565b509392505050565b61139d3383611b46565b6113ff5760405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201526c1c881bdc88185c1c1c9bdd9959609a1b6064820152608401610a58565b61126684848484611fe6565b6000818152600260205260409020546060906001600160a01b031615151515600003611463576040517fdfa1a40800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600e602052604081205460ff166114b4576040518060400160405280600581526020017f66616c73650000000000000000000000000000000000000000000000000000008152506114eb565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b9050600a6114f88461206f565b8260405160200161150b9392919061346b565b604051602081830303815290604052915050919050565b601254600160a01b900460ff1615156001036115515760405163ab35696f60e01b815260040160405180910390fd5b803361155c82610e92565b6001600160a01b0316146115b25760405162461bcd60e51b815260206004820152601960248201527f436f6d6d6f6e426173653a20494e56414c49445f4f574e4552000000000000006044820152606401610a58565b6115bb8261210d565b6000828152600f60205260408082205490517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561164a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166e9190613561565b9050818110156116aa576040517f81b5ad6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d57f00000000000000000000000000000000000000000000000000000000000000003384611959565b604051828152339085907f4aa95f981a8337cb337de335b965507da0879c3b49f799d20058e913f5ad2c269060200160405180910390a350505050565b600080826117228160001961357a565b61172d90600161358d565b61173791906135a0565b9050835b818110156117695760408051602080820193909352815180820384018152908201909152805191012061173b565b61177384826135a0565b61177e90600161358d565b95945050505050565b61178f6118ff565b806000036117b05760405163d7ba92d360e01b815260040160405180910390fd5b60135481036117d25760405163d7ba92d360e01b815260040160405180910390fd5b601355565b6117df6118ff565b6001600160a01b03811661185b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a58565b610e8f81611e00565b60006001600160e01b031982167f80ac58cd0000000000000000000000000000000000000000000000000000000014806118c757506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b806108c557507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316146108c5565b6012546001600160a01b03163314610f2f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a58565b610af96001600160a01b038416838361219d565b6000818152600260205260409020546001600160a01b0316610e8f5760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610a58565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611a0682610e92565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008281526011602090815260408083208151808301909252805482526001908101546001600160a01b0316928201929092528351909291611a9b918591908110611a8c57611a8c6132d5565b6020026020010151600a611712565b90506000611ac584600081518110611ab557611ab56132d5565b60200260200101516103e8611712565b90506000611ad28261222e565b90506000611ae7600d80546001019081905590565b9050611af981858488602001516122c9565b85604051611b0791906135c2565b604051908190038120865190918991907f5e3f21ca8056862d06a417cdb923dd8d3e06312bca2a8821974a27e7a522030b90600090a450505050505050565b600080611b5283610e92565b9050806001600160a01b0316846001600160a01b03161480611b9957506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b80611bbd5750836001600160a01b0316611bb2846109a1565b6001600160a01b0316145b949350505050565b826001600160a01b0316611bd882610e92565b6001600160a01b031614611c3c5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610a58565b6001600160a01b038216611cb75760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610a58565b611cc4838383600161233c565b826001600160a01b0316611cd782610e92565b6001600160a01b031614611d3b5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610a58565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b611df77f0000000000000000000000000000000000000000000000000000000000000000601354611e52565b610e8f81611f35565b601280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b610b9b6001600160a01b038316333084612484565b816001600160a01b0316836001600160a01b031603611ec85760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a58565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000611f4160026124d5565b90506000611f56601480546001019081905590565b6040805180820182528281526001600160a01b0386811660208084019182526000868152601582528581208990558881526011909152848120845181559151600190920180546001600160a01b03191692909316919091179091559151929350913391859185917f6438d905327051fd31a6b248bf430b0527939eccc69883f012652c797b39689d91a450505050565b611ff1848484611bc5565b611ffd848484846125e7565b6112665760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a58565b6060600061207c8361273e565b600101905060008167ffffffffffffffff81111561209c5761209c612ed0565b6040519080825280601f01601f1916602001820160405280156120c6576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450841561138b576120d0565b6000818152600e602052604090205460ff16151560010361215a576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600e6020526040808220805460ff191660011790555182917fc5f5bb097b8b6eedaca84092e68b49ea9018b7d7d6a068cc71c8fba9bda3934c91a250565b6040516001600160a01b038316602482015260448101829052610af99084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152612820565b600c5460009081905b808210156122c2576000600c8381548110612254576122546132d5565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509050806000015185101580156122a5575080602001518511155b156122b65760400151949350505050565b82600101925050612237565b5050919050565b6000848152600f60209081526040808320859055601090915290208390556122f18185612905565b806001600160a01b031683857f8e57532d3d1f4ac4f45fe8626844b6d51ea5c9ef39317d80da0132374ec741428560405161232e91815260200190565b60405180910390a450505050565b61234884848484612a9e565b60018111156123bf5760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e736563757469766520747260448201527f616e7366657273206e6f7420737570706f7274656400000000000000000000006064820152608401610a58565b816001600160a01b03851661241b5761241681600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b61243e565b836001600160a01b0316856001600160a01b03161461243e5761243e8582612b26565b6001600160a01b03841661245a5761245581612bc3565b61247d565b846001600160a01b0316846001600160a01b03161461247d5761247d8482612c72565b5050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526112669085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016121e2565b6040517f5d3b1d300000000000000000000000000000000000000000000000000000000081527f0000000000000000000000000000000000000000000000000000000000000000600482015267ffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016602482015260036044820152621e8480606482015263ffffffff821660848201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690635d3b1d309060a4016020604051808303816000875af11580156125c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c59190613561565b60006001600160a01b0384163b1561273357604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061262b9033908990889088906004016135f8565b6020604051808303816000875af1925050508015612666575060408051601f3d908101601f1916820190925261266391810190613634565b60015b612719573d808015612694576040519150601f19603f3d011682016040523d82523d6000602084013e612699565b606091505b5080516000036127115760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a58565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611bbd565b506001949350505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612787577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106127b3576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106127d157662386f26fc10000830492506010015b6305f5e10083106127e9576305f5e100830492506008015b61271083106127fd57612710830492506004015b6064831061280f576064830492506002015b600a83106108c55760010192915050565b6000612875826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612cb69092919063ffffffff16565b805190915015610af957808060200190518101906128939190613340565b610af95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a58565b6001600160a01b03821661295b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a58565b6000818152600260205260409020546001600160a01b0316156129c05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a58565b6129ce60008383600161233c565b6000818152600260205260409020546001600160a01b031615612a335760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a58565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001811115611266576001600160a01b03841615612ae4576001600160a01b03841660009081526003602052604081208054839290612ade90849061357a565b90915550505b6001600160a01b03831615611266576001600160a01b03831660009081526003602052604081208054839290612b1b90849061358d565b909155505050505050565b60006001612b3384610fdf565b612b3d919061357a565b600083815260076020526040902054909150808214612b90576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090612bd59060019061357a565b60008381526009602052604081205460088054939450909284908110612bfd57612bfd6132d5565b906000526020600020015490508060088381548110612c1e57612c1e6132d5565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480612c5657612c56613651565b6001900381819060005260206000200160009055905550505050565b6000612c7d83610fdf565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6060611bbd848460008585600080866001600160a01b03168587604051612cdd9190613667565b60006040518083038185875af1925050503d8060008114612d1a576040519150601f19603f3d011682016040523d82523d6000602084013e612d1f565b606091505b5091509150612d3087838387612d3b565b979650505050505050565b60608315612daa578251600003612da3576001600160a01b0385163b612da35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a58565b5081611bbd565b611bbd8383815115612dbf5781518083602001fd5b8060405162461bcd60e51b8152600401610a589190612ea4565b6001600160e01b031981168114610e8f57600080fd5b600060208284031215612e0157600080fd5b8135612e0c81612dd9565b9392505050565b6001600160a01b0381168114610e8f57600080fd5b60008060408385031215612e3b57600080fd5b8235612e4681612e13565b946020939093013593505050565b60005b83811015612e6f578181015183820152602001612e57565b50506000910152565b60008151808452612e90816020860160208601612e54565b601f01601f19169290920160200192915050565b602081526000612e0c6020830184612e78565b600060208284031215612ec957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612f0f57612f0f612ed0565b604052919050565b60008060408385031215612f2a57600080fd5b8235915060208084013567ffffffffffffffff80821115612f4a57600080fd5b818601915086601f830112612f5e57600080fd5b813581811115612f7057612f70612ed0565b8060051b9150612f81848301612ee6565b8181529183018401918481019089841115612f9b57600080fd5b938501935b83851015612fb957843582529385019390850190612fa0565b8096505050505050509250929050565b600080600060608486031215612fde57600080fd5b8335612fe981612e13565b92506020840135612ff981612e13565b929592945050506040919091013590565b60006020828403121561301c57600080fd5b8135612e0c81612e13565b6000806020838503121561303a57600080fd5b823567ffffffffffffffff8082111561305257600080fd5b818501915085601f83011261306657600080fd5b81358181111561307557600080fd5b86602082850101111561308757600080fd5b60209290920196919550909350505050565b8015158114610e8f57600080fd5b600080604083850312156130ba57600080fd5b82356130c581612e13565b915060208301356130d581613099565b809150509250929050565b600080602083850312156130f357600080fd5b823567ffffffffffffffff8082111561310b57600080fd5b818501915085601f83011261311f57600080fd5b81358181111561312e57600080fd5b8660208260051b850101111561308757600080fd5b6020808252825182820181905260009190848201906040850190845b8181101561317b5783518352928401929184019160010161315f565b50909695505050505050565b6000806000806080858703121561319d57600080fd5b84356131a881612e13565b93506020858101356131b981612e13565b935060408601359250606086013567ffffffffffffffff808211156131dd57600080fd5b818801915088601f8301126131f157600080fd5b81358181111561320357613203612ed0565b613215601f8201601f19168501612ee6565b9150808252898482850101111561322b57600080fd5b808484018584013760008482840101525080935050505092959194509250565b6000806040838503121561325e57600080fd5b823561326981612e13565b915060208301356130d581612e13565b6000806040838503121561328c57600080fd5b50508035926020909101359150565b600181811c908216806132af57607f821691505b6020821081036132cf57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176108c5576108c56132eb565b6001600160a01b038416815282602082015260606040820152600061177e6060830184612e78565b60006020828403121561335257600080fd5b8151612e0c81613099565b601f821115610af957600081815260208120601f850160051c810160208610156133845750805b601f850160051c820191505b818110156133a357828155600101613390565b505050505050565b67ffffffffffffffff8311156133c3576133c3612ed0565b6133d7836133d1835461329b565b8361335d565b6000601f84116001811461340b57600085156133f35750838201355b600019600387901b1c1916600186901b17835561247d565b600083815260209020601f19861690835b8281101561343c578685013582556020948501946001909201910161341c565b50868210156134595760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008085546134798161329b565b6001828116801561349157600181146134a6576134d5565b60ff19841687528215158302870194506134d5565b8960005260208060002060005b858110156134cc5781548a8201529084019082016134b3565b50505082870194505b50875192506134e8838560208b01612e54565b7f2f00000000000000000000000000000000000000000000000000000000000000939092019283528551916135238382860160208a01612e54565b61355481848601017f2e6a736f6e000000000000000000000000000000000000000000000000000000815260050190565b9998505050505050505050565b60006020828403121561357357600080fd5b5051919050565b818103818111156108c5576108c56132eb565b808201808211156108c5576108c56132eb565b6000826135bd57634e487b7160e01b600052601260045260246000fd5b500690565b815160009082906020808601845b838110156135ec578151855293820193908201906001016135d0565b50929695505050505050565b60006001600160a01b0380871683528086166020840152508360408301526080606083015261362a6080830184612e78565b9695505050505050565b60006020828403121561364657600080fd5b8151612e0c81612dd9565b634e487b7160e01b600052603160045260246000fd5b60008251613679818460208701612e54565b919091019291505056fea2646970667358221220a67ad31eb365dbe7d819ba8b7834c5a4745a95469accbe2570559da4cf9ad58864736f6c6343000815003300000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000ae975071be8f8ee67addbc1a82488f1c248580670000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f1000000000000000000000000c708d6f2153933daa50b2d0758955be0a93a8fecd729dc84e21ae57ffb6be0053bf2b0668aa2aaf300a2a7b2ddf7dc0bb6e875a800000000000000000000000000000000000000000000000000000000000003b70000000000000000000000000000000000000000000000000000000000000007534352415443480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075343524154434800000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103625760003560e01c806370a08231116101c8578063b33712c511610104578063dbe7e3bd116100a2578063eccb3a4f1161007c578063eccb3a4f1461081a578063eedac3a61461083a578063f0d8195714610861578063f2fde38b1461087457600080fd5b8063dbe7e3bd146107a8578063e985e9c5146107cb578063eb2ab6b11461080757600080fd5b8063c87b56dd116100de578063c87b56dd14610758578063c8c523581461076b578063ccd34cd514610786578063d70981541461079557600080fd5b8063b33712c51461071d578063b608369214610725578063b88d4fde1461074557600080fd5b80638da5cb5b1161017157806395d89b411161014b57806395d89b41146106cf578063a22cb465146106d7578063a967dd84146106ea578063b2b8c65b1461070a57600080fd5b80638da5cb5b146106a2578063931688cb146106b357806393822557146106c657600080fd5b8063844c738c116101a2578063844c738c1461066957806387886e87146106725780638d6df0a31461069957600080fd5b806370a082311461063b578063715018a61461064e5780637285b53c1461065657600080fd5b80632f745c59116102a257806353e9cece116102405780636352211e1161021a5780636352211e146105fa57806364a9bd951461060d578063669dafe8146106155780636c8b703f1461062857600080fd5b806353e9cece146105a55780635afdc35d146105d35780635c975abb146105e657600080fd5b806342842e0e1161027c57806342842e0e14610550578063439766ce1461056357806347c0127e1461056b5780634f6ccce71461059257600080fd5b80632f745c591461052257806333c41a901461053557806337a2eb711461054857600080fd5b8063095ea7b31161030f57806318160ddd116102e957806318160ddd146104ca5780631fe543e3146104dc57806323b872dd146104ef578063279c806e1461050257600080fd5b8063095ea7b31461044b5780630d7210461461045e5780630eca343f146104ab57600080fd5b806306b091f91161034057806306b091f91461040e57806306fdde0314610423578063081812fc1461043857600080fd5b806301ffc9a714610367578063030932bb1461038f57806305f6a924146103cf575b600080fd5b61037a610375366004612def565b610887565b60405190151581526020015b60405180910390f35b6103b67f00000000000000000000000000000000000000000000000000000000000003b781565b60405167ffffffffffffffff9091168152602001610386565b6103f67f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c2485806781565b6040516001600160a01b039091168152602001610386565b61042161041c366004612e28565b6108cb565b005b61042b61090f565b6040516103869190612ea4565b6103f6610446366004612eb7565b6109a1565b610421610459366004612e28565b6109c8565b61048e61046c366004612eb7565b601160205260009081526040902080546001909101546001600160a01b031682565b604080519283526001600160a01b03909116602083015201610386565b6104b5621e848081565b60405163ffffffff9091168152602001610386565b6008545b604051908152602001610386565b6104216104ea366004612f17565b610afe565b6104216104fd366004612fc9565b610b9f565b6104ce610510366004612eb7565b60106020526000908152604090205481565b6104ce610530366004612e28565b610c16565b61037a610543366004612eb7565b610cbe565b6104b5603281565b61042161055e366004612fc9565b610cdd565b610421610cf8565b6103f67f000000000000000000000000c708d6f2153933daa50b2d0758955be0a93a8fec81565b6104ce6105a0366004612eb7565b610d80565b6105b86105b3366004612eb7565b610e24565b60408051938452602084019290925290820152606001610386565b6104216105e136600461300a565b610e57565b60125461037a90600160a01b900460ff1681565b6103f6610608366004612eb7565b610e92565b610421610ef7565b6104ce610623366004612eb7565b610f31565b61042b610636366004612eb7565b610f45565b6104ce61064936600461300a565b610fdf565b610421611079565b610421610664366004612eb7565b61108b565b6104ce60145481565b6104ce7fd729dc84e21ae57ffb6be0053bf2b0668aa2aaf300a2a7b2ddf7dc0bb6e875a881565b6104ce600d5481565b6012546001600160a01b03166103f6565b6104216106c1366004613027565b6111af565b6104ce60135481565b61042b6111c4565b6104216106e53660046130a7565b6111d3565b6104ce6106f8366004612eb7565b60156020526000908152604090205481565b6104216107183660046130e0565b6111de565b61042161126c565b61073861073336600461300a565b6112fb565b6040516103869190613143565b610421610753366004613187565b611393565b61042b610766366004612eb7565b61140b565b610773600381565b60405161ffff9091168152602001610386565b6104ce670de0b6b3a764000081565b6104216107a3366004612eb7565b611522565b61037a6107b6366004612eb7565b600e6020526000908152604090205460ff1681565b61037a6107d936600461324b565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b6104ce610815366004613279565b611712565b6104ce610828366004612eb7565b600f6020526000908152604090205481565b6103f67f000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f181565b61042161086f366004612eb7565b611787565b61042161088236600461300a565b6117d7565b60006001600160e01b031982167f780e9d630000000000000000000000000000000000000000000000000000000014806108c557506108c582611864565b92915050565b6108d36118ff565b6108de823383611959565b604051819033907f680f2e4f4032ebf1774e8cdbaddcb1b617a5a606411c8ca96257ada338d3833c90600090a35050565b60606000805461091e9061329b565b80601f016020809104026020016040519081016040528092919081815260200182805461094a9061329b565b80156109975780601f1061096c57610100808354040283529160200191610997565b820191906000526020600020905b81548152906001019060200180831161097a57829003601f168201915b5050505050905090565b60006109ac8261196d565b506000908152600460205260409020546001600160a01b031690565b60006109d382610e92565b9050806001600160a01b0316836001600160a01b031603610a615760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b336001600160a01b0382161480610a7d5750610a7d81336107d9565b610aef5760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c0000006064820152608401610a58565b610af983836119d1565b505050565b336001600160a01b037f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c248580671614610b91576040517f1cf993f40000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b037f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c24858067166024820152604401610a58565b610b9b8282611a3f565b5050565b610ba93382611b46565b610c0b5760405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201526c1c881bdc88185c1c1c9bdd9959609a1b6064820152608401610a58565b610af9838383611bc5565b6000610c2183610fdf565b8210610c955760405162461bcd60e51b815260206004820152602b60248201527f455243373231456e756d657261626c653a206f776e657220696e646578206f7560448201527f74206f6620626f756e64730000000000000000000000000000000000000000006064820152608401610a58565b506001600160a01b03919091166000908152600660209081526040808320938352929052205490565b6000818152600260205260408120546001600160a01b031615156108c5565b610af983838360405180602001604052806000815250611393565b610d006118ff565b601254600160a01b900460ff161515600103610d2f5760405163ab35696f60e01b815260040160405180910390fd5b6012805460ff60a01b1916600160a01b17905560405133907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d90610d769042815260200190565b60405180910390a2565b6000610d8b60085490565b8210610dff5760405162461bcd60e51b815260206004820152602c60248201527f455243373231456e756d657261626c653a20676c6f62616c20696e646578206f60448201527f7574206f6620626f756e647300000000000000000000000000000000000000006064820152608401610a58565b60088281548110610e1257610e126132d5565b90600052602060002001549050919050565b600c8181548110610e3457600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b601254600160a01b900460ff161515600103610e865760405163ab35696f60e01b815260040160405180910390fd5b610e8f81611dcb565b50565b6000818152600260205260408120546001600160a01b0316806108c55760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610a58565b601254600160a01b900460ff161515600103610f265760405163ab35696f60e01b815260040160405180910390fd5b610f2f33611dcb565b565b60006108c5670de0b6b3a764000083613301565b600b6020526000908152604090208054610f5e9061329b565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8a9061329b565b8015610fd75780601f10610fac57610100808354040283529160200191610fd7565b820191906000526020600020905b815481529060010190602001808311610fba57829003601f168201915b505050505081565b60006001600160a01b03821661105d5760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f74206120766160448201527f6c6964206f776e657200000000000000000000000000000000000000000000006064820152608401610a58565b506001600160a01b031660009081526003602052604090205490565b6110816118ff565b610f2f6000611e00565b6110b57f000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f182611e52565b6040805167ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000003b71660208201526001600160a01b037f000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f11691634000aea0917f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c24858067918591016040516020818303038152906040526040518463ffffffff1660e01b815260040161116c93929190613318565b6020604051808303816000875af115801561118b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b9b9190613340565b6111b76118ff565b600a610af98284836133ab565b60606001805461091e9061329b565b610b9b338383611e67565b6111e66118ff565b6000816032811115611224576040517fc1e676e900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808210156112665761125b848484818110611241576112416132d5565b9050602002016020810190611256919061300a565b611f35565b816001019150611224565b50505050565b6112746118ff565b601254600160a01b900460ff1615156000036112bc576040517fdcdde9dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6012805460ff60a01b1916905560405142815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c90602001610d76565b6060600061130883610fdf565b905060008167ffffffffffffffff81111561132557611325612ed0565b60405190808252806020026020018201604052801561134e578160200160208202803683370190505b50905060005b8281101561138b576113668582610c16565b828281518110611378576113786132d5565b6020908102919091010152600101611354565b509392505050565b61139d3383611b46565b6113ff5760405162461bcd60e51b815260206004820152602d60248201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560448201526c1c881bdc88185c1c1c9bdd9959609a1b6064820152608401610a58565b61126684848484611fe6565b6000818152600260205260409020546060906001600160a01b031615151515600003611463576040517fdfa1a40800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600e602052604081205460ff166114b4576040518060400160405280600581526020017f66616c73650000000000000000000000000000000000000000000000000000008152506114eb565b6040518060400160405280600481526020017f74727565000000000000000000000000000000000000000000000000000000008152505b9050600a6114f88461206f565b8260405160200161150b9392919061346b565b604051602081830303815290604052915050919050565b601254600160a01b900460ff1615156001036115515760405163ab35696f60e01b815260040160405180910390fd5b803361155c82610e92565b6001600160a01b0316146115b25760405162461bcd60e51b815260206004820152601960248201527f436f6d6d6f6e426173653a20494e56414c49445f4f574e4552000000000000006044820152606401610a58565b6115bb8261210d565b6000828152600f60205260408082205490517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091907f000000000000000000000000c708d6f2153933daa50b2d0758955be0a93a8fec6001600160a01b0316906370a0823190602401602060405180830381865afa15801561164a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061166e9190613561565b9050818110156116aa576040517f81b5ad6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6116d57f000000000000000000000000c708d6f2153933daa50b2d0758955be0a93a8fec3384611959565b604051828152339085907f4aa95f981a8337cb337de335b965507da0879c3b49f799d20058e913f5ad2c269060200160405180910390a350505050565b600080826117228160001961357a565b61172d90600161358d565b61173791906135a0565b9050835b818110156117695760408051602080820193909352815180820384018152908201909152805191012061173b565b61177384826135a0565b61177e90600161358d565b95945050505050565b61178f6118ff565b806000036117b05760405163d7ba92d360e01b815260040160405180910390fd5b60135481036117d25760405163d7ba92d360e01b815260040160405180910390fd5b601355565b6117df6118ff565b6001600160a01b03811661185b5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610a58565b610e8f81611e00565b60006001600160e01b031982167f80ac58cd0000000000000000000000000000000000000000000000000000000014806118c757506001600160e01b031982167f5b5e139f00000000000000000000000000000000000000000000000000000000145b806108c557507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316146108c5565b6012546001600160a01b03163314610f2f5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610a58565b610af96001600160a01b038416838361219d565b6000818152600260205260409020546001600160a01b0316610e8f5760405162461bcd60e51b815260206004820152601860248201527f4552433732313a20696e76616c696420746f6b656e20494400000000000000006044820152606401610a58565b600081815260046020526040902080546001600160a01b0319166001600160a01b0384169081179091558190611a0682610e92565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b60008281526011602090815260408083208151808301909252805482526001908101546001600160a01b0316928201929092528351909291611a9b918591908110611a8c57611a8c6132d5565b6020026020010151600a611712565b90506000611ac584600081518110611ab557611ab56132d5565b60200260200101516103e8611712565b90506000611ad28261222e565b90506000611ae7600d80546001019081905590565b9050611af981858488602001516122c9565b85604051611b0791906135c2565b604051908190038120865190918991907f5e3f21ca8056862d06a417cdb923dd8d3e06312bca2a8821974a27e7a522030b90600090a450505050505050565b600080611b5283610e92565b9050806001600160a01b0316846001600160a01b03161480611b9957506001600160a01b0380821660009081526005602090815260408083209388168352929052205460ff165b80611bbd5750836001600160a01b0316611bb2846109a1565b6001600160a01b0316145b949350505050565b826001600160a01b0316611bd882610e92565b6001600160a01b031614611c3c5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610a58565b6001600160a01b038216611cb75760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610a58565b611cc4838383600161233c565b826001600160a01b0316611cd782610e92565b6001600160a01b031614611d3b5760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201526437bbb732b960d91b6064820152608401610a58565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b611df77f000000000000000000000000c708d6f2153933daa50b2d0758955be0a93a8fec601354611e52565b610e8f81611f35565b601280546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b610b9b6001600160a01b038316333084612484565b816001600160a01b0316836001600160a01b031603611ec85760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c6572000000000000006044820152606401610a58565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6000611f4160026124d5565b90506000611f56601480546001019081905590565b6040805180820182528281526001600160a01b0386811660208084019182526000868152601582528581208990558881526011909152848120845181559151600190920180546001600160a01b03191692909316919091179091559151929350913391859185917f6438d905327051fd31a6b248bf430b0527939eccc69883f012652c797b39689d91a450505050565b611ff1848484611bc5565b611ffd848484846125e7565b6112665760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a58565b6060600061207c8361273e565b600101905060008167ffffffffffffffff81111561209c5761209c612ed0565b6040519080825280601f01601f1916602001820160405280156120c6576020820181803683370190505b5090508181016020015b600019017f3031323334353637383961626364656600000000000000000000000000000000600a86061a8153600a85049450841561138b576120d0565b6000818152600e602052604090205460ff16151560010361215a576040517f646cf55800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600e6020526040808220805460ff191660011790555182917fc5f5bb097b8b6eedaca84092e68b49ea9018b7d7d6a068cc71c8fba9bda3934c91a250565b6040516001600160a01b038316602482015260448101829052610af99084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152612820565b600c5460009081905b808210156122c2576000600c8381548110612254576122546132d5565b906000526020600020906003020160405180606001604052908160008201548152602001600182015481526020016002820154815250509050806000015185101580156122a5575080602001518511155b156122b65760400151949350505050565b82600101925050612237565b5050919050565b6000848152600f60209081526040808320859055601090915290208390556122f18185612905565b806001600160a01b031683857f8e57532d3d1f4ac4f45fe8626844b6d51ea5c9ef39317d80da0132374ec741428560405161232e91815260200190565b60405180910390a450505050565b61234884848484612a9e565b60018111156123bf5760405162461bcd60e51b815260206004820152603560248201527f455243373231456e756d657261626c653a20636f6e736563757469766520747260448201527f616e7366657273206e6f7420737570706f7274656400000000000000000000006064820152608401610a58565b816001600160a01b03851661241b5761241681600880546000838152600960205260408120829055600182018355919091527ff3f7a9fe364faab93b216da50a3214154f22a0a2b415b23a84c8169e8b636ee30155565b61243e565b836001600160a01b0316856001600160a01b03161461243e5761243e8582612b26565b6001600160a01b03841661245a5761245581612bc3565b61247d565b846001600160a01b0316846001600160a01b03161461247d5761247d8482612c72565b5050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526112669085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016121e2565b6040517f5d3b1d300000000000000000000000000000000000000000000000000000000081527fd729dc84e21ae57ffb6be0053bf2b0668aa2aaf300a2a7b2ddf7dc0bb6e875a8600482015267ffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000003b716602482015260036044820152621e8480606482015263ffffffff821660848201526000907f000000000000000000000000ae975071be8f8ee67addbc1a82488f1c248580676001600160a01b031690635d3b1d309060a4016020604051808303816000875af11580156125c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c59190613561565b60006001600160a01b0384163b1561273357604051630a85bd0160e11b81526001600160a01b0385169063150b7a029061262b9033908990889088906004016135f8565b6020604051808303816000875af1925050508015612666575060408051601f3d908101601f1916820190925261266391810190613634565b60015b612719573d808015612694576040519150601f19603f3d011682016040523d82523d6000602084013e612699565b606091505b5080516000036127115760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e74657200000000000000000000000000006064820152608401610a58565b805181602001fd5b6001600160e01b031916630a85bd0160e11b149050611bbd565b506001949350505050565b6000807a184f03e93ff9f4daa797ed6e38ed64bf6a1f0100000000000000008310612787577a184f03e93ff9f4daa797ed6e38ed64bf6a1f010000000000000000830492506040015b6d04ee2d6d415b85acef810000000083106127b3576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc1000083106127d157662386f26fc10000830492506010015b6305f5e10083106127e9576305f5e100830492506008015b61271083106127fd57612710830492506004015b6064831061280f576064830492506002015b600a83106108c55760010192915050565b6000612875826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612cb69092919063ffffffff16565b805190915015610af957808060200190518101906128939190613340565b610af95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610a58565b6001600160a01b03821661295b5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f20616464726573736044820152606401610a58565b6000818152600260205260409020546001600160a01b0316156129c05760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a58565b6129ce60008383600161233c565b6000818152600260205260409020546001600160a01b031615612a335760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e746564000000006044820152606401610a58565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6001811115611266576001600160a01b03841615612ae4576001600160a01b03841660009081526003602052604081208054839290612ade90849061357a565b90915550505b6001600160a01b03831615611266576001600160a01b03831660009081526003602052604081208054839290612b1b90849061358d565b909155505050505050565b60006001612b3384610fdf565b612b3d919061357a565b600083815260076020526040902054909150808214612b90576001600160a01b03841660009081526006602090815260408083208584528252808320548484528184208190558352600790915290208190555b5060009182526007602090815260408084208490556001600160a01b039094168352600681528383209183525290812055565b600854600090612bd59060019061357a565b60008381526009602052604081205460088054939450909284908110612bfd57612bfd6132d5565b906000526020600020015490508060088381548110612c1e57612c1e6132d5565b6000918252602080832090910192909255828152600990915260408082208490558582528120556008805480612c5657612c56613651565b6001900381819060005260206000200160009055905550505050565b6000612c7d83610fdf565b6001600160a01b039093166000908152600660209081526040808320868452825280832085905593825260079052919091209190915550565b6060611bbd848460008585600080866001600160a01b03168587604051612cdd9190613667565b60006040518083038185875af1925050503d8060008114612d1a576040519150601f19603f3d011682016040523d82523d6000602084013e612d1f565b606091505b5091509150612d3087838387612d3b565b979650505050505050565b60608315612daa578251600003612da3576001600160a01b0385163b612da35760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610a58565b5081611bbd565b611bbd8383815115612dbf5781518083602001fd5b8060405162461bcd60e51b8152600401610a589190612ea4565b6001600160e01b031981168114610e8f57600080fd5b600060208284031215612e0157600080fd5b8135612e0c81612dd9565b9392505050565b6001600160a01b0381168114610e8f57600080fd5b60008060408385031215612e3b57600080fd5b8235612e4681612e13565b946020939093013593505050565b60005b83811015612e6f578181015183820152602001612e57565b50506000910152565b60008151808452612e90816020860160208601612e54565b601f01601f19169290920160200192915050565b602081526000612e0c6020830184612e78565b600060208284031215612ec957600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612f0f57612f0f612ed0565b604052919050565b60008060408385031215612f2a57600080fd5b8235915060208084013567ffffffffffffffff80821115612f4a57600080fd5b818601915086601f830112612f5e57600080fd5b813581811115612f7057612f70612ed0565b8060051b9150612f81848301612ee6565b8181529183018401918481019089841115612f9b57600080fd5b938501935b83851015612fb957843582529385019390850190612fa0565b8096505050505050509250929050565b600080600060608486031215612fde57600080fd5b8335612fe981612e13565b92506020840135612ff981612e13565b929592945050506040919091013590565b60006020828403121561301c57600080fd5b8135612e0c81612e13565b6000806020838503121561303a57600080fd5b823567ffffffffffffffff8082111561305257600080fd5b818501915085601f83011261306657600080fd5b81358181111561307557600080fd5b86602082850101111561308757600080fd5b60209290920196919550909350505050565b8015158114610e8f57600080fd5b600080604083850312156130ba57600080fd5b82356130c581612e13565b915060208301356130d581613099565b809150509250929050565b600080602083850312156130f357600080fd5b823567ffffffffffffffff8082111561310b57600080fd5b818501915085601f83011261311f57600080fd5b81358181111561312e57600080fd5b8660208260051b850101111561308757600080fd5b6020808252825182820181905260009190848201906040850190845b8181101561317b5783518352928401929184019160010161315f565b50909695505050505050565b6000806000806080858703121561319d57600080fd5b84356131a881612e13565b93506020858101356131b981612e13565b935060408601359250606086013567ffffffffffffffff808211156131dd57600080fd5b818801915088601f8301126131f157600080fd5b81358181111561320357613203612ed0565b613215601f8201601f19168501612ee6565b9150808252898482850101111561322b57600080fd5b808484018584013760008482840101525080935050505092959194509250565b6000806040838503121561325e57600080fd5b823561326981612e13565b915060208301356130d581612e13565b6000806040838503121561328c57600080fd5b50508035926020909101359150565b600181811c908216806132af57607f821691505b6020821081036132cf57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176108c5576108c56132eb565b6001600160a01b038416815282602082015260606040820152600061177e6060830184612e78565b60006020828403121561335257600080fd5b8151612e0c81613099565b601f821115610af957600081815260208120601f850160051c810160208610156133845750805b601f850160051c820191505b818110156133a357828155600101613390565b505050505050565b67ffffffffffffffff8311156133c3576133c3612ed0565b6133d7836133d1835461329b565b8361335d565b6000601f84116001811461340b57600085156133f35750838201355b600019600387901b1c1916600186901b17835561247d565b600083815260209020601f19861690835b8281101561343c578685013582556020948501946001909201910161341c565b50868210156134595760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b60008085546134798161329b565b6001828116801561349157600181146134a6576134d5565b60ff19841687528215158302870194506134d5565b8960005260208060002060005b858110156134cc5781548a8201529084019082016134b3565b50505082870194505b50875192506134e8838560208b01612e54565b7f2f00000000000000000000000000000000000000000000000000000000000000939092019283528551916135238382860160208a01612e54565b61355481848601017f2e6a736f6e000000000000000000000000000000000000000000000000000000815260050190565b9998505050505050505050565b60006020828403121561357357600080fd5b5051919050565b818103818111156108c5576108c56132eb565b808201808211156108c5576108c56132eb565b6000826135bd57634e487b7160e01b600052601260045260246000fd5b500690565b815160009082906020808601845b838110156135ec578151855293820193908201906001016135d0565b50929695505050505050565b60006001600160a01b0380871683528086166020840152508360408301526080606083015261362a6080830184612e78565b9695505050505050565b60006020828403121561364657600080fd5b8151612e0c81612dd9565b634e487b7160e01b600052603160045260246000fd5b60008251613679818460208701612e54565b919091019291505056fea2646970667358221220a67ad31eb365dbe7d819ba8b7834c5a4745a95469accbe2570559da4cf9ad58864736f6c63430008150033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000ae975071be8f8ee67addbc1a82488f1c248580670000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f1000000000000000000000000c708d6f2153933daa50b2d0758955be0a93a8fecd729dc84e21ae57ffb6be0053bf2b0668aa2aaf300a2a7b2ddf7dc0bb6e875a800000000000000000000000000000000000000000000000000000000000003b70000000000000000000000000000000000000000000000000000000000000007534352415443480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075343524154434800000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _name (string): SCRATCH
Arg [1] : _symbol (string): SCRATCH
Arg [2] : _vrfCoordinatorV2Address (address): 0xAE975071Be8F8eE67addBC1A82488F1C24858067
Arg [3] : _ticketCost (uint256): 3000000000000000000000
Arg [4] : _linkTokenAddress (address): 0xb0897686c545045aFc77CF20eC7A532E3120E0F1
Arg [5] : _verseTokenAddress (address): 0xc708D6F2153933DAA50B2D0758955Be0A93A8FEc
Arg [6] : _gasKeyHash (bytes32): 0xd729dc84e21ae57ffb6be0053bf2b0668aa2aaf300a2a7b2ddf7dc0bb6e875a8
Arg [7] : _subscriptionId (uint64): 951
-----Encoded View---------------
12 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000100
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000140
Arg [2] : 000000000000000000000000ae975071be8f8ee67addbc1a82488f1c24858067
Arg [3] : 0000000000000000000000000000000000000000000000a2a15d09519be00000
Arg [4] : 000000000000000000000000b0897686c545045afc77cf20ec7a532e3120e0f1
Arg [5] : 000000000000000000000000c708d6f2153933daa50b2d0758955be0a93a8fec
Arg [6] : d729dc84e21ae57ffb6be0053bf2b0668aa2aaf300a2a7b2ddf7dc0bb6e875a8
Arg [7] : 00000000000000000000000000000000000000000000000000000000000003b7
Arg [8] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [9] : 5343524154434800000000000000000000000000000000000000000000000000
Arg [10] : 0000000000000000000000000000000000000000000000000000000000000007
Arg [11] : 5343524154434800000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
97188:5576:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;66747:224;;;;;;:::i;:::-;;:::i;:::-;;;611:14:1;;604:22;586:41;;574:2;559:18;66747:224:0;;;;;;;;92480:39;;;;;;;;812:18:1;800:31;;;782:50;;770:2;755:18;92480:39:0;638:200:1;92185:58:0;;;;;;;;-1:-1:-1;;;;;1041:55:1;;;1023:74;;1011:2;996:18;92185:58:0;843:260:1;95922:322:0;;;;;;:::i;:::-;;:::i;:::-;;50809:100;;;:::i;:::-;;;;;;;:::i;52321:171::-;;;;;;:::i;:::-;;:::i;51839:416::-;;;;;;:::i;:::-;;:::i;74336:53::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;74336:53:0;;;;;;;3292:25:1;;;-1:-1:-1;;;;;3353:55:1;;;3348:2;3333:18;;3326:83;3265:18;74336:53:0;3118:297:1;92882:49:0;;92924:7;92882:49;;;;;3594:10:1;3582:23;;;3564:42;;3552:2;3537:18;92882:49:0;3420:192:1;67387:113:0;67475:10;:17;67387:113;;;3763:25:1;;;3751:2;3736:18;67387:113:0;3617:177:1;86703:261:0;;;;;;:::i;:::-;;:::i;53021:335::-;;;;;;:::i;:::-;;:::i;74195:43::-;;;;;;:::i;:::-;;;;;;;;;;;;;;67055:256;;;;;;:::i;:::-;;:::i;73121:155::-;;;;;;:::i;:::-;;:::i;92674:37::-;;92709:2;92674:37;;53427:185;;;;;;:::i;:::-;;:::i;79481:212::-;;;:::i;92294:35::-;;;;;67577:233;;;;;;:::i;:::-;;:::i;142:29::-;;;;;;:::i;:::-;;:::i;:::-;;;;6212:25:1;;;6268:2;6253:18;;6246:34;;;;6296:18;;;6289:34;6200:2;6185:18;142:29:0;6010:319:1;98189:179:0;;;;;;:::i;:::-;;:::i;78952:18::-;;;;;-1:-1:-1;;;78952:18:0;;;;;;50519:223;;;;;;:::i;:::-;;:::i;97921:146::-;;;:::i;2016:162::-;;;;;;:::i;:::-;;:::i;72861:43::-;;;;;;:::i;:::-;;:::i;50250:207::-;;;;;;:::i;:::-;;:::i;77965:103::-;;;:::i;95117:335::-;;;;;;:::i;:::-;;:::i;93062:27::-;;;;;;92577:36;;;;;74063:29;;;;;;77317:87;77390:6;;-1:-1:-1;;;;;77390:6:0;77317:87;;102611:150;;;;;;:::i;:::-;;:::i;92985:23::-;;;;;;50978:104;;;:::i;52564:155::-;;;;;;:::i;:::-;;:::i;93098:52::-;;;;;;:::i;:::-;;;;;;;;;;;;;;98805:459;;;;;;:::i;:::-;;:::i;79701:214::-;;;:::i;73284:576::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;53683:322::-;;;;;;:::i;:::-;;:::i;75228:561::-;;;;;;:::i;:::-;;:::i;92776:47::-;;92822:1;92776:47;;;;;10451:6:1;10439:19;;;10421:38;;10409:2;10394:18;92776:47:0;10277:188:1;297:47:0;;340:4;297:47;;101930:673;;;;;;:::i;:::-;;:::i;74101:39::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;52790:164;;;;;;:::i;:::-;-1:-1:-1;;;;;52911:25:0;;;52887:4;52911:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;52790:164;96435:648;;;;;;:::i;:::-;;:::i;74147:41::-;;;;;;:::i;:::-;;;;;;;;;;;;;;92378:38;;;;;95460:317;;;;;;:::i;:::-;;:::i;78223:201::-;;;;;;:::i;:::-;;:::i;66747:224::-;66849:4;-1:-1:-1;;;;;;66873:50:0;;66888:35;66873:50;;:90;;;66927:36;66951:11;66927:23;:36::i;:::-;66866:97;66747:224;-1:-1:-1;;66747:224:0:o;95922:322::-;77203:13;:11;:13::i;:::-;96056:90:::1;96082:6;96103:10;96128:7;96056:11;:90::i;:::-;96164:72;::::0;96218:7;;96193:10:::1;::::0;96164:72:::1;::::0;;;::::1;95922:322:::0;;:::o;50809:100::-;50863:13;50896:5;50889:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50809:100;:::o;52321:171::-;52397:7;52417:23;52432:7;52417:14;:23::i;:::-;-1:-1:-1;52460:24:0;;;;:15;:24;;;;;;-1:-1:-1;;;;;52460:24:0;;52321:171::o;51839:416::-;51920:13;51936:23;51951:7;51936:14;:23::i;:::-;51920:39;;51984:5;-1:-1:-1;;;;;51978:11:0;:2;-1:-1:-1;;;;;51978:11:0;;51970:57;;;;-1:-1:-1;;;51970:57:0;;12026:2:1;51970:57:0;;;12008:21:1;12065:2;12045:18;;;12038:30;12104:34;12084:18;;;12077:62;12175:3;12155:18;;;12148:31;12196:19;;51970:57:0;;;;;;;;;48340:10;-1:-1:-1;;;;;52062:21:0;;;;:62;;-1:-1:-1;52087:37:0;52104:5;48340:10;52790:164;:::i;52087:37::-;52040:173;;;;-1:-1:-1;;;52040:173:0;;12428:2:1;52040:173:0;;;12410:21:1;12467:2;12447:18;;;12440:30;12506:34;12486:18;;;12479:62;12577:31;12557:18;;;12550:59;12626:19;;52040:173:0;12226:425:1;52040:173:0;52226:21;52235:2;52239:7;52226:8;:21::i;:::-;51909:346;51839:416;;:::o;86703:261::-;86803:10;-1:-1:-1;;;;;86817:14:0;86803:28;;86799:111;;86849:53;;;;;86875:10;86849:53;;;12891:34:1;-1:-1:-1;;;;;86887:14:0;12961:15:1;12941:18;;;12934:43;12803:18;;86849:53:0;12656:327:1;86799:111:0;86916:42;86935:9;86946:11;86916:18;:42::i;:::-;86703:261;;:::o;53021:335::-;53216:41;48340:10;53249:7;53216:18;:41::i;:::-;53208:99;;;;-1:-1:-1;;;53208:99:0;;13190:2:1;53208:99:0;;;13172:21:1;13229:2;13209:18;;;13202:30;13268:34;13248:18;;;13241:62;-1:-1:-1;;;13319:18:1;;;13312:43;13372:19;;53208:99:0;12988:409:1;53208:99:0;53320:28;53330:4;53336:2;53340:7;53320:9;:28::i;67055:256::-;67152:7;67188:23;67205:5;67188:16;:23::i;:::-;67180:5;:31;67172:87;;;;-1:-1:-1;;;67172:87:0;;13604:2:1;67172:87:0;;;13586:21:1;13643:2;13623:18;;;13616:30;13682:34;13662:18;;;13655:62;13753:13;13733:18;;;13726:41;13784:19;;67172:87:0;13402:407:1;67172:87:0;-1:-1:-1;;;;;;67277:19:0;;;;;;;;:12;:19;;;;;;;;:26;;;;;;;;;67055:256::o;73121:155::-;73222:4;55406:16;;;:7;:16;;;;;;-1:-1:-1;;;;;55406:16:0;55832:31;;73251:17;55743:128;53427:185;53565:39;53582:4;53588:2;53592:7;53565:39;;;;;;;;;;;;:16;:39::i;79481:212::-;77203:13;:11;:13::i;:::-;79254:6:::1;::::0;-1:-1:-1;;;79254:6:0;::::1;;;:14;;79264:4;79254:14:::0;79250:70:::1;;79292:16;;-1:-1:-1::0;;;79292:16:0::1;;;;;;;;;;;79250:70;79582:6:::2;:13:::0;;-1:-1:-1;;;;79582:13:0::2;-1:-1:-1::0;;;79582:13:0::2;::::0;;79613:72:::2;::::0;79634:10:::2;::::0;79613:72:::2;::::0;::::2;::::0;79659:15:::2;3763:25:1::0;;3751:2;3736:18;;3617:177;79613:72:0::2;;;;;;;;79481:212::o:0;67577:233::-;67652:7;67688:30;67475:10;:17;;67387:113;67688:30;67680:5;:38;67672:95;;;;-1:-1:-1;;;67672:95:0;;14016:2:1;67672:95:0;;;13998:21:1;14055:2;14035:18;;;14028:30;14094:34;14074:18;;;14067:62;14165:14;14145:18;;;14138:42;14197:19;;67672:95:0;13814:408:1;67672:95:0;67785:10;67796:5;67785:17;;;;;;;;:::i;:::-;;;;;;;;;67778:24;;67577:233;;;:::o;142:29::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;142:29:0;:::o;98189:179::-;79254:6;;-1:-1:-1;;;79254:6:0;;;;:14;;79264:4;79254:14;79250:70;;79292:16;;-1:-1:-1;;;79292:16:0;;;;;;;;;;;79250:70;98308:52:::1;98340:9;98308:17;:52::i;:::-;98189:179:::0;:::o;50519:223::-;50591:7;55406:16;;;:7;:16;;;;;;-1:-1:-1;;;;;55406:16:0;;50655:56;;;;-1:-1:-1;;;50655:56:0;;14618:2:1;50655:56:0;;;14600:21:1;14657:2;14637:18;;;14630:30;14696:26;14676:18;;;14669:54;14740:18;;50655:56:0;14416:348:1;97921:146:0;79254:6;;-1:-1:-1;;;79254:6:0;;;;:14;;79264:4;79254:14;79250:70;;79292:16;;-1:-1:-1;;;79292:16:0;;;;;;;;;;;79250:70;98006:53:::1;98038:10;98006:17;:53::i;:::-;97921:146::o:0;2016:162::-;2112:7;2144:26;340:4;2144:7;:26;:::i;72861:43::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;50250:207::-;50322:7;-1:-1:-1;;;;;50350:19:0;;50342:73;;;;-1:-1:-1;;;50342:73:0;;15333:2:1;50342:73:0;;;15315:21:1;15372:2;15352:18;;;15345:30;15411:34;15391:18;;;15384:62;15482:11;15462:18;;;15455:39;15511:19;;50342:73:0;15131:405:1;50342:73:0;-1:-1:-1;;;;;;50433:16:0;;;;;:9;:16;;;;;;;50250:207::o;77965:103::-;77203:13;:11;:13::i;:::-;78030:30:::1;78057:1;78030:18;:30::i;95117:335::-:0;95214:73;95240:10;95265:11;95214;:73::i;:::-;95406:27;;;812:18:1;95417:15:0;800:31:1;95406:27:0;;;782:50:1;-1:-1:-1;;;;;95300:10:0;:26;;;;95349:15;;95380:11;;755:18:1;95406:27:0;;;;;;;;;;;;95300:144;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;102611:150::-;77203:13;:11;:13::i;:::-;102732:7:::1;:21;102742:11:::0;;102732:7;:21:::1;:::i;50978:104::-:0;51034:13;51067:7;51060:14;;;;;:::i;52564:155::-;52659:52;48340:10;52692:8;52702;52659:18;:52::i;98805:459::-;77203:13;:11;:13::i;:::-;98926:9:::1;98962:10:::0;92709:2:::1;98996:17:::0;::::1;98992:75;;;99037:18;;;;;;;;;;;;;;98992:75;99091:5;99087:1;:9;99079:178;;;99116:65;99153:10;;99164:1;99153:13;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;99116:18;:65::i;:::-;99227:3;;;;;99079:178;;;98915:349;;98805:459:::0;;:::o;79701:214::-;77203:13;:11;:13::i;:::-;79384:6:::1;::::0;-1:-1:-1;;;79384:6:0;::::1;;;:15;;79394:5;79384:15:::0;79380:74:::1;;79423:19;;;;;;;;;;;;;;79380:74;79801:6:::2;:14:::0;;-1:-1:-1;;;;79801:14:0::2;::::0;;79833:74:::2;::::0;79881:15:::2;3763:25:1::0;;79856:10:0::2;::::0;79833:74:::2;::::0;3751:2:1;3736:18;79833:74:0::2;3617:177:1::0;73284:576:0;73390:16;73424:21;73448:41;73472:6;73448:9;:41::i;:::-;73424:65;;73502:23;73556:13;73528:52;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;73528:52:0;;73502:78;;73593:9;73615:212;73627:13;73623:1;:17;73615:212;;;73672:79;73710:6;73735:1;73672:19;:79::i;:::-;73660:6;73667:1;73660:9;;;;;;;;:::i;:::-;;;;;;;;;;:91;73797:3;;73615:212;;;-1:-1:-1;73846:6:0;73284:576;-1:-1:-1;;;73284:576:0:o;53683:322::-;53857:41;48340:10;53890:7;53857:18;:41::i;:::-;53849:99;;;;-1:-1:-1;;;53849:99:0;;13190:2:1;53849:99:0;;;13172:21:1;13229:2;13209:18;;;13202:30;13268:34;13248:18;;;13241:62;-1:-1:-1;;;13319:18:1;;;13312:43;13372:19;;53849:99:0;12988:409:1;53849:99:0;53959:38;53973:4;53979:2;53983:7;53992:4;53959:13;:38::i;75228:561::-;55808:4;55406:16;;;:7;:16;;;;;;75347:13;;-1:-1:-1;;;;;55406:16:0;55832:31;;75382:27;;75404:5;75382:27;75378:78;;75433:11;;;;;;;;;;;;;;75378:78;75468:23;75494:18;;;:7;:18;;;;;;;;:63;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;75468:89;;75633:7;75659:20;:9;:18;:20::i;:::-;75720:9;75598:172;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;75570:211;;;75228:561;;;:::o;101930:673::-;79254:6;;-1:-1:-1;;;79254:6:0;;;;:14;;79264:4;79254:14;79250:70;;79292:16;;-1:-1:-1;;;79292:16:0;;;;;;;;;;;79250:70;102050:9;73030:10:::1;73009:17;102050:9:::0;73009:7:::1;:17::i;:::-;-1:-1:-1::0;;;;;73009:31:0::1;;72987:106;;;::::0;-1:-1:-1;;;72987:106:0;;20076:2:1;72987:106:0::1;::::0;::::1;20058:21:1::0;20115:2;20095:18;;;20088:30;20154:27;20134:18;;;20127:55;20199:18;;72987:106:0::1;19874:349:1::0;72987:106:0::1;102077:46:::2;102103:9;102077:11;:46::i;:::-;102136:16;102155:41:::0;;;:6:::2;:41;::::0;;;;;;102227:60;;;;;102271:4:::2;102227:60;::::0;::::2;1023:74:1::0;102155:41:0;;102136:16;102227:11:::2;-1:-1:-1::0;;;;;102227:21:0::2;::::0;::::2;::::0;996:18:1;;102227:60:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;102209:78;;102314:8;102304:7;:18;102300:74;;;102346:16;;;;;;;;;;;;;;102300:74;102386:96;102412:11;102438:10;102463:8;102386:11;:96::i;:::-;102500:95;::::0;3763:25:1;;;102551:10:0::2;::::0;102527:9;;102500:95:::2;::::0;3751:2:1;3736:18;102500:95:0::2;;;;;;;102066:537;;79330:1:::1;101930:673:::0;:::o;96435:648::-;96564:7;;96656:11;96604:31;96656:11;-1:-1:-1;;96604:31:0;:::i;:::-;:35;;96638:1;96604:35;:::i;:::-;96603:64;;;;:::i;:::-;96589:78;-1:-1:-1;96697:8:0;96718:288;96760:3;96750:6;:13;96746:59;96784:5;96746:59;96888:72;;;;;;;21269:19:1;;;;96888:72:0;;;;;;;;;21304:12:1;;;96888:72:0;;;96856:123;;;;;96718:288;;;97025:33;97047:11;97025:6;:33;:::i;:::-;:50;;97074:1;97025:50;:::i;:::-;97018:57;96435:648;-1:-1:-1;;;;;96435:648:0:o;95460:317::-;77203:13;:11;:13::i;:::-;95579:12:::1;95595:1;95579:17:::0;95575:70:::1;;95620:13;;-1:-1:-1::0;;;95620:13:0::1;;;;;;;;;;;95575:70;95677:8;;95661:12;:24:::0;95657:77:::1;;95709:13;;-1:-1:-1::0;;;95709:13:0::1;;;;;;;;;;;95657:77;95746:8;:23:::0;95460:317::o;78223:201::-;77203:13;:11;:13::i;:::-;-1:-1:-1;;;;;78312:22:0;::::1;78304:73;;;::::0;-1:-1:-1;;;78304:73:0;;21529:2:1;78304:73:0::1;::::0;::::1;21511:21:1::0;21568:2;21548:18;;;21541:30;21607:34;21587:18;;;21580:62;21678:8;21658:18;;;21651:36;21704:19;;78304:73:0::1;21327:402:1::0;78304:73:0::1;78388:28;78407:8;78388:18;:28::i;49881:305::-:0;49983:4;-1:-1:-1;;;;;;50020:40:0;;50035:25;50020:40;;:105;;-1:-1:-1;;;;;;;50077:48:0;;50092:33;50077:48;50020:105;:158;;;-1:-1:-1;20344:25:0;-1:-1:-1;;;;;;20329:40:0;;;50142:36;20220:157;77482:132;77390:6;;-1:-1:-1;;;;;77390:6:0;48340:10;77546:23;77538:68;;;;-1:-1:-1;;;77538:68:0;;21936:2:1;77538:68:0;;;21918:21:1;;;21955:18;;;21948:30;22014:34;21994:18;;;21987:62;22066:18;;77538:68:0;21734:356:1;47011:224:0;47151:76;-1:-1:-1;;;;;47151:19:0;;47185:9;47209:7;47151:19;:76::i;62140:135::-;55808:4;55406:16;;;:7;:16;;;;;;-1:-1:-1;;;;;55406:16:0;62214:53;;;;-1:-1:-1;;;62214:53:0;;14618:2:1;62214:53:0;;;14600:21:1;14657:2;14637:18;;;14630:30;14696:26;14676:18;;;14669:54;14740:18;;62214:53:0;14416:348:1;61419:174:0;61494:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;61494:29:0;-1:-1:-1;;;;;61494:29:0;;;;;;;;:24;;61548:23;61494:24;61548:14;:23::i;:::-;-1:-1:-1;;;;;61539:46:0;;;;;;;;;;;61419:174;;:::o;100059:879::-;100215:26;100244:54;;;:18;:54;;;;;;;;100215:83;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;100215:83:0;;;;;;;;100357:15;;100215:83;;:26;100335:65;;100357:12;;100215:83;100357:15;;;;;;:::i;:::-;;;;;;;100387:2;100335:7;:65::i;:::-;100311:89;;100413:20;100436:68;100458:12;100471:1;100458:15;;;;;;;;:::i;:::-;;;;;;;100488:5;100436:7;:68::i;:::-;100413:91;;100517:13;100533:51;100561:12;100533:13;:51::i;:::-;100517:67;;100597:22;100622:25;101076:14;101074:16;;;;;;;;;100946:163;100622:25;100597:50;;100660:140;100686:14;100715:13;100743:5;100763:11;:26;;;100660:11;:140::i;:::-;100907:12;100818:112;;;;;;:::i;:::-;;;;;;;;;100849:18;;100818:112;;100882:10;;100849:18;100818:112;;100849:18;;100818:112;100204:734;;;;;100059:879;;:::o;56038:264::-;56131:4;56148:13;56164:23;56179:7;56164:14;:23::i;:::-;56148:39;;56217:5;-1:-1:-1;;;;;56206:16:0;:7;-1:-1:-1;;;;;56206:16:0;;:52;;;-1:-1:-1;;;;;;52911:25:0;;;52887:4;52911:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;56226:32;56206:87;;;;56286:7;-1:-1:-1;;;;;56262:31:0;:20;56274:7;56262:11;:20::i;:::-;-1:-1:-1;;;;;56262:31:0;;56206:87;56198:96;56038:264;-1:-1:-1;;;;56038:264:0:o;60037:1263::-;60196:4;-1:-1:-1;;;;;60169:31:0;:23;60184:7;60169:14;:23::i;:::-;-1:-1:-1;;;;;60169:31:0;;60161:81;;;;-1:-1:-1;;;60161:81:0;;22845:2:1;60161:81:0;;;22827:21:1;22884:2;22864:18;;;22857:30;22923:34;22903:18;;;22896:62;-1:-1:-1;;;22974:18:1;;;22967:35;23019:19;;60161:81:0;22643:401:1;60161:81:0;-1:-1:-1;;;;;60261:16:0;;60253:65;;;;-1:-1:-1;;;60253:65:0;;23251:2:1;60253:65:0;;;23233:21:1;23290:2;23270:18;;;23263:30;23329:34;23309:18;;;23302:62;23400:6;23380:18;;;23373:34;23424:19;;60253:65:0;23049:400:1;60253:65:0;60331:42;60352:4;60358:2;60362:7;60371:1;60331:20;:42::i;:::-;60503:4;-1:-1:-1;;;;;60476:31:0;:23;60491:7;60476:14;:23::i;:::-;-1:-1:-1;;;;;60476:31:0;;60468:81;;;;-1:-1:-1;;;60468:81:0;;22845:2:1;60468:81:0;;;22827:21:1;22884:2;22864:18;;;22857:30;22923:34;22903:18;;;22896:62;-1:-1:-1;;;22974:18:1;;;22967:35;23019:19;;60468:81:0;22643:401:1;60468:81:0;60621:24;;;;:15;:24;;;;;;;;60614:31;;-1:-1:-1;;;;;;60614:31:0;;;;;;-1:-1:-1;;;;;61097:15:0;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;61097:20:0;;;61132:13;;;;;;;;;:18;;60614:31;61132:18;;;61172:16;;;:7;:16;;;;;;:21;;;;;;;;;;61211:27;;60637:7;;61211:27;;;51909:346;51839:416;;:::o;98376:241::-;98472:71;98498:11;98524:8;;98472:11;:71::i;:::-;98556:53;98589:9;98556:18;:53::i;78584:191::-;78677:6;;;-1:-1:-1;;;;;78694:17:0;;;-1:-1:-1;;;;;;78694:17:0;;;;;;;78727:40;;78677:6;;;78694:17;78677:6;;78727:40;;78658:16;;78727:40;78647:128;78584:191;:::o;47345:229::-;47457:109;-1:-1:-1;;;;;47457:23:0;;47495:10;47528:4;47548:7;47457:23;:109::i;61736:315::-;61891:8;-1:-1:-1;;;;;61882:17:0;:5;-1:-1:-1;;;;;61882:17:0;;61874:55;;;;-1:-1:-1;;;61874:55:0;;23656:2:1;61874:55:0;;;23638:21:1;23695:2;23675:18;;;23668:30;23734:27;23714:18;;;23707:55;23779:18;;61874:55:0;23454:349:1;61874:55:0;-1:-1:-1;;;;;61940:25:0;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;61940:46:0;;;;;;;;;;62002:41;;586::1;;;62002::0;;559:18:1;62002:41:0;;;;;;;61736:315;;;:::o;99272:605::-;99369:17;99389:60;99436:1;99389:19;:60::i;:::-;99369:80;;99462:20;99485:23;101245:12;101243:14;;;;;;;;;101117:159;99485:23;99549:95;;;;;;;;;;;-1:-1:-1;;;;;99549:95:0;;;;;;;;;;-1:-1:-1;99657:31:0;;;:17;:31;;;;;:43;;;99711:29;;;:18;:29;;;;;;:42;;;;;;;;;;;;-1:-1:-1;;;;;;99711:42:0;;;;;;;;;;;;99771:98;;99549:95;;-1:-1:-1;99549:95:0;99848:10;;99657:43;;99549:95;;99771:98;;;99358:519;;;99272:605;:::o;54886:313::-;55042:28;55052:4;55058:2;55062:7;55042:9;:28::i;:::-;55089:47;55112:4;55118:2;55122:7;55131:4;55089:22;:47::i;:::-;55081:110;;;;-1:-1:-1;;;55081:110:0;;24010:2:1;55081:110:0;;;23992:21:1;24049:2;24029:18;;;24022:30;24088:34;24068:18;;;24061:62;24159:20;24139:18;;;24132:48;24197:19;;55081:110:0;23808:414:1;15490:716:0;15546:13;15597:14;15614:17;15625:5;15614:10;:17::i;:::-;15634:1;15614:21;15597:38;;15650:20;15684:6;15673:18;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;15673:18:0;-1:-1:-1;15650:41:0;-1:-1:-1;15815:28:0;;;15831:2;15815:28;15872:288;-1:-1:-1;;15904:5:0;16046:8;16041:2;16030:14;;16025:30;15904:5;16012:44;16102:2;16093:11;;;-1:-1:-1;16123:21:0;;16139:5;16123:21;15872:288;;75797:280;75891:18;;;;:7;:18;;;;;;;;:26;;:18;:26;75887:82;;75941:16;;;;;;;;;;;;;;75887:82;75981:18;;;;:7;:18;;;;;;:25;;-1:-1:-1;;75981:25:0;76002:4;75981:25;;;76024:45;75989:9;;76024:45;;;75797:280;:::o;42767:211::-;42911:58;;-1:-1:-1;;;;;24419:55:1;;42911:58:0;;;24401:74:1;24491:18;;;24484:34;;;42884:86:0;;42904:5;;42934:23;;24374:18:1;;42911:58:0;;;;-1:-1:-1;;42911:58:0;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;42911:58:0;;;;;;;;;;42884:19;:86::i;101284:516::-;101457:10;:17;101390:13;;;;101487:306;101499:5;101495:1;:9;101487:306;;;101524:19;101546:10;101557:1;101546:13;;;;;;;;:::i;:::-;;;;;;;;;;;101524:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;101591:2;:12;;;101580:7;:23;;:50;;;;;101618:2;:12;;;101607:7;:23;;101580:50;101576:142;;;101659:12;;;;101284:516;-1:-1:-1;;;;101284:516:0:o;101576:142::-;101763:3;;;;;101507:286;101487:306;;;101410:390;;101284:516;;;:::o;74758:462::-;74930:17;;;;:6;:17;;;;;;;;:26;;;74967:8;:19;;;;;:32;;;75012:64;75032:9;74937;75012:5;:64::i;:::-;75171:9;-1:-1:-1;;;;;75094:118:0;75146:10;75122:9;75094:118;75195:6;75094:118;;;;3763:25:1;;3751:2;3736:18;;3617:177;75094:118:0;;;;;;;;74758:462;;;;:::o;67884:915::-;68061:61;68088:4;68094:2;68098:12;68112:9;68061:26;:61::i;:::-;68151:1;68139:9;:13;68135:222;;;68282:63;;-1:-1:-1;;;68282:63:0;;24731:2:1;68282:63:0;;;24713:21:1;24770:2;24750:18;;;24743:30;24809:34;24789:18;;;24782:62;24880:23;24860:18;;;24853:51;24921:19;;68282:63:0;24529:417:1;68135:222:0;68387:12;-1:-1:-1;;;;;68416:18:0;;68412:187;;68451:40;68483:7;69626:10;:17;;69599:24;;;;:15;:24;;;;;:44;;;69654:24;;;;;;;;;;;;69522:164;68451:40;68412:187;;;68521:2;-1:-1:-1;;;;;68513:10:0;:4;-1:-1:-1;;;;;68513:10:0;;68509:90;;68540:47;68573:4;68579:7;68540:32;:47::i;:::-;-1:-1:-1;;;;;68613:16:0;;68609:183;;68646:45;68683:7;68646:36;:45::i;:::-;68609:183;;;68719:4;-1:-1:-1;;;;;68713:10:0;:2;-1:-1:-1;;;;;68713:10:0;;68709:83;;68740:40;68768:2;68772:7;68740:27;:40::i;:::-;68050:749;67884:915;;;;:::o;42986:248::-;43157:68;;-1:-1:-1;;;;;25232:15:1;;;43157:68:0;;;25214:34:1;25284:15;;25264:18;;;25257:43;25316:18;;;25309:34;;;43130:96:0;;43150:5;;43180:27;;25126:18:1;;43157:68:0;24951:398:1;94562:347:0;94709:192;;;;;94758:11;94709:192;;;25605:25:1;25678:18;94784:15:0;25666:31:1;25646:18;;;25639:59;92822:1:0;25714:18:1;;;25707:47;92924:7:0;25799:18:1;;;25792:43;25773:10;25872:15;;25851:19;;;25844:44;94662:17:0;;94709:15;-1:-1:-1;;;;;94709:34:0;;;;25577:19:1;;94709:192:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;62839:853::-;62993:4;-1:-1:-1;;;;;63014:13:0;;28909:19;:23;63010:675;;63050:71;;-1:-1:-1;;;63050:71:0;;-1:-1:-1;;;;;63050:36:0;;;;;:71;;48340:10;;63101:4;;63107:7;;63116:4;;63050:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;63050:71:0;;;;;;;;-1:-1:-1;;63050:71:0;;;;;;;;;;;;:::i;:::-;;;63046:584;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;63291:6;:13;63308:1;63291:18;63287:328;;63334:60;;-1:-1:-1;;;63334:60:0;;24010:2:1;63334:60:0;;;23992:21:1;24049:2;24029:18;;;24022:30;24088:34;24068:18;;;24061:62;24159:20;24139:18;;;24132:48;24197:19;;63334:60:0;23808:414:1;63287:328:0;63565:6;63559:13;63550:6;63546:2;63542:15;63535:38;63046:584;-1:-1:-1;;;;;;63172:51:0;-1:-1:-1;;;63172:51:0;;-1:-1:-1;63165:58:0;;63010:675;-1:-1:-1;63669:4:0;62839:853;;;;;;:::o;12356:922::-;12409:7;;12496:6;12487:15;;12483:102;;12532:6;12523:15;;;-1:-1:-1;12567:2:0;12557:12;12483:102;12612:6;12603:5;:15;12599:102;;12648:6;12639:15;;;-1:-1:-1;12683:2:0;12673:12;12599:102;12728:6;12719:5;:15;12715:102;;12764:6;12755:15;;;-1:-1:-1;12799:2:0;12789:12;12715:102;12844:5;12835;:14;12831:99;;12879:5;12870:14;;;-1:-1:-1;12913:1:0;12903:11;12831:99;12957:5;12948;:14;12944:99;;12992:5;12983:14;;;-1:-1:-1;13026:1:0;13016:11;12944:99;13070:5;13061;:14;13057:99;;13105:5;13096:14;;;-1:-1:-1;13139:1:0;13129:11;13057:99;13183:5;13174;:14;13170:66;;13219:1;13209:11;13264:6;12356:922;-1:-1:-1;;12356:922:0:o;45834:716::-;46258:23;46284:69;46312:4;46284:69;;;;;;;;;;;;;;;;;46292:5;-1:-1:-1;;;;;46284:27:0;;;:69;;;;;:::i;:::-;46368:17;;46258:95;;-1:-1:-1;46368:21:0;46364:179;;46465:10;46454:30;;;;;;;;;;;;:::i;:::-;46446:85;;;;-1:-1:-1;;;46446:85:0;;26872:2:1;46446:85:0;;;26854:21:1;26911:2;26891:18;;;26884:30;26950:34;26930:18;;;26923:62;27021:12;27001:18;;;26994:40;27051:19;;46446:85:0;26670:406:1;57636:942:0;-1:-1:-1;;;;;57716:16:0;;57708:61;;;;-1:-1:-1;;;57708:61:0;;27283:2:1;57708:61:0;;;27265:21:1;;;27302:18;;;27295:30;27361:34;27341:18;;;27334:62;27413:18;;57708:61:0;27081:356:1;57708:61:0;55808:4;55406:16;;;:7;:16;;;;;;-1:-1:-1;;;;;55406:16:0;55832:31;57780:58;;;;-1:-1:-1;;;57780:58:0;;27644:2:1;57780:58:0;;;27626:21:1;27683:2;27663:18;;;27656:30;27722;27702:18;;;27695:58;27770:18;;57780:58:0;27442:352:1;57780:58:0;57851:48;57880:1;57884:2;57888:7;57897:1;57851:20;:48::i;:::-;55808:4;55406:16;;;:7;:16;;;;;;-1:-1:-1;;;;;55406:16:0;55832:31;57989:58;;;;-1:-1:-1;;;57989:58:0;;27644:2:1;57989:58:0;;;27626:21:1;27683:2;27663:18;;;27656:30;27722;27702:18;;;27695:58;27770:18;;57989:58:0;27442:352:1;57989:58:0;-1:-1:-1;;;;;58396:13:0;;;;;;:9;:13;;;;;;;;:18;;58413:1;58396:18;;;58438:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;58438:21:0;;;;;58477:33;58446:7;;58396:13;;58477:33;;58396:13;;58477:33;86703:261;;:::o;64424:410::-;64614:1;64602:9;:13;64598:229;;;-1:-1:-1;;;;;64636:18:0;;;64632:87;;-1:-1:-1;;;;;64675:15:0;;;;;;:9;:15;;;;;:28;;64694:9;;64675:15;:28;;64694:9;;64675:28;:::i;:::-;;;;-1:-1:-1;;64632:87:0;-1:-1:-1;;;;;64737:16:0;;;64733:83;;-1:-1:-1;;;;;64774:13:0;;;;;;:9;:13;;;;;:26;;64791:9;;64774:13;:26;;64791:9;;64774:26;:::i;:::-;;;;-1:-1:-1;;64424:410:0;;;;:::o;70313:988::-;70579:22;70629:1;70604:22;70621:4;70604:16;:22::i;:::-;:26;;;;:::i;:::-;70641:18;70662:26;;;:17;:26;;;;;;70579:51;;-1:-1:-1;70795:28:0;;;70791:328;;-1:-1:-1;;;;;70862:18:0;;70840:19;70862:18;;;:12;:18;;;;;;;;:34;;;;;;;;;70913:30;;;;;;:44;;;71030:30;;:17;:30;;;;;:43;;;70791:328;-1:-1:-1;71215:26:0;;;;:17;:26;;;;;;;;71208:33;;;-1:-1:-1;;;;;71259:18:0;;;;;:12;:18;;;;;:34;;;;;;;71252:41;70313:988::o;71596:1079::-;71874:10;:17;71849:22;;71874:21;;71894:1;;71874:21;:::i;:::-;71906:18;71927:24;;;:15;:24;;;;;;72300:10;:26;;71849:46;;-1:-1:-1;71927:24:0;;71849:46;;72300:26;;;;;;:::i;:::-;;;;;;;;;72278:48;;72364:11;72339:10;72350;72339:22;;;;;;;;:::i;:::-;;;;;;;;;;;;:36;;;;72444:28;;;:15;:28;;;;;;;:41;;;72616:24;;;;;72609:31;72651:10;:16;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;71667:1008;;;71596:1079;:::o;69100:221::-;69185:14;69202:20;69219:2;69202:16;:20::i;:::-;-1:-1:-1;;;;;69233:16:0;;;;;;;:12;:16;;;;;;;;:24;;;;;;;;:34;;;69278:26;;;:17;:26;;;;;;:35;;;;-1:-1:-1;69100:221:0:o;31371:229::-;31508:12;31540:52;31562:6;31570:4;31576:1;31579:12;31508;32779;32793:23;32820:6;-1:-1:-1;;;;;32820:11:0;32839:5;32846:4;32820:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32778:73;;;;32869:69;32896:6;32904:7;32913:10;32925:12;32869:26;:69::i;:::-;32862:76;32491:455;-1:-1:-1;;;;;;;32491:455:0:o;35064:644::-;35249:12;35278:7;35274:427;;;35306:10;:17;35327:1;35306:22;35302:290;;-1:-1:-1;;;;;28909:19:0;;;35516:60;;;;-1:-1:-1;;;35516:60:0;;28889:2:1;35516:60:0;;;28871:21:1;28928:2;28908:18;;;28901:30;28967:31;28947:18;;;28940:59;29016:18;;35516:60:0;28687:353:1;35516:60:0;-1:-1:-1;35613:10:0;35606:17;;35274:427;35656:33;35664:10;35676:12;36411:17;;:21;36407:388;;36643:10;36637:17;36700:15;36687:10;36683:2;36679:19;36672:44;36407:388;36770:12;36763:20;;-1:-1:-1;;;36763:20:0;;;;;;;;:::i;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;:::-;430:5;196:245;-1:-1:-1;;;196:245:1:o;1108:162::-;-1:-1:-1;;;;;1195:5:1;1191:54;1184:5;1181:65;1171:93;;1260:1;1257;1250:12;1275:338;1358:6;1366;1419:2;1407:9;1398:7;1394:23;1390:32;1387:52;;;1435:1;1432;1425:12;1387:52;1474:9;1461:23;1493:39;1526:5;1493:39;:::i;:::-;1551:5;1603:2;1588:18;;;;1575:32;;-1:-1:-1;;;1275:338:1:o;1618:250::-;1703:1;1713:113;1727:6;1724:1;1721:13;1713:113;;;1803:11;;;1797:18;1784:11;;;1777:39;1749:2;1742:10;1713:113;;;-1:-1:-1;;1860:1:1;1842:16;;1835:27;1618:250::o;1873:271::-;1915:3;1953:5;1947:12;1980:6;1975:3;1968:19;1996:76;2065:6;2058:4;2053:3;2049:14;2042:4;2035:5;2031:16;1996:76;:::i;:::-;2126:2;2105:15;-1:-1:-1;;2101:29:1;2092:39;;;;2133:4;2088:50;;1873:271;-1:-1:-1;;1873:271:1:o;2149:220::-;2298:2;2287:9;2280:21;2261:4;2318:45;2359:2;2348:9;2344:18;2336:6;2318:45;:::i;2374:180::-;2433:6;2486:2;2474:9;2465:7;2461:23;2457:32;2454:52;;;2502:1;2499;2492:12;2454:52;-1:-1:-1;2525:23:1;;2374:180;-1:-1:-1;2374:180:1:o;3799:184::-;-1:-1:-1;;;3848:1:1;3841:88;3948:4;3945:1;3938:15;3972:4;3969:1;3962:15;3988:275;4059:2;4053:9;4124:2;4105:13;;-1:-1:-1;;4101:27:1;4089:40;;4159:18;4144:34;;4180:22;;;4141:62;4138:88;;;4206:18;;:::i;:::-;4242:2;4235:22;3988:275;;-1:-1:-1;3988:275:1:o;4268:1014::-;4361:6;4369;4422:2;4410:9;4401:7;4397:23;4393:32;4390:52;;;4438:1;4435;4428:12;4390:52;4474:9;4461:23;4451:33;;4503:2;4556;4545:9;4541:18;4528:32;4579:18;4620:2;4612:6;4609:14;4606:34;;;4636:1;4633;4626:12;4606:34;4674:6;4663:9;4659:22;4649:32;;4719:7;4712:4;4708:2;4704:13;4700:27;4690:55;;4741:1;4738;4731:12;4690:55;4777:2;4764:16;4799:2;4795;4792:10;4789:36;;;4805:18;;:::i;:::-;4851:2;4848:1;4844:10;4834:20;;4874:28;4898:2;4894;4890:11;4874:28;:::i;:::-;4936:15;;;5006:11;;;5002:20;;;4967:12;;;;5034:19;;;5031:39;;;5066:1;5063;5056:12;5031:39;5090:11;;;;5110:142;5126:6;5121:3;5118:15;5110:142;;;5192:17;;5180:30;;5143:12;;;;5230;;;;5110:142;;;5271:5;5261:15;;;;;;;;4268:1014;;;;;:::o;5287:472::-;5364:6;5372;5380;5433:2;5421:9;5412:7;5408:23;5404:32;5401:52;;;5449:1;5446;5439:12;5401:52;5488:9;5475:23;5507:39;5540:5;5507:39;:::i;:::-;5565:5;-1:-1:-1;5622:2:1;5607:18;;5594:32;5635:41;5594:32;5635:41;:::i;:::-;5287:472;;5695:7;;-1:-1:-1;;;5749:2:1;5734:18;;;;5721:32;;5287:472::o;6334:255::-;6393:6;6446:2;6434:9;6425:7;6421:23;6417:32;6414:52;;;6462:1;6459;6452:12;6414:52;6501:9;6488:23;6520:39;6553:5;6520:39;:::i;6776:592::-;6847:6;6855;6908:2;6896:9;6887:7;6883:23;6879:32;6876:52;;;6924:1;6921;6914:12;6876:52;6964:9;6951:23;6993:18;7034:2;7026:6;7023:14;7020:34;;;7050:1;7047;7040:12;7020:34;7088:6;7077:9;7073:22;7063:32;;7133:7;7126:4;7122:2;7118:13;7114:27;7104:55;;7155:1;7152;7145:12;7104:55;7195:2;7182:16;7221:2;7213:6;7210:14;7207:34;;;7237:1;7234;7227:12;7207:34;7282:7;7277:2;7268:6;7264:2;7260:15;7256:24;7253:37;7250:57;;;7303:1;7300;7293:12;7250:57;7334:2;7326:11;;;;;7356:6;;-1:-1:-1;6776:592:1;;-1:-1:-1;;;;6776:592:1:o;7373:118::-;7459:5;7452:13;7445:21;7438:5;7435:32;7425:60;;7481:1;7478;7471:12;7496:390;7561:6;7569;7622:2;7610:9;7601:7;7597:23;7593:32;7590:52;;;7638:1;7635;7628:12;7590:52;7677:9;7664:23;7696:39;7729:5;7696:39;:::i;:::-;7754:5;-1:-1:-1;7811:2:1;7796:18;;7783:32;7824:30;7783:32;7824:30;:::i;:::-;7873:7;7863:17;;;7496:390;;;;;:::o;7891:615::-;7977:6;7985;8038:2;8026:9;8017:7;8013:23;8009:32;8006:52;;;8054:1;8051;8044:12;8006:52;8094:9;8081:23;8123:18;8164:2;8156:6;8153:14;8150:34;;;8180:1;8177;8170:12;8150:34;8218:6;8207:9;8203:22;8193:32;;8263:7;8256:4;8252:2;8248:13;8244:27;8234:55;;8285:1;8282;8275:12;8234:55;8325:2;8312:16;8351:2;8343:6;8340:14;8337:34;;;8367:1;8364;8357:12;8337:34;8420:7;8415:2;8405:6;8402:1;8398:14;8394:2;8390:23;8386:32;8383:45;8380:65;;;8441:1;8438;8431:12;8511:632;8682:2;8734:21;;;8804:13;;8707:18;;;8826:22;;;8653:4;;8682:2;8905:15;;;;8879:2;8864:18;;;8653:4;8948:169;8962:6;8959:1;8956:13;8948:169;;;9023:13;;9011:26;;9092:15;;;;9057:12;;;;8984:1;8977:9;8948:169;;;-1:-1:-1;9134:3:1;;8511:632;-1:-1:-1;;;;;;8511:632:1:o;9148:1124::-;9243:6;9251;9259;9267;9320:3;9308:9;9299:7;9295:23;9291:33;9288:53;;;9337:1;9334;9327:12;9288:53;9376:9;9363:23;9395:39;9428:5;9395:39;:::i;:::-;9453:5;-1:-1:-1;9477:2:1;9516:18;;;9503:32;9544:41;9503:32;9544:41;:::i;:::-;9604:7;-1:-1:-1;9658:2:1;9643:18;;9630:32;;-1:-1:-1;9713:2:1;9698:18;;9685:32;9736:18;9766:14;;;9763:34;;;9793:1;9790;9783:12;9763:34;9831:6;9820:9;9816:22;9806:32;;9876:7;9869:4;9865:2;9861:13;9857:27;9847:55;;9898:1;9895;9888:12;9847:55;9934:2;9921:16;9956:2;9952;9949:10;9946:36;;;9962:18;;:::i;:::-;10004:53;10047:2;10028:13;;-1:-1:-1;;10024:27:1;10020:36;;10004:53;:::i;:::-;9991:66;;10080:2;10073:5;10066:17;10120:7;10115:2;10110;10106;10102:11;10098:20;10095:33;10092:53;;;10141:1;10138;10131:12;10092:53;10196:2;10191;10187;10183:11;10178:2;10171:5;10167:14;10154:45;10240:1;10235:2;10230;10223:5;10219:14;10215:23;10208:34;;10261:5;10251:15;;;;;9148:1124;;;;;;;:::o;10470:404::-;10538:6;10546;10599:2;10587:9;10578:7;10574:23;10570:32;10567:52;;;10615:1;10612;10605:12;10567:52;10654:9;10641:23;10673:39;10706:5;10673:39;:::i;:::-;10731:5;-1:-1:-1;10788:2:1;10773:18;;10760:32;10801:41;10760:32;10801:41;:::i;10879:248::-;10947:6;10955;11008:2;10996:9;10987:7;10983:23;10979:32;10976:52;;;11024:1;11021;11014:12;10976:52;-1:-1:-1;;11047:23:1;;;11117:2;11102:18;;;11089:32;;-1:-1:-1;10879:248:1:o;11382:437::-;11461:1;11457:12;;;;11504;;;11525:61;;11579:4;11571:6;11567:17;11557:27;;11525:61;11632:2;11624:6;11621:14;11601:18;11598:38;11595:218;;-1:-1:-1;;;11666:1:1;11659:88;11770:4;11767:1;11760:15;11798:4;11795:1;11788:15;11595:218;;11382:437;;;:::o;14227:184::-;-1:-1:-1;;;14276:1:1;14269:88;14376:4;14373:1;14366:15;14400:4;14397:1;14390:15;14769:184;-1:-1:-1;;;14818:1:1;14811:88;14918:4;14915:1;14908:15;14942:4;14939:1;14932:15;14958:168;15031:9;;;15062;;15079:15;;;15073:22;;15059:37;15049:71;;15100:18;;:::i;15541:409::-;-1:-1:-1;;;;;15748:6:1;15744:55;15733:9;15726:74;15836:6;15831:2;15820:9;15816:18;15809:34;15879:2;15874;15863:9;15859:18;15852:30;15707:4;15899:45;15940:2;15929:9;15925:18;15917:6;15899:45;:::i;15955:245::-;16022:6;16075:2;16063:9;16054:7;16050:23;16046:32;16043:52;;;16091:1;16088;16081:12;16043:52;16123:9;16117:16;16142:28;16164:5;16142:28;:::i;16331:545::-;16433:2;16428:3;16425:11;16422:448;;;16469:1;16494:5;16490:2;16483:17;16539:4;16535:2;16525:19;16609:2;16597:10;16593:19;16590:1;16586:27;16580:4;16576:38;16645:4;16633:10;16630:20;16627:47;;;-1:-1:-1;16668:4:1;16627:47;16723:2;16718:3;16714:12;16711:1;16707:20;16701:4;16697:31;16687:41;;16778:82;16796:2;16789:5;16786:13;16778:82;;;16841:17;;;16822:1;16811:13;16778:82;;;16782:3;;;16331:545;;;:::o;17052:1206::-;17176:18;17171:3;17168:27;17165:53;;;17198:18;;:::i;:::-;17227:94;17317:3;17277:38;17309:4;17303:11;17277:38;:::i;:::-;17271:4;17227:94;:::i;:::-;17347:1;17372:2;17367:3;17364:11;17389:1;17384:616;;;;18044:1;18061:3;18058:93;;;-1:-1:-1;18117:19:1;;;18104:33;18058:93;-1:-1:-1;;17009:1:1;17005:11;;;17001:24;16997:29;16987:40;17033:1;17029:11;;;16984:57;18164:78;;17357:895;;17384:616;16278:1;16271:14;;;16315:4;16302:18;;-1:-1:-1;;17420:17:1;;;17521:9;17543:229;17557:7;17554:1;17551:14;17543:229;;;17646:19;;;17633:33;17618:49;;17753:4;17738:20;;;;17706:1;17694:14;;;;17573:12;17543:229;;;17547:3;17800;17791:7;17788:16;17785:159;;;17924:1;17920:6;17914:3;17908;17905:1;17901:11;17897:21;17893:34;17889:39;17876:9;17871:3;17867:19;17854:33;17850:79;17842:6;17835:95;17785:159;;;17987:1;17981:3;17978:1;17974:11;17970:19;17964:4;17957:33;17357:895;;17052:1206;;;:::o;18381:1488::-;18807:3;18836:1;18869:6;18863:13;18899:36;18925:9;18899:36;:::i;:::-;18954:1;18971:18;;;18998:133;;;;19145:1;19140:356;;;;18964:532;;18998:133;-1:-1:-1;;19031:24:1;;19019:37;;19104:14;;19097:22;19085:35;;19076:45;;;-1:-1:-1;18998:133:1;;19140:356;19171:6;19168:1;19161:17;19201:4;19246:2;19243:1;19233:16;19271:1;19285:165;19299:6;19296:1;19293:13;19285:165;;;19377:14;;19364:11;;;19357:35;19420:16;;;;19314:10;;19285:165;;;19289:3;;;19479:6;19474:3;19470:16;19463:23;;18964:532;;19527:6;19521:13;19505:29;;19543:68;19602:8;19597:3;19590:4;19582:6;19578:17;19543:68;:::i;:::-;19668:3;19630:18;;;;19657:15;;;19697:13;;;19719:76;19697:13;19773:11;;;19766:4;19754:17;;19719:76;:::i;:::-;19811:52;19859:2;19848:8;19844:2;19840:17;19836:26;18335:7;18323:20;;18368:1;18359:11;;18263:113;19811:52;19804:59;18381:1488;-1:-1:-1;;;;;;;;;18381:1488:1:o;20228:184::-;20298:6;20351:2;20339:9;20330:7;20326:23;20322:32;20319:52;;;20367:1;20364;20357:12;20319:52;-1:-1:-1;20390:16:1;;20228:184;-1:-1:-1;20228:184:1:o;20417:128::-;20484:9;;;20505:11;;;20502:37;;;20519:18;;:::i;20550:125::-;20615:9;;;20636:10;;;20633:36;;;20649:18;;:::i;20869:266::-;20901:1;20927;20917:189;;-1:-1:-1;;;20959:1:1;20952:88;21063:4;21060:1;21053:15;21091:4;21088:1;21081:15;20917:189;-1:-1:-1;21120:9:1;;20869:266::o;22095:543::-;22313:13;;22256:3;;22287;;22366:4;22393:15;;;22256:3;22436:175;22450:6;22447:1;22444:13;22436:175;;;22513:13;;22499:28;;22549:14;;;;22586:15;;;;22472:1;22465:9;22436:175;;;-1:-1:-1;22627:5:1;;22095:543;-1:-1:-1;;;;;;22095:543:1:o;25899:512::-;26093:4;-1:-1:-1;;;;;26203:2:1;26195:6;26191:15;26180:9;26173:34;26255:2;26247:6;26243:15;26238:2;26227:9;26223:18;26216:43;;26295:6;26290:2;26279:9;26275:18;26268:34;26338:3;26333:2;26322:9;26318:18;26311:31;26359:46;26400:3;26389:9;26385:19;26377:6;26359:46;:::i;:::-;26351:54;25899:512;-1:-1:-1;;;;;;25899:512:1:o;26416:249::-;26485:6;26538:2;26526:9;26517:7;26513:23;26509:32;26506:52;;;26554:1;26551;26544:12;26506:52;26586:9;26580:16;26605:30;26629:5;26605:30;:::i;27799:184::-;-1:-1:-1;;;27848:1:1;27841:88;27948:4;27945:1;27938:15;27972:4;27969:1;27962:15;28395:287;28524:3;28562:6;28556:13;28578:66;28637:6;28632:3;28625:4;28617:6;28613:17;28578:66;:::i;:::-;28660:16;;;;;28395:287;-1:-1:-1;;28395:287:1:o
Swarm Source
ipfs://a67ad31eb365dbe7d819ba8b7834c5a4745a95469accbe2570559da4cf9ad588
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
POL | 100.00% | $0.000064 | 3,548,900 | $226.06 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.