creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface VRFCoordinatorV2Interface {\n  /**\n   * @notice Get configuration relevant for making requests\n   * @return minimumRequestConfirmations global min for request confirmations\n   * @return maxGasLimit global max for request gas limit\n   * @return s_provingKeyHashes list of registered key hashes\n   */\n  function getRequestConfig() external view returns (uint16, uint32, bytes32[] memory);\n\n  /**\n   * @notice Request a set of random words.\n   * @param keyHash - Corresponds to a particular oracle job which uses\n   * that key for generating the VRF proof. Different keyHash's have different gas price\n   * ceilings, so you can select a specific one to bound your maximum per request cost.\n   * @param subId  - The ID of the VRF subscription. Must be funded\n   * with the minimum subscription balance required for the selected keyHash.\n   * @param minimumRequestConfirmations - How many blocks you'd like the\n   * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS\n   * for why you may want to request more. The acceptable range is\n   * [minimumRequestBlockConfirmations, 200].\n   * @param callbackGasLimit - How much gas you'd like to receive in your\n   * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords\n   * may be slightly less than this amount because of gas used calling the function\n   * (argument decoding etc.), so you may need to request slightly more than you expect\n   * to have inside fulfillRandomWords. The acceptable range is\n   * [0, maxGasLimit]\n   * @param numWords - The number of uint256 random values you'd like to receive\n   * in your fulfillRandomWords callback. Note these numbers are expanded in a\n   * secure way by the VRFCoordinator from a single random value supplied by the oracle.\n   * @return requestId - A unique identifier of the request. Can be used to match\n   * a request to a response in fulfillRandomWords.\n   */\n  function requestRandomWords(\n    bytes32 keyHash,\n    uint64 subId,\n    uint16 minimumRequestConfirmations,\n    uint32 callbackGasLimit,\n    uint32 numWords\n  ) external returns (uint256 requestId);\n\n  /**\n   * @notice Create a VRF subscription.\n   * @return subId - A unique subscription id.\n   * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer.\n   * @dev Note to fund the subscription, use transferAndCall. For example\n   * @dev  LINKTOKEN.transferAndCall(\n   * @dev    address(COORDINATOR),\n   * @dev    amount,\n   * @dev    abi.encode(subId));\n   */\n  function createSubscription() external returns (uint64 subId);\n\n  /**\n   * @notice Get a VRF subscription.\n   * @param subId - ID of the subscription\n   * @return balance - LINK balance of the subscription in juels.\n   * @return reqCount - number of requests for this subscription, determines fee tier.\n   * @return owner - owner of the subscription.\n   * @return consumers - list of consumer address which are able to use this subscription.\n   */\n  function getSubscription(\n    uint64 subId\n  ) external view returns (uint96 balance, uint64 reqCount, address owner, address[] memory consumers);\n\n  /**\n   * @notice Request subscription owner transfer.\n   * @param subId - ID of the subscription\n   * @param newOwner - proposed new owner of the subscription\n   */\n  function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external;\n\n  /**\n   * @notice Request subscription owner transfer.\n   * @param subId - ID of the subscription\n   * @dev will revert if original owner of subId has\n   * not requested that msg.sender become the new owner.\n   */\n  function acceptSubscriptionOwnerTransfer(uint64 subId) external;\n\n  /**\n   * @notice Add a consumer to a VRF subscription.\n   * @param subId - ID of the subscription\n   * @param consumer - New consumer which can use the subscription\n   */\n  function addConsumer(uint64 subId, address consumer) external;\n\n  /**\n   * @notice Remove a consumer from a VRF subscription.\n   * @param subId - ID of the subscription\n   * @param consumer - Consumer to remove from the subscription\n   */\n  function removeConsumer(uint64 subId, address consumer) external;\n\n  /**\n   * @notice Cancel a subscription\n   * @param subId - ID of the subscription\n   * @param to - Where to send the remaining LINK to\n   */\n  function cancelSubscription(uint64 subId, address to) external;\n\n  /*\n   * @notice Check to see if there exists a request commitment consumers\n   * for all consumers and keyhashes for a given sub.\n   * @param subId - ID of the subscription\n   * @return true if there exists at least one unfulfilled request for the subscription, false\n   * otherwise.\n   */\n  function pendingRequestExists(uint64 subId) external view returns (bool);\n}\n"
      },
      "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```solidity\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping(bytes32 => uint256) _indexes;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._indexes[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) {\n            // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            if (lastIndex != toDeleteIndex) {\n                bytes32 lastValue = set._values[lastIndex];\n\n                // Move the last value to the index where the value to delete is\n                set._values[toDeleteIndex] = lastValue;\n                // Update the index for the moved value\n                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n            }\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        return set._values[index];\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function _values(Set storage set) private view returns (bytes32[] memory) {\n        return set._values;\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        bytes32[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(uint160(value))));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint160(uint256(_at(set._inner, index))));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(AddressSet storage set) internal view returns (address[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        address[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n    /**\n     * @dev Returns the value stored at position `index` in the set. O(1).\n     *\n     * Note that there are no guarantees on the ordering of values inside the\n     * array, and it may change when more values are added or removed.\n     *\n     * Requirements:\n     *\n     * - `index` must be strictly less than {length}.\n     */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n\n    /**\n     * @dev Return the entire set in an array\n     *\n     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n     * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n     */\n    function values(UintSet storage set) internal view returns (uint256[] memory) {\n        bytes32[] memory store = _values(set._inner);\n        uint256[] memory result;\n\n        /// @solidity memory-safe-assembly\n        assembly {\n            result := store\n        }\n\n        return result;\n    }\n}\n"
      },
      "@pythnetwork/entropy-sdk-solidity/EntropyEvents.sol": {
        "content": "// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport \"./EntropyStructs.sol\";\n\ninterface EntropyEvents {\n    event Registered(EntropyStructs.ProviderInfo provider);\n\n    event Requested(EntropyStructs.Request request);\n\n    event Revealed(\n        EntropyStructs.Request request,\n        bytes32 userRevelation,\n        bytes32 providerRevelation,\n        bytes32 blockHash,\n        bytes32 randomNumber\n    );\n}\n"
      },
      "@pythnetwork/entropy-sdk-solidity/EntropyStructs.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\n\npragma solidity ^0.8.0;\n\ncontract EntropyStructs {\n    struct ProviderInfo {\n        uint128 feeInWei;\n        uint128 accruedFeesInWei;\n        // The commitment that the provider posted to the blockchain, and the sequence number\n        // where they committed to this. This value is not advanced after the provider commits,\n        // and instead is stored to help providers track where they are in the hash chain.\n        bytes32 originalCommitment;\n        uint64 originalCommitmentSequenceNumber;\n        // Metadata for the current commitment. Providers may optionally use this field to to help\n        // manage rotations (i.e., to pick the sequence number from the correct hash chain).\n        bytes commitmentMetadata;\n        // Optional URI where clients can retrieve revelations for the provider.\n        // Client SDKs can use this field to automatically determine how to retrieve random values for each provider.\n        // TODO: specify the API that must be implemented at this URI\n        bytes uri;\n        // The first sequence number that is *not* included in the current commitment (i.e., an exclusive end index).\n        // The contract maintains the invariant that sequenceNumber <= endSequenceNumber.\n        // If sequenceNumber == endSequenceNumber, the provider must rotate their commitment to add additional random values.\n        uint64 endSequenceNumber;\n        // The sequence number that will be assigned to the next inbound user request.\n        uint64 sequenceNumber;\n        // The current commitment represents an index/value in the provider's hash chain.\n        // These values are used to verify requests for future sequence numbers. Note that\n        // currentCommitmentSequenceNumber < sequenceNumber.\n        //\n        // The currentCommitment advances forward through the provider's hash chain as values\n        // are revealed on-chain.\n        bytes32 currentCommitment;\n        uint64 currentCommitmentSequenceNumber;\n    }\n\n    struct Request {\n        // Storage slot 1 //\n        address provider;\n        uint64 sequenceNumber;\n        // The number of hashes required to verify the provider revelation.\n        uint32 numHashes;\n        // Storage slot 2 //\n        // The commitment is keccak256(userCommitment, providerCommitment). Storing the hash instead of both saves 20k gas by\n        // eliminating 1 store.\n        bytes32 commitment;\n        // Storage slot 3 //\n        // The number of the block where this request was created.\n        // Note that we're using a uint64 such that we have an additional space for an address and other fields in\n        // this storage slot. Although block.number returns a uint256, 64 bits should be plenty to index all of the\n        // blocks ever generated.\n        uint64 blockNumber;\n        // The address that requested this random number.\n        address requester;\n        // If true, incorporate the blockhash of blockNumber into the generated random value.\n        bool useBlockhash;\n        // There are 3 remaining bytes of free space in this slot.\n    }\n}\n"
      },
      "@pythnetwork/entropy-sdk-solidity/IEntropy.sol": {
        "content": "// SPDX-License-Identifier: Apache 2\npragma solidity ^0.8.0;\n\nimport \"./EntropyEvents.sol\";\n\ninterface IEntropy is EntropyEvents {\n    // Register msg.sender as a randomness provider. The arguments are the provider's configuration parameters\n    // and initial commitment. Re-registering the same provider rotates the provider's commitment (and updates\n    // the feeInWei).\n    //\n    // chainLength is the number of values in the hash chain *including* the commitment, that is, chainLength >= 1.\n    function register(\n        uint128 feeInWei,\n        bytes32 commitment,\n        bytes calldata commitmentMetadata,\n        uint64 chainLength,\n        bytes calldata uri\n    ) external;\n\n    // Withdraw a portion of the accumulated fees for the provider msg.sender.\n    // Calling this function will transfer `amount` wei to the caller (provided that they have accrued a sufficient\n    // balance of fees in the contract).\n    function withdraw(uint128 amount) external;\n\n    // As a user, request a random number from `provider`. Prior to calling this method, the user should\n    // generate a random number x and keep it secret. The user should then compute hash(x) and pass that\n    // as the userCommitment argument. (You may call the constructUserCommitment method to compute the hash.)\n    //\n    // This method returns a sequence number. The user should pass this sequence number to\n    // their chosen provider (the exact method for doing so will depend on the provider) to retrieve the provider's\n    // number. The user should then call fulfillRequest to construct the final random number.\n    //\n    // This method will revert unless the caller provides a sufficient fee (at least getFee(provider)) as msg.value.\n    // Note that excess value is *not* refunded to the caller.\n    function request(\n        address provider,\n        bytes32 userCommitment,\n        bool useBlockHash\n    ) external payable returns (uint64 assignedSequenceNumber);\n\n    // Fulfill a request for a random number. This method validates the provided userRandomness and provider's proof\n    // against the corresponding commitments in the in-flight request. If both values are validated, this function returns\n    // the corresponding random number.\n    //\n    // Note that this function can only be called once per in-flight request. Calling this function deletes the stored\n    // request information (so that the contract doesn't use a linear amount of storage in the number of requests).\n    // If you need to use the returned random number more than once, you are responsible for storing it.\n    function reveal(\n        address provider,\n        uint64 sequenceNumber,\n        bytes32 userRandomness,\n        bytes32 providerRevelation\n    ) external returns (bytes32 randomNumber);\n\n    function getProviderInfo(\n        address provider\n    ) external view returns (EntropyStructs.ProviderInfo memory info);\n\n    function getDefaultProvider() external view returns (address provider);\n\n    function getRequest(\n        address provider,\n        uint64 sequenceNumber\n    ) external view returns (EntropyStructs.Request memory req);\n\n    function getFee(address provider) external view returns (uint128 feeAmount);\n\n    function getAccruedPythFees()\n        external\n        view\n        returns (uint128 accruedPythFeesInWei);\n\n    function constructUserCommitment(\n        bytes32 userRandomness\n    ) external pure returns (bytes32 userCommitment);\n\n    function combineRandomValues(\n        bytes32 userRandomness,\n        bytes32 providerRandomness,\n        bytes32 blockHash\n    ) external pure returns (bytes32 combinedRandomness);\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-core/SlashtokenDrawRegistry.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport {SubscriptionRegistry} from \"../handshake-registry-libs/SubscriptionRegistry.sol\";\nimport {ISlashTokenDraw, ISlashTokenDrawPyth} from \"../handshake-registry-types/ISlashTokenDraw.sol\";\n\n/// @author 0xCocomastoras\n/// @custom:version 1.0\n/// @title SlashTokenDrawRegistry\n/// @notice SlashTokenDrawRegistry is a simple, yet powerful tool to airdrop tokens/NFTs or native currency to lottery winners using merkle trees and chainlink/pyth's vrf.\ncontract SlashTokenDrawRegistry is SubscriptionRegistry {\n    constructor(){}\n\n    /**\n        @notice ERC-20 token draw with equal amount to all winners\n        @param drawId_ The draw's id\n        @param erc20Token The address of the token to airdrop\n        @param rootHash The root of the merkle tree\n        @param numOfWinners The number of total winners\n        @param numOfParticipants The number of total participants\n        @param winningAmountPerUser The amount each winner gonna get\n\n        @dev Initialises a new erc20 draw using Chainlink's VRF\n\n        Requirements:\n        - Contract must not be frozen\n        - Caller must not be denylisted\n        - Contract must be initialised\n        - `drawId_` must not been used before\n        - `numOfWinners` must be greater than 0 and less than 101 and equal or less than participants\n        - `numOfParticipants` must be greater than 0 and less than 100001\n        - There must be an active chainlink contract\n        - The caller must provide a correct msg.value\n    **/\n    function createNewErc20DrawChainlink(bytes32 drawId_, address erc20Token, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256 winningAmountPerUser) external payable {\n        require(frozen == 0, 'CF');\n        require(denylist[msg.sender] == 0, 'UD');\n        require(isInitialized != 0, 'NIY');\n        require(numOfWinners != 0 && numOfWinners <= 100 && numOfWinners <= numOfParticipants, 'NVW');\n        require(numOfParticipants != 0 && numOfParticipants <= 100000, 'NVP');\n        require(drawIdToContract[drawId_] == address(0), 'DIU');\n        address providerAdd =  providerToAddress[validProviders.CHAINLINK];\n        require(providerAdd != address(0), \"NVPR\");\n        drawIdToContract[drawId_] = providerAdd;\n        userToDrawIds[msg.sender].push(drawId_);\n        uint256 value = _getBaseFeeForWallet(); // Check if wallet has a custom fee\n        uint256 purchasedTxns = _getAvailableTxnsForWallet(); // Check if wallet has purchased bundle txns\n        uint256 serviceFee = _calculateVRFCost(0); // Calculate estimate chainlink fee denominated to native in wei\n        value = value == 0 ? baseFee : value; // If user doesn't have a custom fee user base fee\n        ofe += serviceFee;\n        if (purchasedTxns == 0) {\n            require((msg.value >= value+serviceFee - highSlippage*((serviceFee)/100)) && (msg.value <= value+serviceFee + lowSlippage*((serviceFee)/100)), \"NVV\"); // We allow a highSlippage% change on gas price fow small spikes\n        } else {\n            require((msg.value >= serviceFee - highSlippage*(serviceFee/100)) && (msg.value <= serviceFee + lowSlippage*((serviceFee)/100)), \"NVV\"); // We allow a highSlippage% change on gas price fow small spikes\n            _updateAvailableTxnsForWallet();\n        }\n        // Calls the active chainlink contract and initialises the request\n        ISlashTokenDraw(providerAdd).createNewErc20Draw(drawId_, msg.sender, erc20Token, rootHash, numOfWinners, numOfParticipants, winningAmountPerUser);\n    }\n\n    /**\n        @notice Native draw with equal amount to all winners\n        @param drawId_ The draw's id\n        @param rootHash The root of the merkle tree\n        @param numOfWinners The number of total winners\n        @param numOfParticipants The number of total participants\n        @param winningAmountPerUser The amount each winner gonna get\n\n        @dev Initialises a new native draw using Chainlink's VRF\n\n        Requirements:\n        - Contract must not be frozen\n        - Caller must not be denylisted\n        - Contract must be initialised\n        - `drawId_` must not been used before\n        - `numOfWinners` must be greater than 0 and less than 101 and equal or less than participants\n        - `numOfParticipants` must be greater than 0 and less than 100001\n        - There must be an active chainlink contract\n        - The caller must provide a correct msg.value\n    **/\n    function createNewNativeDrawChainlink(bytes32 drawId_, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256 winningAmountPerUser) external payable {\n        require(denylist[msg.sender] == 0, 'UD');\n        require(frozen == 0, 'CF');\n        require(isInitialized != 0, 'NIY');\n        require(numOfWinners != 0 && numOfWinners <= 100 && numOfWinners <= numOfParticipants, 'NVW');\n        require(numOfParticipants != 0 && numOfParticipants <= 100000, 'NVP');\n        require(drawIdToContract[drawId_] == address(0), 'DIU');\n        address providerAdd =  providerToAddress[validProviders.CHAINLINK];\n        require(providerAdd != address(0), \"NVPR\");\n        drawIdToContract[drawId_] = providerAdd;\n        userToDrawIds[msg.sender].push(drawId_);\n        uint256 value = _getBaseFeeForWallet(); // Check if wallet has a custom fee\n        uint256 purchasedTxns = _getAvailableTxnsForWallet(); // Check if wallet has purchased bundle txns\n        uint256 serviceFee = _calculateVRFCost(0); // Calculate estimate chainlink fee denominated to native in wei\n        value = value == 0 ? baseFee : value; // If user doesn't have a custom fee user base fee\n        ofe += serviceFee;\n        if (purchasedTxns == 0) {\n            require((msg.value >= value+serviceFee - highSlippage*((serviceFee)/100)) && (msg.value <= value+serviceFee + lowSlippage*((serviceFee)/100)), \"NVV\"); // We allow a highSlippage% change on gas price fow small spikes\n        } else {\n            require((msg.value >= serviceFee - highSlippage*(serviceFee/100)) && (msg.value <= serviceFee + lowSlippage*((serviceFee)/100)), \"NVV\"); // We allow a highSlippage% change on gas price fow small spikes\n            _updateAvailableTxnsForWallet();\n        }\n        ISlashTokenDraw(providerAdd).createNewNativeDraw(drawId_, msg.sender, rootHash, numOfWinners, numOfParticipants, winningAmountPerUser);\n    }\n\n    /**\n        @notice ERC-721 token draw with equal amount to all winners\n        @param drawId_ The draw's id\n        @param erc721Token The address of the token to airdrop\n        @param rootHash The root of the merkle tree\n        @param numOfWinners The number of total winners\n        @param numOfParticipants The number of total participants\n        @param erc721TokenIds The tokenIds each winner gonna get\n\n        @dev Initialises a new erc721 draw using Chainlink's VRF\n\n        Requirements:\n        - Contract must not be frozen\n        - Caller must not be denylisted\n        - Contract must be initialised\n        - `drawId_` must not been used before\n        - `numOfWinners` must be greater than 0 and less than 101 and equal or less than participants\n        - `numOfParticipants` must be greater than 0 and less than 100001\n        - `erc721TokenIds` length must match the `numOfParticipants`\n        - There must be an active chainlink contract\n        - The caller must provide a correct msg.value\n    **/\n    function createNewErc721DrawChainlink(bytes32 drawId_, address erc721Token, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256[] memory erc721TokenIds) external payable {\n        require(frozen == 0, 'CF');\n        require(denylist[msg.sender] == 0, 'UD');\n        require(isInitialized != 0, 'NIY');\n        require(numOfWinners != 0 && numOfWinners <= 100 && numOfWinners <= numOfParticipants, 'NVW');\n        require(numOfParticipants != 0 && numOfParticipants <= 100000, 'NVP');\n        require(numOfWinners == erc721TokenIds.length, 'NVL');\n        require(drawIdToContract[drawId_] == address(0), 'DIU');\n        address providerAdd =  providerToAddress[validProviders.CHAINLINK];\n        require(providerAdd != address(0), \"NVPR\");\n        drawIdToContract[drawId_] = providerAdd;\n        userToDrawIds[msg.sender].push(drawId_);\n        uint256 value = _getBaseFeeForWallet(); // Check if wallet has a custom fee\n        uint256 purchasedTxns = _getAvailableTxnsForWallet(); // Check if wallet has purchased bundle txns\n        uint256 serviceFee = _calculateVRFCost(0); // Calculate estimate chainlink fee denominated to native in wei\n        value = value == 0 ? baseFee : value;  // If user doesn't have a custom fee user base fee\n        ofe += serviceFee;\n        if (purchasedTxns == 0) {\n            require((msg.value >= value+serviceFee - highSlippage*((serviceFee)/100)) && (msg.value <= value+serviceFee + lowSlippage*((serviceFee)/100)), \"NVV\"); // We allow a highSlippage% change on gas price fow small spikes\n        } else {\n            require((msg.value >= serviceFee - highSlippage*(serviceFee/100)) && (msg.value <= serviceFee + lowSlippage*((serviceFee)/100)), \"NVV\"); // We allow a highSlippage% change on gas price fow small spikes\n            _updateAvailableTxnsForWallet();\n        }\n        ISlashTokenDraw(providerAdd).createNewErc721Draw(drawId_, msg.sender, erc721Token, rootHash, numOfWinners, numOfParticipants, keccak256(abi.encodePacked(erc721TokenIds)));\n    }\n\n    /**\n        @notice ERC-20 token draw with equal amount to all winners\n        @param drawId_ The draw's id\n        @param erc20Token The address of the token to airdrop\n        @param rootHash The root of the merkle tree\n        @param numOfWinners The number of total winners\n        @param numOfParticipants The number of total participants\n        @param winningAmountPerUser The amount each winner gonna get\n        @param commitment Caller's secret number keccak256 hash\n\n        @dev Initialises a new erc20 draw using Pyth's VRF\n\n        Requirements:\n        - Contract must not be frozen\n        - Caller must not be denylisted\n        - Contract must be initialised\n        - `drawId_` must not been used before\n        - `numOfWinners` must be greater than 0 and less than 101 and equal or less than participants\n        - `numOfParticipants` must be greater than 0 and less than 100001\n        - There must be an active Pyth contract\n        - The caller must provide a correct msg.value\n    **/\n    function createNewErc20DrawPyth(bytes32 drawId_, address erc20Token, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256 winningAmountPerUser, bytes32 commitment) external payable {\n        require(frozen == 0, 'CF');\n        require(denylist[msg.sender] == 0, 'UD');\n        require(isInitialized != 0, 'NIY');\n        require(numOfWinners != 0 && numOfWinners <= 100 && numOfWinners <= numOfParticipants, 'NVW');\n        require(numOfParticipants != 0 && numOfParticipants <= 100000, 'NVP');\n        require(drawIdToContract[drawId_] == address(0), 'DIU');\n        address providerAdd =  providerToAddress[validProviders.PYTH];\n        require(providerAdd != address(0), \"NVPR\");\n        drawIdToContract[drawId_] = providerAdd;\n        userToDrawIds[msg.sender].push(drawId_);\n        uint256 value = _getBaseFeeForWallet(); // Check if wallet has a custom fee\n        uint256 purchasedTxns = _getAvailableTxnsForWallet(); // Check if wallet has purchased bundle txns\n        uint256 serviceFee = _calculateVRFCost(1); // Calculate estimate chainlink fee denominated to native in wei\n        value = value == 0 ? baseFee : value;  // If user doesn't have a custom fee user base fee\n        ofe += serviceFee;\n        if (purchasedTxns == 0) {\n            require((msg.value == value+serviceFee), \"NVV\");\n        } else {\n            require((msg.value == serviceFee), \"NVV\");\n            _updateAvailableTxnsForWallet();\n        }\n        ISlashTokenDrawPyth(providerAdd).createNewErc20Draw{value: serviceFee}(drawId_, msg.sender, erc20Token, rootHash, numOfWinners, numOfParticipants, winningAmountPerUser, commitment, serviceFee);\n    }\n\n    /**\n        @notice Native draw with equal amount to all winners\n        @param drawId_ The draw's id\n        @param rootHash The root of the merkle tree\n        @param numOfWinners The number of total winners\n        @param numOfParticipants The number of total participants\n        @param winningAmountPerUser The amount each winner gonna get\n        @param commitment Caller's secret number keccak256 hash\n\n        @dev Initialises a new erc20 draw using Pyth's VRF\n\n        Requirements:\n        - Contract must not be frozen\n        - Caller must not be denylisted\n        - Contract must be initialised\n        - `drawId_` must not been used before\n        - `numOfWinners` must be greater than 0 and less than 101 and equal or less than participants\n        - `numOfParticipants` must be greater than 0 and less than 100001\n        - There must be an active Pyth contract\n        - The caller must provide a correct msg.value\n    **/\n    function createNewNativeDrawPyth(bytes32 drawId_, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256 winningAmountPerUser, bytes32 commitment) external payable {\n        require(frozen == 0, 'CF');\n        require(denylist[msg.sender] == 0, 'UD');\n        require(isInitialized != 0, 'NIY');\n        require(numOfWinners != 0 && numOfWinners <= 100 && numOfWinners <= numOfParticipants, 'NVW');\n        require(numOfParticipants != 0 && numOfParticipants <= 100000, 'NVP');\n        require(drawIdToContract[drawId_] == address(0), 'DIU');\n        address providerAdd =  providerToAddress[validProviders.PYTH];\n        require(providerAdd != address(0), \"NVPR\");\n        drawIdToContract[drawId_] = providerAdd;\n        userToDrawIds[msg.sender].push(drawId_);\n        uint256 value = _getBaseFeeForWallet(); // Check if wallet has a custom fee\n        uint256 purchasedTxns = _getAvailableTxnsForWallet(); // Check if wallet has purchased bundle txns\n        uint256 serviceFee = _calculateVRFCost(1); // Calculate estimate chainlink fee denominated to native in wei\n        value = value == 0 ? baseFee : value; // If user doesn't have a custom fee user base fee\n        ofe += serviceFee;\n        if (purchasedTxns == 0) {\n            require((msg.value == value+serviceFee), \"NVV\");\n        } else {\n            require((msg.value == serviceFee), \"NVV\");\n            _updateAvailableTxnsForWallet();\n        }\n        ISlashTokenDrawPyth(providerAdd).createNewNativeDraw{value: serviceFee}(drawId_, msg.sender, rootHash, numOfWinners, numOfParticipants, winningAmountPerUser, commitment, serviceFee);\n    }\n\n    /**\n        @notice ERC-721 token draw with equal amount to all winners\n        @param drawId_ The draw's id\n        @param erc721Token The address of the token to airdrop\n        @param rootHash The root of the merkle tree\n        @param numOfWinners The number of total winners\n        @param numOfParticipants The number of total participants\n        @param erc721TokenIds The tokenIds each winner gonna get\n        @param commitment Caller's secret number keccak256 hash\n\n        @dev Initialises a new erc20 draw using Pyth's VRF\n\n        Requirements:\n        - Contract must not be frozen\n        - Caller must not be denylisted\n        - Contract must be initialised\n        - `drawId_` must not been used before\n        - `numOfWinners` must be greater than 0 and less than 101 and equal or less than participants\n        - `numOfParticipants` must be greater than 0 and less than 100001\n        - `erc721TokenIds` length must match the `numOfParticipants`\n        - There must be an active Pyth contract\n        - The caller must provide a correct msg.value\n    **/\n    function createNewErc721DrawPyth(bytes32 drawId_, address erc721Token, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants,  uint256[] memory erc721TokenIds, bytes32 commitment) external payable {\n        require(frozen == 0, 'CF');\n        require(denylist[msg.sender] == 0, 'UD');\n        require(isInitialized != 0, 'NIY');\n        require(numOfWinners != 0 && numOfWinners <= 100 && numOfWinners <= numOfParticipants, 'NVW');\n        require(numOfParticipants != 0 && numOfParticipants <= 100000, 'NVP');\n        require(drawIdToContract[drawId_] == address(0), 'DIU');\n        address providerAdd =  providerToAddress[validProviders.PYTH];\n        require(providerAdd != address(0), \"NVPR\");\n        drawIdToContract[drawId_] = providerAdd;\n        userToDrawIds[msg.sender].push(drawId_);\n        uint256 value = _getBaseFeeForWallet(); // Check if wallet has a custom fee\n        uint256 purchasedTxns = _getAvailableTxnsForWallet(); // Check if wallet has purchased bundle txns\n        uint256 serviceFee = _calculateVRFCost(1); // Calculate estimate chainlink fee denominated to native in wei\n        value = value == 0 ? baseFee : value; // If user doesn't have a custom fee user base fee\n        ofe += serviceFee;\n        if (purchasedTxns == 0) {\n            require((msg.value == value+serviceFee), \"NVV\");\n        } else {\n            require((msg.value == serviceFee), \"NVV\");\n            _updateAvailableTxnsForWallet();\n        }\n        ISlashTokenDrawPyth(providerAdd).createNewErc721Draw{value: serviceFee}(drawId_, msg.sender, erc721Token, rootHash, numOfWinners, numOfParticipants, keccak256(abi.encodePacked(erc721TokenIds)), commitment, serviceFee);\n    }\n}\n\n\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-libs/CallHandler.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"./ManagerActions.sol\";\nimport {ISlashTokenDrawCaller, ISlashTokenDrawPythCaller} from \"../handshake-registry-types/ISlashTokenDraw.sol\";\ncontract CallHandler is ManagerActions {\n    constructor(){}\n\n    /**\n        @notice External view functions that returns the requestId for a given drawId_\n        @param drawId_ The draw's id to check\n\n        @dev Checks if the drawId_ exists then checks if its a pyth or chainlink draw and proceeds to get the requestId\n    **/\n    function getRequestIdForDrawId(bytes32 drawId_) external view returns(uint256) {\n        address drawAddress = drawIdToContract[drawId_];\n        if(_checkPythAddresses(drawAddress)) {\n            return uint256(ISlashTokenDrawPythCaller(drawAddress).getRequestIdForDrawId(drawId_));\n        }else if(_checkChainlinkAddresses(drawAddress)){\n            return ISlashTokenDrawCaller(drawAddress).getRequestIdForDrawId(drawId_);\n        }else {\n            return 0;\n        }\n    }\n\n    /**\n        @notice External view functions that returns the draw's status for a given drawId_\n        @param drawId_ The draw's id to check\n\n        @dev Checks if the drawId_ exists then checks if its a pyth or chainlink draw and proceeds to get the current status\n    **/\n    function getDrawStatus(bytes32 drawId_) external view returns(uint256) {\n        address drawAddress = drawIdToContract[drawId_];\n        if(_checkPythAddresses(drawAddress)) {\n            return ISlashTokenDrawPythCaller(drawAddress).getDrawStatus(drawId_);\n        }else if(_checkChainlinkAddresses(drawAddress)){\n            return ISlashTokenDrawCaller(drawAddress).getDrawStatus(drawId_);\n        }else {\n            return 0;\n        }\n    }\n\n    /**\n        @notice External view functions that returns the response of the VRF/Entropy for a given drawId_\n        @param drawId_ The draw's id to check\n\n        @dev Checks if the drawId_ exists then checks if its a pyth or chainlink draw and proceeds to get the response of the corresponding provider\n    **/\n    function getRequestResponse(bytes32 drawId_) external view returns(uint256) {\n        address drawAddress = drawIdToContract[drawId_];\n        if(_checkPythAddresses(drawAddress)) {\n            return ISlashTokenDrawPythCaller(drawAddress).getRequestResponse(drawId_);\n        }else if(_checkChainlinkAddresses(drawAddress)){\n            return ISlashTokenDrawCaller(drawAddress).getRequestResponse(drawId_);\n        }else {\n            return 0;\n        }\n    }\n\n    /**\n        @notice External view functions that returns the Entropy's uri and sequence number for a given drawId_\n        @param drawId_ The draw's id to check\n\n        @dev Checks if the drawId_ is a pyth draw and proceeds to get the provider's uri and draw's sequence number\n    **/\n    function getProviderInfoAndSequenceNumber(bytes32 drawId_) external view returns (bytes memory, uint64) {\n        address drawAddress = drawIdToContract[drawId_];\n        if(_checkPythAddresses(drawAddress)) {\n            return ISlashTokenDrawPythCaller(drawAddress).getProviderInfoAndSequenceNumber(drawId_);\n        }else {\n            return ('', 0);\n        }\n    }\n\n    /**\n        @notice External view functions that returns the block that the distribution happened\n        @param drawId_ The draw's id to check\n\n        @dev Checks if the drawId_ exists then checks if its a pyth or chainlink draw and proceeds to get the block that the distribution happened\n    **/\n    function getDistributionBlock(bytes32 drawId_) external view returns(uint256) {\n        address drawAddress = drawIdToContract[drawId_];\n        if(_checkPythAddresses(drawAddress)) {\n            return ISlashTokenDrawPythCaller(drawAddress).getDistributionBlock(drawId_);\n        }else if(_checkChainlinkAddresses(drawAddress)){\n            return ISlashTokenDrawCaller(drawAddress).getDistributionBlock(drawId_);\n        }else {\n            return 0;\n        }\n    }\n\n     /**\n        @notice External view functions that returns the user's drawId's and corresponding provider\n        @param user The user's address\n    **/\n    function getUserDrawIds(address user) external view returns(bytes32[] memory drawIds, uint256[] memory network) {\n        drawIds = userToDrawIds[user];\n        network = new uint256[](drawIds.length);\n        for(uint256 i=0; i<drawIds.length; i++){\n            address drawAddress = drawIdToContract[drawIds[i]];\n            network[i] = _checkChainlinkAddresses(drawAddress) ? 0 : 1;\n        }\n    }\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-libs/ContractRegistry.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ncontract ContractRegistry {\n    /// @dev the two valid types of randomness provider\n    enum validProviders{CHAINLINK, PYTH}\n    /// @dev mapping of drawId_ to draw provider address (chainlink, pyth)\n    mapping(bytes32 => address) internal drawIdToContract;\n    /// @dev mapping of provider type to active provider address (chainlink, pyth), address(0) if there is no active\n    mapping(validProviders => address) internal providerToAddress;\n    /// @dev mapping of caller's address to caller's drawIds\n    mapping(address => bytes32[]) internal userToDrawIds;\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-libs/ManagerActions.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol\";\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"@pythnetwork/entropy-sdk-solidity/IEntropy.sol\";\nimport {ContractRegistry} from \"./ContractRegistry.sol\";\nimport {PriceFeed} from \"./PriceFeed.sol\";\n\ncontract ManagerActions is ContractRegistry, PriceFeed {\n    event Claimed(uint256 SF, uint256 OF);\n    /// @dev Accepted slippages of calculated service fee on execution and estimation\n    uint256 internal lowSlippage = 1;\n    uint256 internal highSlippage = 1;\n    /// @dev Registry's owner\n    address internal owner;\n    /// @dev Registry's feeSink\n    address internal feeSink;\n    /// @dev Registry's freeze status\n    uint256 public frozen;\n    /// @dev Provider fees\n    uint256 internal ofe;\n    /// @dev User's address to denylist flag\n    mapping(address => uint256) internal denylist;\n    using EnumerableSet for EnumerableSet.AddressSet;\n    /// @dev list of denied addresses\n    EnumerableSet.AddressSet internal deniedAddresses;\n    /// @dev list of pyth draw addresses\n    EnumerableSet.AddressSet internal pythAddresses;\n    /// @dev list of chainlink draw addresses\n    EnumerableSet.AddressSet internal chainlinkAddresses;\n\n    constructor(){}\n\n    /**\n        @notice Admin freezes / unfreezes contracts\n        @param value_ 0 = unfreeze, any other value = freeze\n    */\n    function freezeContract(uint256 value_) external {\n        require(msg.sender == owner, 'NVS');\n        frozen = value_;\n    }\n\n    /**\n        @notice Admin updates fee sink address\n        @param feeSink_ The new fee sink address\n    */\n    function updateFeeSink(address feeSink_) external {\n        require(msg.sender == owner, 'NVS');\n        feeSink = feeSink_;\n    }\n\n    /**\n        @notice Admin updates the config\n        @param chainlinkDraw_ The new chainlink draw contract address or address(0)\n        @param pythDraw_ The new pyth draw contract address or address(0)\n        @param entropyAddress_ The new entropy's address\n        @param providerAddress_ The new provider's address\n        @param coordinatorAddress_ The new chainlink coordinator address\n        @param subId_ The new suscription id\n        @param priceFeedAddress_ The new price feed's address\n        @param multiplier_ The new multiplier\n        @param divisor_ The new divisor\n        @param gasLimit_ The new max gas limit\n\n        @dev Updates the chainlinkDraw and pythDraw contract addresses, the entropy's, coordinator's and price feed configs, the max gasLimit of coordinator and multiplier/divisor to produce the premium Link fee per network\n    */\n    function updateConfigs(address chainlinkDraw_, address pythDraw_, address entropyAddress_, address providerAddress_, address coordinatorAddress_, uint64 subId_, address priceFeedAddress_, uint256 multiplier_, uint256 divisor_, uint256 gasLimit_) external {\n        require(msg.sender == owner, 'NVS');\n        if(pythDraw_ != address(0)){\n            pythAddresses.add(pythDraw_);\n        }\n        if(chainlinkDraw_ != address(0)){\n            chainlinkAddresses.add(chainlinkDraw_);\n        }\n        providerToAddress[validProviders.CHAINLINK] = chainlinkDraw_;\n        providerToAddress[validProviders.PYTH] = pythDraw_;\n        entropy = IEntropy(entropyAddress_);\n        provider = providerAddress_;\n        COORDINATOR = VRFCoordinatorV2Interface(coordinatorAddress_);\n        subscriptionId = subId_;\n        priceFeedAddress = priceFeedAddress_;\n        multiplier = multiplier_;\n        divisor = divisor_;\n        gasLimit = gasLimit_;\n    }\n\n    function updateSlippage(uint256 lowSlippage_, uint256 highSlippage_) external {\n        require(msg.sender == owner, 'NVS');\n        lowSlippage = lowSlippage_;\n        highSlippage = highSlippage_;\n    }\n\n    /**\n        @notice Admin claims contract fees\n    */\n    function claimFees() external {\n        address owner_ = owner;\n        uint256 cBalance;\n        uint256 of_ = ofe;\n        ofe = 0;\n        assembly {\n            if iszero(eq(caller(), owner_)) {\n                revert(0,0)\n            }\n            cBalance := selfbalance()\n            if iszero(call(gas(), sload(feeSink.slot), selfbalance(), 0, 0, 0, 0)) {\n                revert(0,0)\n            }\n        }\n        emit Claimed(cBalance - of_, of_);\n    }\n\n    /**\n        @notice Admin adds addresses to denylist\n        @param list A list of addresses to add\n    */\n    function addToDenylist(address[] memory list) external {\n        require(msg.sender == owner, 'NVS');\n        uint len = list.length;\n        for(uint i = 0; i < len;) {\n            if (!deniedAddresses.contains(list[i])) {\n                deniedAddresses.add(list[i]);\n            }\n            unchecked {\n                denylist[list[i]] = 1;\n                i++;\n            }\n        }\n    }\n\n    /**\n        @notice Admin removes addresses to denylist\n        @param list A list of addresses to remove\n    */\n    function removeFromDenylist(address[] memory list) external {\n        require(msg.sender == owner, 'NVS');\n        uint len = list.length;\n        for(uint i = 0; i < len;) {\n            if (deniedAddresses.contains(list[i])) {\n                deniedAddresses.remove(list[i]);\n            }\n            unchecked {\n                denylist[list[i]] = 0;\n                i++;\n            }\n        }\n    }\n\n    /**\n        @notice External view function that returns the list of denied addresses\n    */\n    function getDenylist() external view returns (address[] memory) {\n        require(msg.sender == owner, 'NVS');\n        return deniedAddresses.values();\n    }\n\n    /**\n        @notice External view function that protocol and service fees\n    */\n    function getInfo() external view returns(uint256, uint256) {\n        return(address(this).balance - ofe, ofe);\n    }\n\n    /**\n        @notice Internal view function that returns true if given address is a current or past pythDraw address\n        @param contract_ Address to check\n    */\n    function _checkPythAddresses(address contract_) internal view returns (bool) {\n        return pythAddresses.contains(contract_);\n    }\n\n    /**\n        @notice Internal view function that returns true if given address is a current or past chainlinkDraw address\n        @param contract_ Address to check\n    */\n    function _checkChainlinkAddresses(address contract_) internal view returns (bool) {\n        return chainlinkAddresses.contains(contract_);\n    }\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-libs/PriceFeed.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../handshake-registry-types/IAggregator.sol\";\nimport \"@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol\";\nimport \"@pythnetwork/entropy-sdk-solidity/IEntropy.sol\";\n\ncontract PriceFeed {\n    /// @dev multiplier to produce premium fee\n    uint256 internal multiplier;\n    /// @dev divisor to produce premium fee\n    uint256 internal divisor;\n    /// @dev max gas limit for active gas lane\n    uint256 internal gasLimit;\n    /// @dev Link's price feed\n    address internal priceFeedAddress;\n    /// @dev active coordinator's subscription id\n    uint64 internal subscriptionId;\n    VRFCoordinatorV2Interface internal COORDINATOR;\n\n    /// @dev Entropies's configuration\n    IEntropy internal entropy;\n    address internal provider = 0x6CC14824Ea2918f5De5C2f75A9Da968ad4BD6344;\n\n    constructor(){}\n\n    /**\n        @notice Internal function that initialises the price feed config\n        @param priceFeed The price feed's address\n        @param vrfCoordinator_ The coordinator's address\n        @param entropyProvider_ The entropy's address\n        @param multiplier_ The premium link fee multiplier\n        @param divisor_ The premium link fee divisor\n        @param gasLimit_ The max gas limit for active lane\n        @param subscriptionId_ The sub id\n    **/\n    function _initialisePriceFeed(address priceFeed, address vrfCoordinator_, address entropyProvider_, uint256 multiplier_, uint256 divisor_, uint256 gasLimit_, uint64 subscriptionId_) internal {\n        priceFeedAddress = priceFeed;\n        COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator_);\n        entropy = IEntropy(entropyProvider_);\n        multiplier = multiplier_;\n        divisor = divisor_;\n        gasLimit = gasLimit_;\n        subscriptionId = subscriptionId_;\n    }\n\n    /**\n        @notice Internal view function that estimates the service fee\n        @param network 0 for chainlink , 1 for pyth\n    **/\n    function _calculateVRFCost(uint256 network) internal view returns (uint256 nativeRequired) {\n         if(network == 0 ){\n             IAggregator priceFeed = IAggregator(priceFeedAddress);\n             (uint96 balanceLink,,,) = COORDINATOR.getSubscription(subscriptionId);\n             (,int256 answer,,,) = priceFeed.latestRoundData();\n             uint256 currentBalanceToWei;\n             uint256 minBalanceRequired;\n             uint256 gasPrice;\n             uint256 gasLimit_ = gasLimit;\n             uint256 multiplier_ = multiplier;\n             uint256 divisor_ = divisor;\n             assembly {\n                currentBalanceToWei := div(mul(balanceLink, answer), exp(10,18))\n                let linkPremiumToWei := div(mul(multiplier_, answer), divisor_)\n                minBalanceRequired := add(linkPremiumToWei, mul(mul(gasLimit_,exp(10,9)), 215000))\n                nativeRequired := add(linkPremiumToWei, mul(gasprice(), 215000))\n                gasPrice := gasprice()\n             }\n             require(gasPrice <= gasLimit_*10**9, 'GH');\n             require(currentBalanceToWei >= minBalanceRequired, 'NVCB');\n         } else {\n             nativeRequired = entropy.getFee(provider);\n         }\n    }\n\n    /**\n        @notice External view function that estimates the service fee\n        @param network 0 for chainlink , 1 for pyth\n\n        Returns the native required and for chainlink's draws a status code where:\n            -2 : gas price higher than limit\n            -1 : not enough balance in the coordinator\n            >0 : coordinator's balance\n    **/\n    function calculateVRFCost(uint256 network, uint256 gasPrice) external view returns (uint256 nativeRequired, int256 statusCode) {\n        if(network == 0) {\n            IAggregator priceFeed = IAggregator(priceFeedAddress);\n            (uint96 balanceLink,,,) = COORDINATOR.getSubscription(subscriptionId);\n            (,int256 answer,,,) = priceFeed.latestRoundData();\n            uint256 currentBalanceToWei;\n            uint256 minBalanceRequired;\n            uint256 gasLimit_ = gasLimit;\n            uint256 multiplier_ = multiplier;\n            uint256 divisor_ = divisor;\n            assembly {\n                currentBalanceToWei := div(mul(balanceLink, answer), exp(10,18))\n                let linkPremiumToWei := div(mul(multiplier_, answer), divisor_)\n                minBalanceRequired := add(linkPremiumToWei, mul(mul(gasLimit_,exp(10,9)), 215000))\n                nativeRequired := add(linkPremiumToWei, mul(gasPrice, 215000))\n            }\n            if(gasPrice > gasLimit_*(10**9)){\n                statusCode = -2;\n            } else {\n                if (currentBalanceToWei >= minBalanceRequired) {\n                    statusCode = int256(uint256(balanceLink));\n                } else {\n                    statusCode = -1;\n                }\n            }\n        } else {\n            nativeRequired = entropy.getFee(provider);\n        }\n    }\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-libs/SubscriptionRegistry.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\nimport \"../handshake-registry-types/PremiumSubscriptionRegistryEvents.sol\";\nimport \"./ManagerActions.sol\";\nimport \"../handshake-registry-types/DrawRegistryEvents.sol\";\nimport {CallHandler} from \"./CallHandler.sol\";\n\n\n/// @dev Struct containing Chainlink's and Pyth's info, price feed address for Link/Native price\nstruct PriceFeedInitiator {\n    address priceFeed;\n    address vrfCoordinator;\n    address entropyProvider;\n    uint256 multiplier;\n    uint256 divisor;\n    uint256 gasLimit;\n    uint64 subscriptionId;\n}\n\n\ncontract SubscriptionRegistry is DrawRegistryEvents, PremiumSubscriptionRegistryEvents, CallHandler {\n    // @dev user's adddress to custom base fee for no bundle purchases\n    mapping (address => uint256) baseFeeWhitelisted;\n    // @dev user address to total available txns to use\n    mapping(address => uint256) public userToTxns;\n    // @dev an array of available bundles up for purchase\n    uint256[] internal availableTxnsBundles;\n    // @dev an array of price per bundle\n    uint256[] internal txnsBundlesToPrice;\n    // @dev flag that checks if registry is initialised\n    uint256 internal isInitialized;\n    // @dev draw's base fee\n    uint256 public baseFee;\n\n    using EnumerableSet for EnumerableSet.AddressSet;\n    EnumerableSet.AddressSet internal bundleUsers;\n\n    constructor(){}\n\n\n    function initialize (\n        address admin_,\n        address feeSink_,\n        address chainlink_,\n        address pyth_,\n        uint256 baseFeeCostInWei,\n        uint256[] memory availableTxnsBundles_,\n        uint256[] memory txnsBundlesToPrice_,\n        PriceFeedInitiator memory priceFeedInitiator_\n    ) external\n    {\n        require(isInitialized == 0, 'AI');\n        require(availableTxnsBundles_.length == txnsBundlesToPrice_.length, 'NVD');\n        owner = admin_;\n        feeSink = feeSink_;\n        availableTxnsBundles = availableTxnsBundles_;\n        txnsBundlesToPrice = txnsBundlesToPrice_;\n        isInitialized = 1;\n        baseFee = baseFeeCostInWei;\n        providerToAddress[validProviders.CHAINLINK] = chainlink_;\n        providerToAddress[validProviders.PYTH] = pyth_;\n        if(pyth_ != address(0)){\n            pythAddresses.add(pyth_);\n        }\n        if(chainlink_ != address(0)){\n            chainlinkAddresses.add(chainlink_);\n        }\n        _initialisePriceFeed(priceFeedInitiator_.priceFeed, priceFeedInitiator_.vrfCoordinator, priceFeedInitiator_.entropyProvider, priceFeedInitiator_.multiplier, priceFeedInitiator_.divisor, priceFeedInitiator_.gasLimit, priceFeedInitiator_.subscriptionId);\n    }\n\n    /**\n        @notice User buys a bundle of txns\n        @param bundleIndex The index of the bundle array\n        @param quantity The number of bundles that the user wants to buy\n    **/\n    function buyTxnsBundle(uint256 bundleIndex, uint256 quantity) external payable {\n        require(frozen == 0, \"CF\");\n        require(msg.value == txnsBundlesToPrice[bundleIndex] * quantity, 'NVV');\n        require(denylist[msg.sender] == 0, 'UD');\n        require(quantity != 0, 'NVA');\n        if(!bundleUsers.contains(msg.sender)) {\n            bundleUsers.add(msg.sender);\n        }\n        uint256 total;\n        unchecked {\n            total = availableTxnsBundles[bundleIndex] * quantity;\n            userToTxns[msg.sender] += total;\n        }\n        emit TxnsBundleBought(msg.sender, msg.value, total);\n    }\n\n    /**\n        @notice Admin sets promo fee for wallet instead of default base fee\n        @param wallet User's wallet address\n        @param amountInWei New cost per txns\n    **/\n    function setBaseFeeForWallet(address wallet, uint256 amountInWei) external {\n        require(amountInWei < baseFee, \"NVV\");\n        require(msg.sender == owner, 'NVS');\n        baseFeeWhitelisted[wallet] = amountInWei;\n        emit WalletBaseFeeSet(wallet, amountInWei);\n    }\n\n    /**\n        @notice Admin resets promo fee for wallet. Default base fee applies\n        @param wallet User's wallet address\n    **/\n    function resetBaseFeeForWallet(address wallet) external {\n        require(msg.sender == owner, 'NVS');\n        delete baseFeeWhitelisted[wallet];\n        emit WalletBaseFeeReset(wallet);\n    }\n\n    /**\n        @notice Admin adds txns to a user\n        @param wallets A list of user's wallet address\n        @param txns A list of txns to be added\n    **/\n    function addTxnsToWallets(address[] memory wallets, uint256[] memory txns) external {\n        require(msg.sender == owner, 'NVS');\n        require(wallets.length == txns.length, \"NVL\");\n        uint len = wallets.length;\n        for(uint i =0; i<len;){\n            unchecked {\n                userToTxns[wallets[i]] += txns[i];\n                i++;\n            }\n        }\n        emit TxnsAdded(wallets, txns);\n    }\n\n    /**\n        @notice Admin sets the new base fee for all txns\n        @param baseFee_ New base fee\n    **/\n    function setNewBaseFee(uint256 baseFee_) external {\n        require(msg.sender == owner, 'NVS');\n        baseFee = baseFee_;\n    }\n\n    /**\n        @notice Admin sets the new available txnsBundles and prices\n        @param availableTxnsBundles_ New available bundles\n        @param txnsBundlesToPrice_ New price per bundles\n    **/\n    function updateBundles(uint256[] memory availableTxnsBundles_, uint256[] memory txnsBundlesToPrice_ ) external {\n        require(msg.sender == owner, 'NVS');\n        require(availableTxnsBundles_.length == txnsBundlesToPrice_.length, 'NVD');\n        availableTxnsBundles = availableTxnsBundles_;\n        txnsBundlesToPrice = txnsBundlesToPrice_;\n        emit BundlesUpdated(msg.sender, availableTxnsBundles_, txnsBundlesToPrice_);\n    }\n\n    /**\n        @notice External view function that returns active bundle offers\n    **/\n    function getBundles() external view returns (uint256[] memory AvailableBundles, uint256[] memory BundlesPrices) {\n        AvailableBundles = availableTxnsBundles;\n        BundlesPrices = txnsBundlesToPrice;\n    }\n\n    /**\n        @notice External view function that returns the custom base fee for wallet\n    **/\n    function getBaseFeeForWallet() external view returns (uint256) {\n        return baseFeeWhitelisted[msg.sender];\n    }\n\n    /**\n        @notice External view function that returns the available txns for wallet\n    **/\n    function getAvailableTxnsForWallet() external view returns (uint256) {\n        return userToTxns[msg.sender];\n    }\n\n    /**\n        @notice External view function that returns all the users that have bought a bundle\n    */\n    function getUsersThatBoughtBundles() external view returns (address[] memory Users) {\n        require(msg.sender == owner, 'NVS');\n        Users = bundleUsers.values();\n    }\n\n    /**\n        @notice Internal view function that returns the custom base fee for wallet\n    **/\n    function _getBaseFeeForWallet() internal view returns (uint256) {\n        return baseFeeWhitelisted[msg.sender];\n    }\n\n    /**\n        @notice Internal view function that returns the available txns for wallet\n    **/\n    function _updateAvailableTxnsForWallet() internal {\n        unchecked {\n            --userToTxns[msg.sender];\n        }\n    }\n\n    /**\n        @notice Internal view function that returns the available txns for wallet\n    **/\n    function _getAvailableTxnsForWallet() internal view returns (uint256) {\n        return userToTxns[msg.sender];\n    }\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-types/DrawRegistryEvents.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ninterface DrawRegistryEvents {\n    event TxnsBundleBought(address indexed Buyer, uint256 Amount, uint256 Txns);\n    event BundlesUpdated(address indexed Operator, uint256[] BundlesAmounts, uint256[] BundlesPrices);\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-types/IAggregator.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ninterface IAggregator {\n    function latestRoundData() external view returns (\n        uint80 roundId,\n        int256 answer,\n        uint256 startedAt,\n        uint256 updatedAt,\n        uint80 answeredInRound\n    );\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-types/ISlashTokenDraw.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ninterface ISlashTokenDraw {\n    function createNewErc20Draw(bytes32 drawId_, address operator, address erc20Token, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256 winningAmountPerUser) external;\n    function createNewNativeDraw(bytes32 drawId_, address operator, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256 winningAmountPerUser) external;\n    function createNewErc721Draw(bytes32 drawId_, address operator, address erc721Token, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, bytes32 erc721IdsHash) external;\n}\n\ninterface ISlashTokenDrawPyth {\n    function createNewErc20Draw(bytes32 drawId_, address operator, address erc20Token, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256 winningAmountPerUser, bytes32 commitment, uint256 fee) external payable;\n    function createNewNativeDraw(bytes32 drawId_, address operator, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, uint256 winningAmountPerUser, bytes32 commitment, uint256 fee) external payable;\n    function createNewErc721Draw(bytes32 drawId_, address operator, address erc721Token, bytes32 rootHash, uint256 numOfWinners, uint256 numOfParticipants, bytes32 erc721IdsHash, bytes32 commitment, uint256 fee) external payable;\n}\n\ninterface ISlashTokenDrawCaller {\n    function getDrawStatus(bytes32 drawId_) external view returns (uint256);\n    function getRequestIdForDrawId(bytes32 drawId_) external view returns (uint256);\n    function getRequestResponse(bytes32 drawId_) external view returns(uint256);\n    function getDistributionBlock(bytes32 drawId_) external view returns(uint256);\n}\n\ninterface ISlashTokenDrawPythCaller {\n    function getDrawStatus(bytes32 drawId_) external view returns (uint256);\n    function getRequestIdForDrawId(bytes32 drawId_) external view returns (uint64);\n    function getRequestResponse(bytes32 drawId_) external view returns(uint256);\n    function getProviderInfoAndSequenceNumber(bytes32 drawId_) external view returns (bytes memory, uint64);\n    function getDistributionBlock(bytes32 drawId_) external view returns(uint256);\n}\n"
      },
      "contracts/handshake-draw-combined/handshake-registry/handshake-registry-types/PremiumSubscriptionRegistryEvents.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.0;\n\ninterface PremiumSubscriptionRegistryEvents {\n    event WalletBaseFeeSet(address indexed Wallet, uint256 BaseFeeInWei);\n    event WalletBaseFeeReset(address indexed Wallet);\n    event TxnsAdded(address[] Wallet, uint256[] Txns);\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 9999999
      },
      "evmVersion": "paris",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}