creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      ".deps/payout deployment/PayoutPursuit.sol": {
        "content": "/**\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Copyright (c) 2024, PayoutPursuit | DRIFTToken\n *\n * DRIFT is the studio token behind the Drift studio. Drift is a Web3 game studio, which already has a ready-to-play Beta version of its game, Payout Pursuit.\n *\n * The DRIFT token has utility for gamers and non-gamers. Gamers that hold DRIFT will be able to customize their gaming experience with NFT skins and other features.\n * Non-gamers who stake DRIFT receive a percentage of game revenue, and the token also receives Liquidity from a percentage of game revenue.\n *\n * The Drift project has been developed by a highly experienced, fully doxxed Web3 team, with multiple successes in the Web3 space.\n *\n * Drift:\n * https://drifttoken.io/\n *\n * Influ3nce:\n * https://influ3nce.me/\n *\n * Amba$$ador:\n * https://influ3nce.me/ambassador/\n *\n * Twitter / X:\n * https://twitter.com/TheDriftToken\n *\n * Telegram:\n * https://t.me/driftportal\n *\n */\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\nimport {ReentrancyGuardUpgradeable} from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport {AggregatorV3Interface} from \"@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol\";\nimport {PayoutPursuitTime} from \"./extension/PayoutPursuitTime.sol\";\nimport {PayoutPursuitPlayer} from \"./extension/PayoutPursuitPlayer.sol\";\nimport {SafeMath} from \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\nimport {AllowableAddress} from \"./utils/AllowableAddress.sol\";\nimport {Utils} from \"./utils/Utils.sol\";\n\n// Interface of Payout Pursuit NFT cars\ninterface IPayoutPursuitCars {\n    function setupIdsForEvent(\n        bytes32 _eventId,\n        uint256 idDk,\n        uint256 idT10,\n        uint256 idT30\n    ) external;\n\n    function updateURI(uint256[] memory ids, string[] memory newuri) external;\n\n    function mint(\n        address account,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) external;\n\n    function getTokenPerEvent(bytes32 _eventId, uint8 _tier)\n        external\n        view\n        returns (uint256);\n\n    function uriPerEvent(bytes32 _eventId)\n        external\n        view\n        returns (\n            string memory driftKing,\n            string memory top10,\n            string memory top30\n        );\n\n    function removeAllIdsOfEvent(bytes32 _eventId) external;\n\n    function balanceOf(address account, uint256 id)\n        external\n        view\n        returns (uint256);\n}\n\n// Entry of Payout Pursuit Contract\ncontract PayoutPursuit is\n    OwnableUpgradeable,\n    AllowableAddress,\n    PayoutPursuitTime,\n    PayoutPursuitPlayer,\n    ReentrancyGuardUpgradeable,\n    Utils\n{\n    using SafeMath for uint256;\n\n    enum EventStatus {\n        PROGRESS,\n        CANCELLED,\n        COMPLETED\n    }\n\n    struct EventRound {\n        bytes32 eventId;\n        string eventName;\n        string eventMap;\n        uint256 entryFeesUsd;\n        uint256 startTimestamp;\n        uint256 endTimestamp;\n        uint256 totalFeesRaised;\n        uint256 totalFeesRaisedInUSD;\n        EventStatus status;\n    }\n\n    struct RewardLocked {\n        uint256 amount;\n        uint256 deadline;\n    }\n\n    /* Variables */\n    bool public initialized = false;\n    string public version;\n\n    address payable public feesWallet;\n    AggregatorV3Interface public priceFeed;\n    IPayoutPursuitCars public payoutPursuitNft;\n\n    uint256 public eventNonce = 0;\n    uint256 public minParticipants = 5; // Minimum participant required\n    uint256 public claimDeadline = 30 days; // 1 month deadline; otherwise admin withdraw\n\n    bytes32[] private allEvents;\n    bytes32[] private activeEvents;\n\n    uint256 private _additionalPoolAmount;\n    uint256 private _totalFeesCollectedAllEvents;\n\n    mapping(bytes32 => EventRound) private eventDetails;\n    mapping(bytes32 => bool) public eventLeaderboardLocked;\n    mapping(bytes32 => bool) public eventStoppedAndRefund;\n    mapping(bytes32 => mapping(address => bool)) public eventClaims;\n    mapping(bytes32 => mapping(PercentageDist => uint256))\n        private rewardDistribution;\n    mapping(PercentageDist => uint256) public percentage; // Percentages multiplication with 1000. (i.e. 7% = 7 * 1000 = 7000 OR 23.10% = 23.10 * 1000 = 23100)\n    mapping(bytes32 => RewardLocked) public lockedReward;\n\n    /* Modifiers */\n    modifier isUserAlreadyNotEntered(bytes32 _currEventId) {\n        require(\n            !playerData[_currEventId][_msgSender()].userAccess,\n            \"PayoutPursuit: already registered for current event\"\n        );\n        _;\n    }\n\n    /* Events */\n    event EventStatusUpdated(\n        bytes32 indexed eventId,\n        string indexed status,\n        uint256 timestamp\n    );\n    event TierPercentagesUpdated(\n        uint256 percentageOfDriftking,\n        uint256 percentageOfTop10,\n        uint256 percentageOfTop30,\n        uint256 percentageOfRev\n    );\n    event PriceFeedUpdated(address newPriceFeed);\n    event FeesWalletUpdated(address newFeesWallet);\n    event NFTAddressUpdated(address newNFTAddress);\n    event DeadlineOfClaimUpdated(uint256 newDeadline);\n\n    /* Constructor */\n    /**\n     * @notice Initialize Construction called from proxy initialization\n     * @param _owner                        Owner Address\n     * @param _feesWallet                   Fee Wallet Address\n     * @param _priceFeed                    Price feed contract address by chain link\n     * @param _payoutPursuitNftAddress      Payout Pursuit cars NFT contract address\n     */\n    function initialize(\n        address _owner,\n        address _feesWallet,\n        address _priceFeed,\n        address _payoutPursuitNftAddress\n    ) external initializer {\n        __Ownable_init(_owner);\n        feesWallet = payable(_feesWallet);\n        priceFeed = AggregatorV3Interface(_priceFeed);\n        payoutPursuitNft = IPayoutPursuitCars(_payoutPursuitNftAddress);\n        percentage[PercentageDist.DRIFTKING] = 28.00 * 1000;\n        percentage[PercentageDist.TOP10] = 23.10 * 1000;\n        percentage[PercentageDist.TOP30] = 18.90 * 1000;\n        percentage[PercentageDist.REV] = 30.00 * 1000;\n\n        eventNonce = 0;\n        minParticipants = 5;\n        claimDeadline = 30 days;\n\n        version = \"1\";\n        initialized = true;\n    }\n\n    /*\n     * @notice fallback functions\n     */\n    receive() external payable {}\n\n    fallback() external payable {}\n\n    /**\n     * @notice Internal callable function when player first time entered in event and paid fees and this function checks if the player send required wei to participate.\n     * @param _eventId      Unique ID of event\n     * @return {price in native and usd}\n     */\n    function isFeesOkay(bytes32 _eventId) internal returns (uint256, uint256) {\n        uint256 priceNative = getPriceRate(_eventId);\n        require(msg.value >= priceNative, \"PayoutPursuit: invalid entry fees\");\n        _additionalPoolAmount += (msg.value - priceNative);\n        _totalFeesCollectedAllEvents += priceNative;\n        return (priceNative, eventDetails[_eventId].entryFeesUsd);\n    }\n\n    /**\n     * @notice Internal callable function when create event. It generates unique ID for new event.\n     * @return {new generated event ID}\n     */\n    function generateEventId() internal returns (bytes32) {\n        bytes32 newEventId = bytes32(\n            keccak256(abi.encodePacked(block.timestamp, eventNonce))\n        );\n        eventNonce++;\n        return newEventId;\n    }\n\n    /**\n     * @notice Create new event\n     * @notice Accessable to only allowed address\n     * @param _eventId              Unique ID of event if available, else empty and it generates a new unique event ID\n     * @param _eventName            New event name\n     * @param _eventMapName         Map name of new event\n     * @param _entryFeesInUsd       Event entry fees in USD\n     * @param _openingTime          Opening timestamp of Event\n     * @param _closingTime          Closing timestamp of Event\n     * @param _nftIdForDriftKing    Payout Pursuit car NFT ID for Drift King if available, zero otherwise\n     * @param _nftIdFortop10        Payout Pursuit car NFT ID for Top 10% winners if available, zero otherwise\n     * @param _nftIdFortop30        Payout Pursuit car NFT ID for Top 30% winners if available, zero otherwise\n     */\n    function createEvent(\n        bytes32 _eventId,\n        string memory _eventName,\n        string memory _eventMapName,\n        uint256 _entryFeesInUsd,\n        uint256 _openingTime,\n        uint256 _closingTime,\n        uint256 _nftIdForDriftKing,\n        uint256 _nftIdFortop10,\n        uint256 _nftIdFortop30\n    ) external onlyAllowedAddress nonReentrant returns (bool) {\n        bytes32 raceEvent = _eventId > 0 ? _eventId : generateEventId();\n        require(\n            eventDetails[raceEvent].eventId == 0,\n            \"PayoutPursuit: event id already exists\"\n        );\n        _newEvent(_openingTime, _closingTime, raceEvent);\n        eventDetails[raceEvent] = EventRound({\n            eventId: raceEvent,\n            eventName: _eventName,\n            eventMap: _eventMapName,\n            entryFeesUsd: _entryFeesInUsd,\n            startTimestamp: _openingTime,\n            endTimestamp: _closingTime,\n            totalFeesRaised: 0,\n            totalFeesRaisedInUSD: 0,\n            status: EventStatus.PROGRESS\n        });\n        activeEvents.push(raceEvent);\n        allEvents.push(raceEvent);\n\n        if (\n            _nftIdForDriftKing != 0 ||\n            _nftIdFortop10 != 0 ||\n            _nftIdFortop30 != 0\n        ) {\n            payoutPursuitNft.setupIdsForEvent(\n                raceEvent,\n                _nftIdForDriftKing,\n                _nftIdFortop10,\n                _nftIdFortop30\n            );\n        }\n        return true;\n    }\n\n    /**\n     * @notice Update event\n     * @notice Accessable to only allowed address\n     * @param _entryFeesInUsd       Event entry fees in USD\n     * @param _eventName            Event new name if needs update, empty otherwise\n     * @param _eventMap             Map name of event if needs update, empty otherwise\n     * @param _eventId              Existing unique ID of event\n     */\n    function updateEvent(\n        uint256 _entryFeesInUsd,\n        string memory _eventName,\n        string memory _eventMap,\n        bytes32 _eventId\n    ) external onlyAllowedAddress nonReentrant {\n        if (_entryFeesInUsd > 0) {\n            eventDetails[_eventId].entryFeesUsd = _entryFeesInUsd;\n        }\n        if (!compareStrings(_eventName, \"\")) {\n            eventDetails[_eventId].eventName = _eventName;\n        }\n        if (!compareStrings(_eventMap, \"\")) {\n            eventDetails[_eventId].eventMap = _eventMap;\n        }\n    }\n\n    /**\n     * @notice Extend event time\n     * @notice Accessable to only owner\n     * @param _newClosingTime       New closing timestamp\n     * @param _eventId              Existing unique ID of event\n     */\n    function extendEventTime(uint256 _newClosingTime, bytes32 _eventId)\n        public\n        onlyOwner\n        nonReentrant\n    {\n        _extendEventTime(_newClosingTime, _eventId);\n        eventDetails[_eventId].endTimestamp = _newClosingTime;\n    }\n\n    /**\n     * @notice Cancel event if not\n     * @notice Accessable to only owner\n     * @param _refundToPlayers      Refund to players pass true, false otherwise\n     * @param _eventId              Existing unique ID of event\n     * @param _force                If true, no checking of minimum participants joined as well as no checking of already event closed and forcedly cancelled\n     */\n    function cancelEvent(\n        bool _refundToPlayers,\n        bytes32 _eventId,\n        bool _force\n    ) external onlyOwner nonReentrant {\n        EventRound storage _eventDetails = eventDetails[_eventId];\n        require(\n            _eventDetails.status != EventStatus.CANCELLED,\n            \"PayoutPursuit: event already cancelled\"\n        );\n\n        // Check if event already closed and no user has been participated\n        if (getTotalPlayers(_eventId).length >= minParticipants && !_force) {\n            require(!hasClosed(_eventId), \"PayoutPursuitTime: already closed\");\n        }\n        _cancelEvent(_eventId);\n        _eventDetails.endTimestamp = closingTime(_eventId);\n        _eventDetails.status = EventStatus.CANCELLED;\n\n        if (_refundToPlayers) {\n            lockedReward[_eventId] = RewardLocked({\n                amount: _eventDetails.totalFeesRaised,\n                deadline: block.timestamp + claimDeadline\n            });\n\n            eventStoppedAndRefund[_eventId] = _refundToPlayers;\n        }\n\n        payoutPursuitNft.removeAllIdsOfEvent(_eventId);\n\n        emit EventStatusUpdated(_eventId, \"CANCELLED\", block.timestamp);\n    }\n\n    /**\n     * @notice Pause event if open and not already paused\n     * @notice Accessable to only owner\n     * @param _eventId              Existing unique ID of event\n     */\n    function pauseEvent(bytes32 _eventId)\n        external\n        onlyOwner\n        onlyWhileOpen(_eventId)\n        nonReentrant\n    {\n        _pauseEvent(_eventId);\n\n        emit EventStatusUpdated(_eventId, \"PAUSED\", block.timestamp);\n    }\n\n    /**\n     * @notice Resume event if already paused\n     * @notice Accessable to only owner\n     * @param _eventId              Existing unique ID of event\n     * @param _newClosingTime       New closing timestamp if needs to extend, zero otherwise\n     */\n    function unpauseEvent(bytes32 _eventId, uint256 _newClosingTime)\n        external\n        onlyOwner\n        nonReentrant\n    {\n        if (_newClosingTime != 0) {\n            extendEventTime(_newClosingTime, _eventId);\n        }\n        _unpauseEvent(_eventId);\n\n        emit EventStatusUpdated(_eventId, \"ACTIVE\", block.timestamp);\n    }\n\n    /**\n     * @notice Participate in event by entry and pay fees.\n     * @param _eventId              Existing unique ID of event\n     */\n    function entryInEvent(bytes32 _eventId)\n        external\n        payable\n        onlyWhileOpen(_eventId)\n        isEventPaused(_eventId)\n        isUserAlreadyNotEntered(_eventId)\n        nonReentrant\n    {\n        (uint256 feesNative, uint256 feesUsd) = isFeesOkay(_eventId);\n        eventDetails[_eventId].totalFeesRaised += feesNative;\n        eventDetails[_eventId].totalFeesRaisedInUSD += feesUsd;\n        _playerEntered(\n            _eventId,\n            _msgSender(),\n            block.timestamp,\n            feesNative,\n            feesUsd\n        );\n    }\n\n    /**\n     * @notice Submit user addresses when event completed.\n     * @notice Accessable to only owner\n     * @param _eventId          Existing unique ID of event\n     * @param _playerDK         Array of addresses of Drift King if multiple rarely, otherwise only one address i.e Just ONE Drift King\n     * @param _playersTop10     Array of addresses of Top 10% winners\n     * @param _playersTop30     Array of addresses of Top 30% winners\n     * @param isLocked          True if submission is final and verified and should lock for permanent, false otherwise\n     */\n    function submitUsersData(\n        bytes32 _eventId,\n        address[] memory _playerDK,\n        address[] memory _playersTop10,\n        address[] memory _playersTop30,\n        bool isLocked\n    )\n        external\n        onlyOwner\n        nonReentrant\n        onlyWhenClosed(_eventId)\n        returns (bytes[] memory x)\n    {\n        require(\n            !eventLeaderboardLocked[_eventId],\n            \"PayoutPursuit: event leaderboard locked\"\n        );\n        require(\n            _eventId != 0 && eventDetails[_eventId].eventId != 0,\n            \"PayoutPursuit: event id invalid\"\n        );\n        {\n            bytes[] memory y = new bytes[](3);\n            y[0] = encode(_eventId, PercentageDist.DRIFTKING, _playerDK);\n            y[1] = encode(_eventId, PercentageDist.TOP10, _playersTop10);\n            y[2] = encode(_eventId, PercentageDist.TOP30, _playersTop30);\n            x = y;\n        }\n        _removeFromArray(activeEvents, _eventId);\n        eventDetails[_eventId].status = EventStatus.COMPLETED;\n\n        emit EventStatusUpdated(_eventId, \"COMPLETED\", block.timestamp);\n\n        if (isLocked) {\n            lockLeaderboard(_eventId);\n        }\n    }\n\n    /**\n     * @notice Lock leaderboard of completed event if not already locked and data already submitted.\n     * @notice Accessable to only owner\n     * @param _eventId      Existing unique ID of event\n     */\n    function lockLeaderboard(bytes32 _eventId) public onlyOwner {\n        (\n            address[] memory _playersTop10,\n            address[] memory _playersTop30,\n            address[] memory _playerDK\n        ) = getUsersData(_eventId);\n\n        require(\n            (_playersTop10.length > 0 || _playersTop30.length > 0) &&\n                _playerDK.length > 0,\n            \"PayoutPursuit: leaderboard not found\"\n        );\n\n        eventLeaderboardLocked[_eventId] = true;\n\n        uint256 _totalFeesRaised = eventDetails[_eventId].totalFeesRaised;\n        uint256 _eventRev = (_totalFeesRaised *\n            percentage[PercentageDist.REV]) / 10**5;\n        rewardDistribution[_eventId][PercentageDist.DRIFTKING] =\n            (_totalFeesRaised * percentage[PercentageDist.DRIFTKING]) /\n            10**5;\n        rewardDistribution[_eventId][PercentageDist.TOP10] = _playersTop10\n            .length > 0\n            ? ((_totalFeesRaised * percentage[PercentageDist.TOP10]) / 10**5) /\n                _playersTop10.length\n            : 0;\n        rewardDistribution[_eventId][PercentageDist.TOP30] = _playersTop30\n            .length > 0\n            ? ((_totalFeesRaised * percentage[PercentageDist.TOP30]) / 10**5) /\n                _playersTop30.length\n            : 0;\n        lockedReward[_eventId] = RewardLocked({\n            amount: _totalFeesRaised - _eventRev,\n            deadline: block.timestamp + claimDeadline\n        });\n        _transferNative(feesWallet, _eventRev);\n    }\n\n    /**\n     * @notice Claim refund of cancelled event by the participants if available\n     * @param _eventId          Existing unique ID of event\n     */\n    function claimRefund(bytes32 _eventId) external nonReentrant {\n        require(\n            eventStoppedAndRefund[_eventId] &&\n                block.timestamp <= lockedReward[_eventId].deadline,\n            \"PayoutPursuit: no refunds available\"\n        );\n        require(\n            !eventClaims[_eventId][_msgSender()],\n            \"PayoutPursuit: already claimed\"\n        );\n        PlayerData memory _playerData = playerData[_eventId][_msgSender()];\n        require(\n            _playerData.userAccess &&\n                _playerData.player == _msgSender() &&\n                _playerData.player != address(0),\n            \"PayoutPursuit: invalid address\"\n        );\n\n        eventClaims[_eventId][_msgSender()] = true;\n\n        uint256 _refundAmount = min(\n            _playerData.feesPaidInNative,\n            address(this).balance\n        );\n\n        lockedReward[_eventId].amount -= _refundAmount;\n\n        require(\n            _refundAmount > 0,\n            \"PayoutPursuit: insufficient funds, please contact support\"\n        );\n\n        _transferNative(_msgSender(), _refundAmount);\n    }\n\n    /**\n     * @notice Internally called function from \"isRewardAvailable\"\n     * @param _eventId      Existing unique ID of event\n     * @param _per          Tier of players (0 for DRIFTKING, 1 for TOP10, 2 for TOP30)\n     * @return  {Per player reward}\n     */\n    function playerRewardCalculation(bytes32 _eventId, PercentageDist _per)\n        internal\n        view\n        returns (uint256)\n    {\n        return rewardDistribution[_eventId][_per];\n    }\n\n    /**\n     * @notice Claim reward by participant if wins and claim available\n     * @param _eventId      Existing unique ID of event\n     */\n    function claimReward(bytes32 _eventId)\n        external\n        nonReentrant\n        onlyWhenClosed(_eventId)\n    {\n        require(\n            !eventClaims[_eventId][_msgSender()],\n            \"PayoutPursuit: already claimed\"\n        );\n\n        PlayerData storage _playerData = playerData[_eventId][_msgSender()];\n\n        uint256 calculatedReward = 0;\n        PercentageDist rank = PercentageDist.NONE;\n\n        if (lockedReward[_eventId].deadline >= block.timestamp) {\n            (\n                uint256 _calculatedReward,\n                PercentageDist _rank,\n\n            ) = isRewardAvailable(_eventId, _msgSender());\n\n            calculatedReward = _calculatedReward;\n            rank = _rank;\n        }\n\n        require(\n            calculatedReward > 0,\n            \"PayoutPursuit: no claim available or already claimed\"\n        );\n\n        eventClaims[_eventId][_msgSender()] = true;\n\n        _playerData.claimTimestamp = block.timestamp;\n        _playerData.rank = rank;\n        _playerData.player = _msgSender();\n\n        uint256 reward = min(calculatedReward, address(this).balance);\n\n        lockedReward[_eventId].amount -= reward;\n\n        if (rank != PercentageDist.NONE) {\n            uint256 _nftId = payoutPursuitNft.getTokenPerEvent(\n                _eventId,\n                uint8(rank)\n            );\n            if (payoutPursuitNft.balanceOf(_msgSender(), _nftId) == 0) {\n                payoutPursuitNft.mint(_msgSender(), _nftId, 1, \"\");\n            }\n        }\n\n        require(\n            reward > 0,\n            \"PayoutPursuit: insufficient funds, please contact support\"\n        );\n\n        _transferNative(_msgSender(), reward);\n    }\n\n    /**\n     * @notice Check if reward available for participant\n     * @param _eventId      Existing unique ID of event\n     * @param _user         Address of Participant\n     * @return {Amount, Tier, true if already claimed otherwise false}\n     */\n    function isRewardAvailable(bytes32 _eventId, address _user)\n        public\n        view\n        returns (\n            uint256,\n            PercentageDist,\n            bool\n        )\n    {\n        (\n            address[] memory _playersTop10,\n            address[] memory _playersTop30,\n            address[] memory _playerDK\n        ) = getUsersData(_eventId);\n\n        address _playerData;\n        PercentageDist _per = PercentageDist.NONE;\n\n        if (_playerDK.length > 0) {\n            for (uint8 i = 0; i < _playerDK.length; i++) {\n                if (_playerDK[i] == _user) {\n                    _playerData = _playerDK[i];\n                    _per = PercentageDist.DRIFTKING;\n                    break;\n                }\n            }\n        }\n\n        if (_per == PercentageDist.NONE) {\n            for (uint256 j = 0; j < _playersTop10.length; j++) {\n                if (_playersTop10[j] == _user) {\n                    _playerData = _playersTop10[j];\n                    _per = PercentageDist.TOP10;\n                    break;\n                }\n            }\n        }\n\n        if (_per == PercentageDist.NONE) {\n            for (uint256 k = 0; k < _playersTop30.length; k++) {\n                if (_playersTop30[k] == _user) {\n                    _playerData = _playersTop30[k];\n                    _per = PercentageDist.TOP30;\n                    break;\n                }\n            }\n        }\n\n        if (_per == PercentageDist.NONE) {\n            return (0, _per, false);\n        }\n\n        return (\n            min(\n                playerRewardCalculation(_eventId, _per),\n                lockedReward[_eventId].amount\n            ),\n            _per,\n            eventClaims[_eventId][_user]\n        );\n    }\n\n    /**\n     * @notice Update percentages of Tiers (in multiplication with 1000)\n     * @notice Accessable to only owner\n     * @param _driftking    Percentage for Drift King Tier\n     * @param _top10        Percentage for Top 10% Tier\n     * @param _top30        Percentage for Top 30% Tier\n     * @param _rev          Percentage for Platform revenue Tier\n     */\n    function updatePercentages(\n        uint256 _driftking,\n        uint256 _top10,\n        uint256 _top30,\n        uint256 _rev\n    ) external onlyOwner {\n        percentage[PercentageDist.DRIFTKING] = _driftking;\n        percentage[PercentageDist.TOP10] = _top10;\n        percentage[PercentageDist.TOP30] = _top30;\n        percentage[PercentageDist.REV] = _rev;\n        emit TierPercentagesUpdated(_driftking, _top10, _top30, _rev);\n    }\n\n    /**\n     * @notice Update price feed address of chain link\n     * @notice Accessable to only owner\n     * @param _priceFeed    New address of Price Feed\n     */\n    function updatePriceFeed(address _priceFeed) external onlyOwner {\n        priceFeed = AggregatorV3Interface(_priceFeed);\n        emit PriceFeedUpdated(_priceFeed);\n    }\n\n    /**\n     * @notice Update fees wallet address\n     * @notice Accessable to only owner\n     * @param _feesWallet    New address of Fees wallet\n     */\n    function updateFeesWallet(address _feesWallet) external onlyOwner {\n        feesWallet = payable(_feesWallet);\n        emit FeesWalletUpdated(_feesWallet);\n    }\n\n    /**\n     * @notice Update NFT contract address\n     * @notice Accessable to only owner\n     * @param _payoutPursuitNft    New address of NFT contract\n     */\n    function updatePayoutPursuitNftAddress(address _payoutPursuitNft)\n        external\n        onlyOwner\n    {\n        payoutPursuitNft = IPayoutPursuitCars(_payoutPursuitNft);\n        emit NFTAddressUpdated(_payoutPursuitNft);\n    }\n\n    /**\n     * @notice Update claim deadline in days\n     * @notice Accessable to only owner\n     * @param _newDeadlineInDays    New deadline in days\n     */\n    function updateClaimDeadline(uint256 _newDeadlineInDays)\n        external\n        onlyOwner\n    {\n        claimDeadline = _newDeadlineInDays * 1 days;\n        emit DeadlineOfClaimUpdated(_newDeadlineInDays);\n    }\n\n    /**\n     * @notice Get submitted data of addresses of completed events\n     * @param _eventId      Existing unique ID of event\n     * @return top10        Addresses of Top 10% winners\n     * @return top30        Addresses of Top 30% winners\n     * @return dk           Address(es) of Drift King\n     */\n    function getUsersData(bytes32 _eventId)\n        public\n        view\n        returns (\n            address[] memory top10,\n            address[] memory top30,\n            address[] memory dk\n        )\n    {\n        bytes[] memory _encodedData1 = encodeData[_eventId][\n            PercentageDist.DRIFTKING\n        ];\n        bytes[] memory _encodedData2 = encodeData[_eventId][\n            PercentageDist.TOP10\n        ];\n        bytes[] memory _encodedData3 = encodeData[_eventId][\n            PercentageDist.TOP30\n        ];\n        if (_encodedData1.length > 0) {\n            dk = decode(\n                _eventId,\n                PercentageDist.DRIFTKING,\n                _encodedData1[_encodedData1.length - 1]\n            );\n        }\n        if (_encodedData2.length > 0) {\n            top10 = decode(\n                _eventId,\n                PercentageDist.TOP10,\n                _encodedData2[_encodedData2.length - 1]\n            );\n        }\n        if (_encodedData3.length > 0) {\n            top30 = decode(\n                _eventId,\n                PercentageDist.TOP30,\n                _encodedData3[_encodedData3.length - 1]\n            );\n        }\n    }\n\n    /**\n     * @notice Get all event IDs that ever created\n     * @return x    All IDs of events\n     */\n    function getAllEvents() external view returns (bytes32[] memory x) {\n        return allEvents;\n    }\n\n    /**\n     * @notice Get all active event IDs\n     * @return x    All IDs of active events\n     */\n    function getActiveEvents() external view returns (bytes32[] memory x) {\n        x = new bytes32[](activeEvents.length);\n        uint256 _index = 0;\n        bool _isClosed = false;\n        for (uint8 i = 0; i < activeEvents.length; i++) {\n            if (isEventOpen(activeEvents[i])) {\n                x[_index] = activeEvents[i];\n                _index++;\n            } else {\n                _isClosed = true;\n            }\n        }\n\n        if (_isClosed) {\n            bytes32[] memory _temp = new bytes32[](_index);\n            for (uint8 j = 0; j < _index; j++) {\n                _temp[j] = x[j];\n            }\n            x = _temp;\n        }\n    }\n\n    /**\n     * @notice Get all inactive event IDs\n     * @return completed    All IDs of completed events\n     * @return cancelled    All IDs of cancelled events\n     * @return paused       All IDs of paused events\n     * @return pending      All IDs of events that will active soon\n     * @return process      All IDs of events that closed and leaderboard submission is pending\n     */\n    function getInactiveEvents()\n        external\n        view\n        returns (\n            bytes32[] memory completed,\n            bytes32[] memory cancelled,\n            bytes32[] memory paused,\n            bytes32[] memory pending,\n            bytes32[] memory process\n        )\n    {\n        bytes32[] memory tempCompleted = new bytes32[](allEvents.length);\n        bytes32[] memory tempCancelled = new bytes32[](allEvents.length);\n        bytes32[] memory tempPaused = new bytes32[](allEvents.length);\n        bytes32[] memory tempPending = new bytes32[](allEvents.length);\n        bytes32[] memory tempProcess = new bytes32[](allEvents.length);\n        {\n            uint256 completedCount;\n            uint256 cancelledCount;\n            uint256 pausedCount;\n            uint256 pendingCount;\n            uint256 processCount;\n\n            for (uint8 i = 0; i < allEvents.length; i++) {\n                bytes32 v = allEvents[i];\n                if (eventDetails[v].status == EventStatus.COMPLETED) {\n                    tempCompleted[completedCount++] = v;\n                }\n                if (eventDetails[v].status == EventStatus.CANCELLED) {\n                    tempCancelled[cancelledCount++] = v;\n                }\n                if (\n                    eventPaused[v] &&\n                    eventDetails[v].status == EventStatus.PROGRESS\n                ) {\n                    tempPaused[pausedCount++] = v;\n                }\n                if (\n                    openingTime(v) > block.timestamp &&\n                    eventDetails[v].status == EventStatus.PROGRESS\n                ) {\n                    tempPending[pendingCount++] = v;\n                }\n                if (\n                    hasClosed(v) &&\n                    eventDetails[v].status == EventStatus.PROGRESS\n                ) {\n                    tempProcess[processCount++] = v;\n                }\n            }\n\n            completed = new bytes32[](completedCount);\n            cancelled = new bytes32[](cancelledCount);\n            paused = new bytes32[](pausedCount);\n            pending = new bytes32[](pendingCount);\n            process = new bytes32[](processCount);\n        }\n\n        for (uint256 j = 0; j < completed.length; j++) {\n            completed[j] = tempCompleted[j];\n        }\n        for (uint256 k = 0; k < cancelled.length; k++) {\n            cancelled[k] = tempCancelled[k];\n        }\n        for (uint256 l = 0; l < paused.length; l++) {\n            paused[l] = tempPaused[l];\n        }\n        for (uint256 m = 0; m < pending.length; m++) {\n            pending[m] = tempPending[m];\n        }\n        for (uint256 n = 0; n < process.length; n++) {\n            process[n] = tempProcess[n];\n        }\n    }\n\n    /**\n     * @notice Get detail about event\n     * @param _eventId                  Existing unique ID of event\n     * @return eventId                  Event ID\n     * @return eventName                Name of event\n     * @return eventMap                 Name of event map\n     * @return entryFeesUsd             Entry fees in USD\n     * @return startTimestamp           Event start time\n     * @return endTimestamp             Event end time\n     * @return totalFeesRaised          Total fees raised in event\n     * @return totalFeesRaisedInUSD     Total fees raised in event in USD\n     * @return status                   Current status of event\n     * @return nftUri                   URI of all NFTs of event\n     */\n    function getEventDetails(bytes32 _eventId)\n        public\n        view\n        returns (\n            bytes32 eventId,\n            string memory eventName,\n            string memory eventMap,\n            uint256 entryFeesUsd,\n            uint256 startTimestamp,\n            uint256 endTimestamp,\n            uint256 totalFeesRaised,\n            uint256 totalFeesRaisedInUSD,\n            string memory status,\n            string[] memory nftUri\n        )\n    {\n        EventRound memory _event = eventDetails[_eventId];\n        string memory _eventStatus;\n        if (_event.status == EventStatus.PROGRESS) {\n            _eventStatus = \"ACTIVE\";\n            if (_event.startTimestamp == 0) {\n                _eventStatus = \"NOTEXIST\";\n            } else if (eventPaused[_eventId]) {\n                _eventStatus = \"PAUSED\";\n            } else if (openingTime(_eventId) > block.timestamp) {\n                _eventStatus = \"PENDING\";\n            } else if (hasClosed(_eventId)) {\n                _eventStatus = \"PROCESS\";\n            }\n        } else if (_event.status == EventStatus.COMPLETED) {\n            _eventStatus = \"COMPLETED\";\n        } else if (_event.status == EventStatus.CANCELLED) {\n            _eventStatus = \"CANCELLED\";\n        }\n\n        string[] memory _uris = new string[](3);\n        (_uris[0], _uris[1], _uris[2]) = payoutPursuitNft.uriPerEvent(_eventId);\n\n        return (\n            _event.eventId,\n            _event.eventName,\n            _event.eventMap,\n            _event.entryFeesUsd,\n            _event.startTimestamp,\n            _event.endTimestamp,\n            _event.totalFeesRaised,\n            _event.totalFeesRaisedInUSD,\n            _eventStatus,\n            _uris\n        );\n    }\n\n    /**\n     * @notice Get Native value from USD\n     * @param _amount       Amount in USD\n     * @return {amount in native}\n     */\n    function getPriceUsdToNative(uint256 _amount)\n        public\n        view\n        returns (uint256)\n    {\n        (, int256 price, , , ) = priceFeed.latestRoundData();\n        uint256 adjust_price = uint256(price) * 1e10;\n        uint256 usd = _amount;\n        uint256 rate = (usd * 1e18) / adjust_price;\n        return rate;\n    }\n\n    /**\n     * @notice Get event fees rate in native from USD\n     * @param _eventId      Existing unique ID of event\n     * @return {event fees in native}\n     */\n    function getPriceRate(bytes32 _eventId) public view returns (uint256) {\n        uint256 feeInUSD = eventDetails[_eventId].entryFeesUsd;\n        uint256 rate = getPriceUsdToNative(feeInUSD);\n        return rate;\n    }\n\n    /**\n     * @notice Deposit Reward to Pool for winners\n     * @notice Accessable to only owner\n     * @param _amount       Amount in wei\n     * @param _eventId      Existing unique ID of event\n     * @return {True or False}\n     */\n    function depositToRewardPool(uint256 _amount, bytes32 _eventId)\n        public\n        payable\n        onlyOwner\n        returns (bool)\n    {\n        require(\n            eventDetails[_eventId].startTimestamp != 0,\n            \"PayoutPursuit: invalid event id\"\n        );\n        require(msg.value >= _amount, \"PayoutPursuit: insufficient amount\");\n        _additionalPoolAmount += (msg.value - _amount);\n        _totalFeesCollectedAllEvents += _amount;\n        additionalRewardToPool[_eventId] += _amount;\n        eventDetails[_eventId].totalFeesRaised += _amount;\n        eventDetails[_eventId].totalFeesRaisedInUSD += getPriceNativeToUSD(\n            _amount\n        );\n        return true;\n    }\n\n    /**\n     * @notice Withdraw funds if available\n     * @notice Accessable to only owner\n     * @param _eventId      Existing unique ID of event\n     */\n    function withdrawFunds(bytes32 _eventId) public onlyOwner {\n        // Admin can withdraw funds if winners not claimed within 1 month\n        require(\n            block.timestamp >= lockedReward[_eventId].deadline,\n            \"PayoutPursuit: event rewards locked for winners to claim\"\n        );\n        _transferNative(\n            feesWallet,\n            min(lockedReward[_eventId].amount, address(this).balance)\n        );\n    }\n\n    /**\n     * @notice Withdraw other funds if available\n     * @notice Accessable to only owner\n     * @param _token    Token address or (zero address for Native)\n     */\n    function withdrawAdditionalFunds(address _token) public onlyOwner {\n        if (_token != address(0)) {\n            uint256 _balance = IERC20(_token).balanceOf(address(this));\n            require(\n                _balance > 0,\n                \"PayoutPursuit: insufficient contract balance\"\n            );\n            require(IERC20(_token).transfer(feesWallet, _balance));\n        } else {\n            require(\n                address(this).balance > 0,\n                \"PayoutPursuit: insufficient contract balance\"\n            );\n            _transferNative(\n                feesWallet,\n                min(_additionalPoolAmount, address(this).balance)\n            );\n            _additionalPoolAmount = 0;\n        }\n    }\n\n    /**\n     * @notice Internally called when transferring native amounts\n     * @param _recipient    Recipient address\n     * @param _amount       Amount in wei\n     */\n    function _transferNative(address _recipient, uint256 _amount) internal {\n        (bool sent, ) = payable(_recipient).call{value: _amount}(\"\");\n        require(sent);\n    }\n\n    mapping(bytes32 => uint256) public additionalRewardToPool;\n\n    /**\n     * @notice Get USD value from Native\n     * @param _amount       Amount in Native\n     * @return {amount in USD}\n     */\n    function getPriceNativeToUSD(uint256 _amount)\n        public\n        view\n        returns (uint256)\n    {\n        (, int256 price, , , ) = priceFeed.latestRoundData();\n        uint256 ethPrice = uint256(price) / 10**priceFeed.decimals();\n        uint256 native = _amount;\n        uint256 rate = native * ethPrice;\n        return rate;\n    }\n\n    /**\n     * @notice Get total rewards ever exists combined of all events\n     * @return {amount in Native}\n     */\n    function getTotalRewardsOfAllEvents() external view returns (uint256) {\n        return _totalFeesCollectedAllEvents;\n    }\n\n    /**\n     * @notice Withdraw additional added rewards from pool if available\n     * @notice Accessable to only owner\n     * @param _eventId      Existing unique ID of event\n     * @param _amount       Amount in wei\n     */\n    function withdrawAdditionalAddedRewardFundsFromPool(\n        bytes32 _eventId,\n        uint256 _amount\n    ) public onlyOwner {\n        require(\n            address(this).balance > 0,\n            \"PayoutPursuit: insufficient contract balance\"\n        );\n        require(\n            _amount <= additionalRewardToPool[_eventId],\n            \"PayoutPursuit: amount more than additional added reward\"\n        );\n        _transferNative(owner(), min(_amount, address(this).balance));\n        additionalRewardToPool[_eventId] -= _amount;\n        _totalFeesCollectedAllEvents -= _amount;\n        eventDetails[_eventId].totalFeesRaised -= _amount;\n        eventDetails[_eventId].totalFeesRaisedInUSD -= getPriceNativeToUSD(\n            _amount\n        );\n    }\n\n    function fix_v1(uint256 _amountDeposited, bytes32 _eventId) internal {\n        if(_amountDeposited > 0) {\n            additionalRewardToPool[_eventId] += _amountDeposited;\n            eventDetails[_eventId].totalFeesRaisedInUSD += getPriceNativeToUSD(\n                _amountDeposited\n            );\n        }\n    }\n}\n\ncontract PayoutPursuit_v1_1 is PayoutPursuit {\n    bool public initialized_v1_1 = false;\n\n    /* Constructor v1.1*/\n    /**\n     * @notice Initialize Construction called from proxy initialization\n     * @notice Upgrade to fixed deposit pool reward\n     * @param _amountDeposited      Amount deposited in game pool\n     */\n    function initialize_v1_1(uint256 _amountDeposited, bytes32 _eventId)\n        external\n        onlyOwner\n    {\n        require(!initialized_v1_1, \"PayoutPursuit: already initialized\");\n        fix_v1(_amountDeposited, _eventId);\n        version = \"1.1\";\n        initialized_v1_1 = true;\n    }\n}\n"
      },
      ".deps/payout deployment/utils/Utils.sol": {
        "content": "/**\r\n * SPDX-License-Identifier: Apache-2.0\r\n *\r\n * Copyright (c) 2023, DriftToken | DecentraCrew.\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n\r\npragma solidity ^0.8.9;\r\n\r\ncontract Utils {\r\n\r\n    /**\r\n     * @notice Helper function to find the minimum of two values.\r\n     * @param a     Number 1\r\n     * @param b     Number 2\r\n     * @return {Minimum number} \r\n     */\r\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\r\n        return a < b ? a : b;\r\n    }\r\n\r\n    /**\r\n     * @notice Helper internal function to remove specific value from an array\r\n     * @param _data     Array data\r\n     * @param _target   Item to find in array and remove\r\n     */\r\n    function _removeFromArray(bytes32[] storage _data, bytes32 _target)\r\n        internal\r\n    {\r\n        if (_data.length > 0) {\r\n            uint256 index = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;\r\n            uint256 i = 0;\r\n            uint256 j = _data.length - 1;\r\n            while (i <= j) {\r\n                if (_data[i] == _target) {\r\n                    index = i;\r\n                    break;\r\n                }\r\n                if (_data[j] == _target) {\r\n                    index = j;\r\n                    break;\r\n                }\r\n                i++;\r\n                j--;\r\n            }\r\n            if (\r\n                index !=\r\n                0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\r\n            ) {\r\n                _data[index] = _data[_data.length - 1];\r\n                _data.pop();\r\n            }\r\n        }\r\n    }\r\n\r\n    /**\r\n     * @notice Implementation of comparision of strings.\r\n     * @param s1    String 1\r\n     * @param s2    String 2\r\n     * @return {True or False}\r\n     */\r\n    function compareStrings(string memory s1, string memory s2)\r\n        internal\r\n        pure\r\n        returns (bool)\r\n    {\r\n        return\r\n            keccak256(abi.encodePacked(s1)) == keccak256(abi.encodePacked(s2));\r\n    }\r\n}"
      },
      ".deps/payout deployment/utils/AllowableAddress.sol": {
        "content": "// SPDX-License-Identifier: MIT\r\npragma solidity ^0.8.4;\r\n\r\nimport {OwnableUpgradeable} from \"@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol\";\r\n\r\ncontract AllowableAddress is OwnableUpgradeable {\r\n    /******* Variables *******/\r\n    // allowed address => bool\r\n    mapping(address => bool) private allowedAddress;\r\n    // blacklist address => bool\r\n    mapping(address => bool) private blacklistAddress;\r\n\r\n    /******* Modifiers *******/\r\n    modifier onlyAllowedAddress() {\r\n        require(\r\n            allowedAddress[_msgSender()] == true ||\r\n                owner() == _msgSender(),\r\n            \"You are not allowed.\"\r\n        );\r\n        _;\r\n    }\r\n\r\n    modifier blacklistCheck() {\r\n        require(!blacklistAddress[_msgSender()], \"Address is blacklisted\");\r\n        _;\r\n    }\r\n\r\n    /******* Events *******/\r\n    event BlacklistUpdated(bool status);\r\n\r\n    /******* Constructor *******/\r\n    function __AllowableAddress_init(address _ownerAddress) internal {\r\n        __Ownable_init(_ownerAddress);\r\n    }\r\n\r\n    /**\r\n     * @notice Disallow the address and remove from onlyAllowedAddress\r\n     * @param _address  Any address\r\n     */\r\n    function disallowAddress(address _address) public onlyOwner {\r\n        require(\r\n            allowedAddress[_address] == true,\r\n            \"The address is already not allowed.\"\r\n        );\r\n        allowedAddress[_address] = true;\r\n    }\r\n\r\n    /**\r\n     * @notice Allow the address and add to onlyAllowedAddress\r\n     * @param _address  Any address\r\n     */\r\n    function allowAddress(address _address) public onlyOwner {\r\n        require(\r\n            allowedAddress[_address] == false,\r\n            \"The address is already allowed.\"\r\n        );\r\n        allowedAddress[_address] = true;\r\n    }\r\n\r\n    /**\r\n     * @notice Manage blacklisting to restrict addresses\r\n     * @param addresses     Any addresses\r\n     * @param status        true or false\r\n     */\r\n    function manageBlacklist(address[] calldata addresses, bool status)\r\n        external\r\n        virtual\r\n        onlyAllowedAddress\r\n    {\r\n        for (uint256 i; i < addresses.length; ++i) {\r\n            blacklistAddress[addresses[i]] = status;\r\n        }\r\n        emit BlacklistUpdated(status);\r\n    }\r\n\r\n    /**\r\n     * @param _address  Any address\r\n     * @return {The address is allowed or not allowed}\r\n     */\r\n    function isAddressAllowed(address _address) public view returns (bool) {\r\n        return allowedAddress[_address];\r\n    }\r\n\r\n    /**\r\n     * @param _address  Any address\r\n     * @return {The address is blacklisted or not}\r\n     */\r\n    function isBlacklisted(address _address) public view returns (bool) {\r\n        return blacklistAddress[_address];\r\n    }\r\n}\r\n"
      },
      "@openzeppelin/contracts/utils/math/SafeMath.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n    /**\n     * @dev Returns the addition of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            uint256 c = a + b;\n            if (c < a) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b > a) return (false, 0);\n            return (true, a - b);\n        }\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n            // benefit is lost if 'b' is also tested.\n            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n            if (a == 0) return (true, 0);\n            uint256 c = a * b;\n            if (c / a != b) return (false, 0);\n            return (true, c);\n        }\n    }\n\n    /**\n     * @dev Returns the division of two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a / b);\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n     *\n     * _Available since v3.4._\n     */\n    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n        unchecked {\n            if (b == 0) return (false, 0);\n            return (true, a % b);\n        }\n    }\n\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a + b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a - b;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a * b;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator.\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a / b;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a % b;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {trySub}.\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b <= a, errorMessage);\n            return a - b;\n        }\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a / b;\n        }\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * reverting with custom message when dividing by zero.\n     *\n     * CAUTION: This function is deprecated because it requires allocating memory for the error\n     * message unnecessarily. For custom revert reasons use {tryMod}.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        unchecked {\n            require(b > 0, errorMessage);\n            return a % b;\n        }\n    }\n}\n"
      },
      ".deps/payout deployment/extension/PayoutPursuitPlayer.sol": {
        "content": "/**\r\n * SPDX-License-Identifier: Apache-2.0\r\n *\r\n * Copyright (c) 2024, DriftToken\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n\r\npragma solidity ^0.8.20;\r\n\r\nabstract contract PayoutPursuitPlayer {\r\n    enum PercentageDist {\r\n        DRIFTKING,\r\n        TOP10,\r\n        TOP30,\r\n        REV,\r\n        NONE\r\n    }\r\n\r\n    struct PlayerData {\r\n        address player;\r\n        PercentageDist rank;\r\n        uint256 feesPaidInNative;\r\n        uint256 feesPaidInUsd;\r\n        uint256 eventRegisterTimestamp;\r\n        uint256 claimTimestamp;\r\n        bool userAccess;\r\n    }\r\n\r\n    mapping(bytes32 => mapping(address => PlayerData)) public playerData;\r\n    mapping(bytes32 => address[]) private totalPlayers;\r\n    mapping(bytes32 => mapping(PercentageDist => bytes[])) internal encodeData;\r\n\r\n    event PlayerEntry(\r\n        bytes32 indexed currEvent,\r\n        address indexed player,\r\n        uint256 regTimestamp\r\n    );\r\n\r\n    function _playerEntered(\r\n        bytes32 _eventId,\r\n        address _player,\r\n        uint256 _regTimestamp,\r\n        uint256 _feesNative,\r\n        uint256 _feesUsd\r\n    ) internal {\r\n        playerData[_eventId][_player] = PlayerData({\r\n            player: _player,\r\n            rank: PercentageDist.NONE,\r\n            feesPaidInNative: _feesNative,\r\n            feesPaidInUsd: _feesUsd,\r\n            eventRegisterTimestamp: _regTimestamp,\r\n            claimTimestamp: 0,\r\n            userAccess: true\r\n        });\r\n        totalPlayers[_eventId].push(_player);\r\n        emit PlayerEntry(_eventId, _player, _regTimestamp);\r\n    }\r\n\r\n    function encode(\r\n        bytes32 _eventId,\r\n        PercentageDist _percent,\r\n        address[] memory x\r\n    ) internal returns (bytes memory) {\r\n        bytes memory encoded = abi.encode(x);\r\n        encodeData[_eventId][_percent].push(encoded);\r\n        return encoded;\r\n    }\r\n\r\n    function decode(\r\n        bytes32 _eventId,\r\n        PercentageDist _percent,\r\n        bytes memory _encodedData\r\n    ) internal view returns (address[] memory x) {\r\n        if (encodeData[_eventId][_percent].length > 0) {\r\n            bytes memory _data = encodeData[_eventId][_percent][\r\n                encodeData[_eventId][_percent].length - 1\r\n            ];\r\n            if (_encodedData.length > 0) {\r\n                _data = _encodedData;\r\n            }\r\n            (x) = abi.decode(_data, (address[]));\r\n        }\r\n    }\r\n\r\n    function getTotalPlayers(bytes32 _eventId)\r\n        public\r\n        view\r\n        returns (address[] memory players)\r\n    {\r\n        players = totalPlayers[_eventId];\r\n    }\r\n}"
      },
      ".deps/payout deployment/extension/PayoutPursuitTime.sol": {
        "content": "/**\r\n * SPDX-License-Identifier: Apache-2.0\r\n *\r\n * Copyright (c) 2024, DriftToken\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n */\r\n\r\npragma solidity ^0.8.20;\r\n\r\nabstract contract PayoutPursuitTime {\r\n    mapping(bytes32 => uint256) private _openingTime;\r\n    mapping(bytes32 => uint256) private _closingTime;\r\n    mapping(bytes32 => bool) public eventPaused;\r\n\r\n    event EventTimeExtended(uint256 prevClosingTime, uint256 newClosingTime);\r\n    event NewEvent(uint256 newOpeningTime, uint256 newClosingTime);\r\n    event CancelEvent(uint256 closingTime);\r\n    event EventPaused(bytes32 eventId);\r\n    event EventUnpaused(bytes32 eventId);\r\n\r\n    modifier onlyWhileOpen(bytes32 _eventId) {\r\n        require(isOpen(_eventId), \"PayoutPursuitTime: not open\");\r\n        _;\r\n    }\r\n\r\n    modifier onlyWhenClosed(bytes32 _eventId) {\r\n        require(hasClosed(_eventId), \"PayoutPursuitTime: event in progress\");\r\n        _;\r\n    }\r\n\r\n    modifier isEventPaused(bytes32 _eventId) {\r\n        require(!eventPaused[_eventId], \"PayoutPursuitTime: event is paused\");\r\n        _;\r\n    }\r\n\r\n    function openingTime(bytes32 _eventId) public view returns (uint256) {\r\n        return _openingTime[_eventId];\r\n    }\r\n\r\n    function closingTime(bytes32 _eventId) public view returns (uint256) {\r\n        return _closingTime[_eventId];\r\n    }\r\n\r\n    function isOpen(bytes32 _eventId) internal view returns (bool) {\r\n        return\r\n            block.timestamp >= _openingTime[_eventId] &&\r\n            block.timestamp <= _closingTime[_eventId];\r\n    }\r\n\r\n    function hasClosed(bytes32 _eventId) public view returns (bool) {\r\n        return block.timestamp > _closingTime[_eventId] && _closingTime[_eventId] != 0;\r\n    }\r\n\r\n    function _extendEventTime(uint256 newClosingTime, bytes32 _eventId)\r\n        internal\r\n    {\r\n        require(!hasClosed(_eventId) || eventPaused[_eventId], \"PayoutPursuitTime: already closed\");\r\n        require(\r\n            newClosingTime > _closingTime[_eventId],\r\n            \"PayoutPursuitTime: new closing time is before current closing time\"\r\n        );\r\n\r\n        emit EventTimeExtended(_closingTime[_eventId], newClosingTime);\r\n        _closingTime[_eventId] = newClosingTime;\r\n    }\r\n\r\n    function _newEvent(\r\n        uint256 newOpeningTime,\r\n        uint256 newClosingTime,\r\n        bytes32 _eventId\r\n    ) internal {\r\n        require(\r\n            newOpeningTime >= block.timestamp,\r\n            \"PayoutPursuitTime: opening time is before current time\"\r\n        );\r\n        require(\r\n            newClosingTime > newOpeningTime,\r\n            \"PayoutPursuitTime: closing time is before opening time\"\r\n        );\r\n\r\n        emit NewEvent(newOpeningTime, newClosingTime);\r\n        _openingTime[_eventId] = newOpeningTime;\r\n        _closingTime[_eventId] = newClosingTime;\r\n    }\r\n\r\n    function _cancelEvent(bytes32 _eventId) internal {\r\n        uint256 currentTimestamp = block.timestamp;\r\n        emit CancelEvent(currentTimestamp);\r\n        _closingTime[_eventId] = currentTimestamp;\r\n    }\r\n\r\n    function _pauseEvent(bytes32 _eventId)\r\n        internal\r\n        onlyWhileOpen(_eventId)\r\n    {\r\n        eventPaused[_eventId] = true;\r\n        emit EventPaused(_eventId);\r\n    }\r\n\r\n    function _unpauseEvent(bytes32 _eventId)\r\n        internal\r\n    {\r\n        eventPaused[_eventId] = false;\r\n        emit EventUnpaused(_eventId);\r\n    }\r\n\r\n    function isEventOpen(bytes32 _eventId) public view returns (bool) {\r\n        return isOpen(_eventId) && !eventPaused[_eventId];\r\n    }\r\n}"
      },
      "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface AggregatorV3Interface {\n  function decimals() external view returns (uint8);\n\n  function description() external view returns (string memory);\n\n  function version() external view returns (uint256);\n\n  function getRoundData(\n    uint80 _roundId\n  ) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n  function latestRoundData()\n    external\n    view\n    returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {ContextUpgradeable} from \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The initial owner is set to the address provided by the deployer. This can\n * later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n    /// @custom:storage-location erc7201:openzeppelin.storage.Ownable\n    struct OwnableStorage {\n        address _owner;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Ownable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;\n\n    function _getOwnableStorage() private pure returns (OwnableStorage storage $) {\n        assembly {\n            $.slot := OwnableStorageLocation\n        }\n    }\n\n    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    function __Ownable_init(address initialOwner) internal onlyInitializing {\n        __Ownable_init_unchained(initialOwner);\n    }\n\n    function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        OwnableStorage storage $ = _getOwnableStorage();\n        return $._owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        OwnableStorage storage $ = _getOwnableStorage();\n        address oldOwner = $._owner;\n        $._owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address from, address to, uint256 value) external returns (bool);\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Storage of the initializable contract.\n     *\n     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions\n     * when using with upgradeable contracts.\n     *\n     * @custom:storage-location erc7201:openzeppelin.storage.Initializable\n     */\n    struct InitializableStorage {\n        /**\n         * @dev Indicates that the contract has been initialized.\n         */\n        uint64 _initialized;\n        /**\n         * @dev Indicates that the contract is in the process of being initialized.\n         */\n        bool _initializing;\n    }\n\n    // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.Initializable\")) - 1)) & ~bytes32(uint256(0xff))\n    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;\n\n    /**\n     * @dev The contract is already initialized.\n     */\n    error InvalidInitialization();\n\n    /**\n     * @dev The contract is not initializing.\n     */\n    error NotInitializing();\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint64 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any\n     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in\n     * production.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        // Cache values to avoid duplicated sloads\n        bool isTopLevelCall = !$._initializing;\n        uint64 initialized = $._initialized;\n\n        // Allowed calls:\n        // - initialSetup: the contract is not in the initializing state and no previous version was\n        //                 initialized\n        // - construction: the contract is initialized at version 1 (no reininitialization) and the\n        //                 current contract is just being deployed\n        bool initialSetup = initialized == 0 && isTopLevelCall;\n        bool construction = initialized == 1 && address(this).code.length == 0;\n\n        if (!initialSetup && !construction) {\n            revert InvalidInitialization();\n        }\n        $._initialized = 1;\n        if (isTopLevelCall) {\n            $._initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            $._initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint64 version) {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing || $._initialized >= version) {\n            revert InvalidInitialization();\n        }\n        $._initialized = version;\n        $._initializing = true;\n        _;\n        $._initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        _checkInitializing();\n        _;\n    }\n\n    /**\n     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.\n     */\n    function _checkInitializing() internal view virtual {\n        if (!_isInitializing()) {\n            revert NotInitializing();\n        }\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        // solhint-disable-next-line var-name-mixedcase\n        InitializableStorage storage $ = _getInitializableStorage();\n\n        if ($._initializing) {\n            revert InvalidInitialization();\n        }\n        if ($._initialized != type(uint64).max) {\n            $._initialized = type(uint64).max;\n            emit Initialized(type(uint64).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint64) {\n        return _getInitializableStorage()._initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _getInitializableStorage()._initializing;\n    }\n\n    /**\n     * @dev Returns a pointer to the storage namespace.\n     */\n    // solhint-disable-next-line var-name-mixedcase\n    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {\n        assembly {\n            $.slot := INITIALIZABLE_STORAGE\n        }\n    }\n}\n"
      },
      "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 20
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}