creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "staking.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"iface.sol\";\nimport \"BytesLib.sol\";\nimport \"SafeERC20.sol\";\nimport \"Initializable.sol\";\nimport \"AccessControlUpgradeable.sol\";\nimport \"PausableUpgradeable.sol\";\nimport \"ReentrancyGuardUpgradeable.sol\";\nimport \"SafeCast.sol\";\n\n\n/**\n * @title Bedrock Ethereum 2.0 Staking Contract\n *\n * Description:\n * \n * ───╔═╦═╗─╔╗╔═╗──────╔╗──╔╗╔╗─╔╦╗╔╗─╔═╗─╔╗───────╔╦╗\n * ╔═╗║═╣═╬═╣╚╣═╣╔══╗╔╗╠╬═╗║╚╬╬╗╠╣╚╬╬═╣═╣╔╝╚╗╔═╦═╦╦╬╣╚╦╦╗\n * ║╬╚╬═╠═║╩╣╔╬═║╠══╣║╚╣║╬╚╣╬║║╚╣║╔╣║╩╬═║╚╗╔╝║╩╣╬║║║║╔╣║║\n * ╚══╩═╩═╩═╩═╩═╝╚══╝╚═╩╩══╩═╩╩═╩╩═╩╩═╩═╝─╚╝─╚═╩╗╠═╩╩═╬╗║\n * ─────────────────────────────────────────────╚╝────╚═╝\n * \n * Term:\n *  ExchangeRatio:              Exchange Ratio of xETH to ETH, normally >= 1.0\n *  TotalXETH:                  Total Supply of xETH\n *  TotalStaked:                Total Ethers Staked to Validators\n *  TotalDebts:                 Total unpaid debts(generated from redeemFromValidators), \n *                              awaiting to be paid by turn off validators to clean debts.\n *  TotalPending:               Pending Ethers(<32 Ethers), awaiting to be staked\n *  RewardDebts:                The amount re-staked into TotalPending\n *\n *  AccountedUserRevenue:       Overall Net revenue which belongs to all xETH holders(excluded re-staked amount)\n *  ReportedValidators:         Latest Reported Validator Count\n *  ReportedValidatorBalance:   Latest Reported Validator Overall Balance\n *  RecentReceived:             The Amount this contract receives recently.\n *  CurrentReserve:             Assets Under Management\n *\n * Lemma 1: (AUM)\n *\n *          CurrentReserve = TotalPending + TotalStaked + AccountedUserRevenue - TotalDebts - RewardDebts\n *\n * Lemma 2: (Exchange Ratio)\n *\n *          ExchangeRatio = CurrentReserve / TotalXETH\n *\n * Rule 1: (function mint) For every mint operation, the ethers pays debt in priority the reset will be put in TotalPending(deprecated),\n *          ethersToMint:               The amount user deposits\n *\n *          TotalPending = TotalPending + ethersToMint\n *          TotalXETH = TotalXETH + ethersToMint / ExchangeRatio\n *\n * Rule 2: (function mint) At any time TotalPending has more than 32 Ethers, It will be staked, TotalPending\n *          moves to TotalStaked and keeps TotalPending less than 32 Ether.\n *\n *          TotalPending = TotalPending - ⌊TotalPending/32ETH⌋ * 32ETH\n *          TotalStaked = TotalStaked + ⌊TotalPending/32ETH⌋ * 32ETH\n *\n * Rule 3: (function validatorStopped) Whenever a validator stopped, all value pays debts in priority, then:\n *          valueStopped:               The value sent-back via receive() funtion\n *          amountUnstaked:             The amount of unstaked node (base 32ethers)\n *          validatorStopped:           The count of validator stopped\n *          \n *          incrRewardDebt := valueStopped - amountUnstaked\n *          RewardDebts = RewardDebt + incrRewardDebt\n *          RecentReceived = RecentReceived + valueStopped\n *          TotalPending = TotalPending + Max(0, amountUnstaked - TotalDebts) + incrRewardDebt\n *          TotalStaked = TotalStaked - validatorStopped * 32 ETH\n *\n * Rule 4.1: (function pushBeacon) Oracle push balance, rebase if new validator is alive:\n *          aliveValidator:             The count of validators alive\n *          \n *          RewardBase = ReportedValidatorBalance + Max(0, aliveValidator - ReportedValidators) * 32 ETH\n *\n * Rule 4.2: (function pushBeacon) Oracle push balance, revenue calculation:\n *          aliveBalance:               The balance of current alive validators\n *\n *          r := aliveBalance + RecentReceived - RewardBase\n *          AccountedUserRevenue = AccountedUserRevenue + r * (1000 - managerFeeShare) / 1000\n *          RecentReceived = 0\n *          ReportedValidators = aliveValidator\n *          ReportedValidatorBalance = aliveBalance\n */\ncontract Staking is Initializable, PausableUpgradeable, AccessControlUpgradeable, ReentrancyGuardUpgradeable {\n    using SafeERC20 for IERC20;\n    using Address for address payable;\n    using Address for address;\n\n    // stored credentials\n    struct ValidatorCredential {\n        bytes pubkey;\n        bytes signature;\n        bool stopped;\n        bool restaking; // UPDATE(20240115) : flag the validator is using liquid staking address\n        uint8 eigenpod; // UPDATE(20240402) : eigenpod id\n    }\n\n    // track ether debts to return to async caller\n    struct Debt {\n        address account;\n        uint256 amount;\n    }\n\n    /**\n        Incorrect storage preservation:\n\n        |Implementation_v0   |Implementation_v1        |\n        |--------------------|-------------------------|\n        |address _owner      |address _lastContributor | <=== Storage collision!\n        |mapping _balances   |address _owner           |\n        |uint256 _supply     |mapping _balances        |\n        |...                 |uint256 _supply          |\n        |                    |...                      |\n        Correct storage preservation:\n\n        |Implementation_v0   |Implementation_v1        |\n        |--------------------|-------------------------|\n        |address _owner      |address _owner           |\n        |mapping _balances   |mapping _balances        |\n        |uint256 _supply     |uint256 _supply          |\n        |...                 |address _lastContributor | <=== Storage extension.\n        |                    |...                      |\n    */\n\n    // Always extend storage instead of modifying it\n    // Variables in implementation v0 \n    bytes32 public constant MANAGER_ROLE = keccak256(\"MANAGER_ROLE\");\n    bytes32 public constant ORACLE_ROLE = keccak256(\"ORACLE_ROLE\");\n    bytes32 public constant REGISTRY_ROLE = keccak256(\"REGISTRY_ROLE\");\n    bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n    uint256 public constant DEPOSIT_SIZE = 32 ether;\n    uint256 public constant SAFE_PUSH_REWARDS = 30 ether;\n\n    uint256 private constant MULTIPLIER = 1e18; \n    uint256 private constant DEPOSIT_AMOUNT_UNIT = 1000000000 wei;\n    uint256 private constant SIGNATURE_LENGTH = 96;\n    uint256 private constant PUBKEY_LENGTH = 48;\n\n    address public ethDepositContract;      // ETH 2.0 Deposit contract\n    address public xETHAddress;             // xETH token address\n    address public redeemContract;          // redeeming contract for user to pull ethers\n\n    uint256 public managerFeeShare;         // manager's fee in 1/1000\n    bytes32 public withdrawalCredentials;   // WithdrawCredential for all validator\n\n    // credentials, pushed by owner\n    ValidatorCredential [] public validatorRegistry;\n    mapping(bytes32 => uint256) private pubkeyIndices; // indices of validatorRegistry by pubkey hash, starts from 1\n\n    // next validator id\n    uint256 private nextValidatorId;\n\n    // exchange ratio related variables\n    // track user deposits & redeem (xETH mint & burn)\n    uint256 private totalPending;           // track pending ethers awaiting to be staked to validators\n    uint256 private totalStaked;            // track current staked ethers for validators, rounded to 32 ethers\n    uint256 private totalDebts;             // track current unpaid debts\n\n    // FIFO of debts from redeemFromValidators\n    mapping(uint256=>Debt) private etherDebts;\n    uint256 private firstDebt;\n    uint256 private lastDebt;\n    mapping(address=>uint256) private userDebts;    // debts from user's perspective\n\n    // track revenue from validators to form exchange ratio\n    uint256 private accountedUserRevenue;           // accounted shared user revenue\n    uint256 private accountedManagerRevenue;        // accounted manager's revenue\n    uint256 private rewardDebts;                    // check validatorStopped function\n\n    // revenue related variables\n    // track beacon validator & balance\n    uint256 private reportedValidators;\n    uint256 private reportedValidatorBalance;\n\n    // balance tracking\n    int256 private accountedBalance;                // tracked balance change in functions,\n                                                    // NOTE(x): balance might be negative for not accounting validators's redeeming\n\n    uint256 private maxToStop;                      // set max validators to stop (20240530)\n    uint256 private recentReceived;                 // track recently received (un-accounted) value into this contract\n    bytes32 private vectorClock;                    // a vector clock for detecting receive() & pushBeacon() causality violations\n    uint256 private vectorClockTicks;               // record current vector clock step;\n\n    // track stopped validators\n    uint256 private stoppedValidators;              // track stopped validators count\n\n    // phase switch from 0 to 1\n    uint256 private __DEPRECATED_phase;\n\n    // gas refunds\n    uint256 [] private refunds;\n\n    // PATCH VARIABLES(UPGRADES)\n    uint256 private recentStopped;                  // track recent stopped validators(update: 20220927)\n\n    /**\n     * @dev empty reserved space for future adding of variables\n     */\n    uint256[31] private __gap;\n\n    // KYC control\n    mapping(address=>uint256) __DEPRECATED_quotaUsed;\n    mapping(address=>bool) __DEPRECATED_whiteList;\n\n    // auto-compounding\n    bool private __DEPRECATED_autoCompoundEnabled;\n\n    // DEPRECATED(20240130): eigenlayer's restaking withdrawal credential\n    bytes32 private __DEPRECATED_restakingWithdrawalCredentials;\n    address private __DEPRECATED_restakingAddress;\n\n    // UPDATE(20240130): use variable instead of constant, require upgradeAndCall to set it's value\n    address public restakingContract;\n\n    // UPDATE(20240405): record latest unrealized profits\n    uint256 private reportedUnrealizedProfits;\n\n    /** \n     * ======================================================================================\n     * \n     * SYSTEM SETTINGS, OPERATED VIA OWNER(DAO/TIMELOCK)\n     * \n     * ======================================================================================\n     */\n    receive() external payable { }\n    constructor() { _disableInitializers(); }\n\n    /**\n     * @dev pause the contract\n     */\n    function pause() public onlyRole(PAUSER_ROLE) {\n        _pause();\n    }\n\n    /**\n     * @dev unpause the contract\n     */\n    function unpause() public onlyRole(PAUSER_ROLE) {\n        _unpause();\n    }\n\n    /**\n     * @dev initialization address\n     */\n    /*\n    function initialize() initializer public {\n        __Pausable_init();\n        __AccessControl_init();\n        __ReentrancyGuard_init();\n\n        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n        _grantRole(ORACLE_ROLE, msg.sender);\n        _grantRole(REGISTRY_ROLE, msg.sender);\n        _grantRole(PAUSER_ROLE, msg.sender);\n        _grantRole(MANAGER_ROLE, msg.sender);\n\n        // init default values\n        managerFeeShare = 5;\n        firstDebt = 1;\n        lastDebt = 0;\n        phase = 0;\n        _vectorClockTick();\n\n        // initiate default withdrawal credential to the contract itself\n        // uint8('0x1') + 11 bytes(0) + this.address\n        bytes memory cred = abi.encodePacked(bytes1(0x01), new bytes(11), address(this));\n        withdrawalCredentials = BytesLib.toBytes32(cred, 0);\n    }\n   */\n   \n    /**\n     * UPDATE(20240130): to set a variable after upgrades\n     * use upgradeAndCall to initializeV2\n     */ \n    /*\n    function initializeV2(address restakingContract_) reinitializer(2) public {\n        restakingContract = restakingContract_;\n    }\n    */\n\n    /**\n     * @dev replace validators in batch\n     */\n    function replaceValidators(\n        bytes [] calldata oldpubkeys, \n        bytes [] calldata pubkeys, \n        bytes [] calldata signatures, \n        bool restaking, \n        uint8 [] calldata podIds) external onlyRole(REGISTRY_ROLE) {\n        _require(pubkeys.length == signatures.length, \"SYS007\");\n        _require(oldpubkeys.length == pubkeys.length, \"SYS007\");\n        _require(pubkeys.length == podIds.length, \"SYS007\");\n\n        uint256 n = pubkeys.length;\n\n        for(uint256 i=0;i<n;i++) {\n            _require(oldpubkeys[i].length == PUBKEY_LENGTH, \"SYS004\");\n            _require(pubkeys[i].length == PUBKEY_LENGTH, \"SYS004\");\n            _require(signatures[i].length == SIGNATURE_LENGTH, \"SYS003\");\n\n            // mark old pub key to false\n            bytes32 oldPubKeyHash = keccak256(oldpubkeys[i]);\n            _require(pubkeyIndices[oldPubKeyHash] > 0, \"SYS006\");\n            uint256 index = pubkeyIndices[oldPubKeyHash] - 1;\n            delete pubkeyIndices[oldPubKeyHash];\n\n            // set new pubkey\n            bytes32 pubkeyHash = keccak256(pubkeys[i]);\n            ValidatorCredential storage validator = validatorRegistry[index];\n            validator.pubkey = pubkeys[i];\n            validator.signature = signatures[i];\n            validator.restaking = restaking;\n            validator.eigenpod = podIds[i];\n            pubkeyIndices[pubkeyHash] = index+1;\n        }\n    }\n\n    /**\n     * @dev register a batch of validators\n     */\n    function registerValidators(bytes [] calldata pubkeys, bytes [] calldata signatures) external onlyRole(REGISTRY_ROLE) {\n        _require(pubkeys.length == signatures.length, \"SYS007\");\n        uint256 n = pubkeys.length;\n        for(uint256 i=0;i<n;i++) {\n            _require(pubkeys[i].length == PUBKEY_LENGTH, \"SYS004\");\n            _require(signatures[i].length == SIGNATURE_LENGTH, \"SYS003\");\n\n            bytes32 pubkeyHash = keccak256(pubkeys[i]);\n            _require(pubkeyIndices[pubkeyHash] == 0, \"SYS005\");\n            validatorRegistry.push(ValidatorCredential({pubkey:pubkeys[i], signature:signatures[i], stopped:false, restaking: false, eigenpod: 0}));\n            pubkeyIndices[pubkeyHash] = validatorRegistry.length;\n        }\n    }\n\n    /**\n     * @dev register a batch of LRT validators\n     * UPDATE(20240115): register a batch of validators for Liquid Restaking (EigenLayer)\n     */\n    function registerRestakingValidators(bytes [] calldata pubkeys, bytes [] calldata signatures) external onlyRole(REGISTRY_ROLE) {\n        _require(pubkeys.length == signatures.length, \"SYS007\");\n        uint256 n = pubkeys.length;\n        for(uint256 i=0;i<n;i++) {\n            _require(pubkeys[i].length == PUBKEY_LENGTH, \"SYS004\");\n            _require(signatures[i].length == SIGNATURE_LENGTH, \"SYS003\");\n\n            bytes32 pubkeyHash = keccak256(pubkeys[i]);\n            _require(pubkeyIndices[pubkeyHash] == 0, \"SYS005\");\n            validatorRegistry.push(ValidatorCredential({pubkey:pubkeys[i], signature:signatures[i], stopped:false, restaking: true, eigenpod: 0}));\n            pubkeyIndices[pubkeyHash] = validatorRegistry.length;\n        }\n    }\n\n    /**\n     * @dev register a batch of LRT validators\n     * UPDATE(20240402): register a batch of validators for Liquid Restaking (EigenLayer) with given eigenpod id\n     */\n    function registerRestakingValidators(\n        bytes [] calldata pubkeys, \n        bytes [] calldata signatures, \n        uint8 [] calldata podIds) external onlyRole(REGISTRY_ROLE) {\n        _require(pubkeys.length == signatures.length, \"SYS007\");\n        _require(pubkeys.length == podIds.length, \"SYS007\");\n        uint256 n = pubkeys.length;\n        uint256 maxPods = IRestaking(restakingContract).getTotalPods();\n\n        for(uint256 i=0;i<n;i++) {\n            _require(pubkeys[i].length == PUBKEY_LENGTH, \"SYS004\");\n            _require(signatures[i].length == SIGNATURE_LENGTH, \"SYS003\");\n            _require(podIds[i] < maxPods, \"SYS031\");\n\n            bytes32 pubkeyHash = keccak256(pubkeys[i]);\n            _require(pubkeyIndices[pubkeyHash] == 0, \"SYS005\");\n            validatorRegistry.push(ValidatorCredential({pubkey:pubkeys[i], signature:signatures[i], stopped:false, restaking: true, eigenpod: podIds[i]}));\n            pubkeyIndices[pubkeyHash] = validatorRegistry.length;\n        }\n    }\n\n    /**\n     * @dev set manager's fee in 1/1000\n     */\n    function setManagerFeeShare(uint256 milli) external onlyRole(DEFAULT_ADMIN_ROLE)  {\n        _require(milli >=0 && milli <=1000, \"SYS008\");\n        managerFeeShare = milli;\n\n        emit ManagerFeeSet(milli);\n    }\n\n    /**\n     * @dev set eth deposit contract address\n     */\n    function setETHDepositContract(address _ethDepositContract) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        ethDepositContract = _ethDepositContract;\n\n        emit DepositContractSet(_ethDepositContract);\n    }\n\n\n    /**\n     * @dev set withdraw credential to receive revenue, usually this should be the contract itself.\n     */\n    function setWithdrawCredential(bytes32 withdrawalCredentials_) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        withdrawalCredentials = withdrawalCredentials_;\n        emit WithdrawCredentialSet(withdrawalCredentials);\n    } \n\n    \n    /**\n     * @dev stake into eth2 staking contract by calling this function\n     */\n    function stake() external { _stakeInternal(); }\n\n    /**\n     * @dev internal entry of stake() external \n     */\n    function _stakeInternal() internal {\n        // spin max nodes\n        uint256 numValidators = totalPending / DEPOSIT_SIZE;\n        uint256 maxValidators = (nextValidatorId + numValidators <= validatorRegistry.length)?\n                                    numValidators:\n                                    validatorRegistry.length - nextValidatorId;\n\n        for (uint256 i = 0;i<maxValidators;i++) {\n            _spinup();\n        }\n\n        if (maxValidators > 0) {\n            emit ValidatorActivated(nextValidatorId);\n        }\n    }\n\n    /**\n     * @dev manager withdraw fees as uniETH\n     */\n    function withdrawManagerFee(address to) external onlyRole(MANAGER_ROLE) {\n        IERC20(xETHAddress).safeTransfer(to, IERC20(xETHAddress).balanceOf(address(this)));\n    }\n\n    /**\n     * @dev compound manager's revenue\n     *  NOTE(20240406): this MUST be called in pushBeacon, to make sure debts are paied in priority, otherwise\n     *      debts may be used to pay as the manager's revenue(that may take serveral months to come back).\n     */\n    function _compoundManagerRevenue() internal {\n        uint256 freeEthers = address(this).balance - totalPending;\n        uint256 amountEthers = freeEthers < accountedManagerRevenue ? freeEthers:accountedManagerRevenue;\n\n        if (amountEthers > 0) {\n            uint256 totalSupply = IERC20(xETHAddress).totalSupply();\n            uint256 totalEthers = currentReserve();\n            uint256 tokensToMint = totalSupply * amountEthers / totalEthers;\n\n            // swapping\n            // uint256 ratio = _exchangeRatioInternal();           // RATIO GUARD BEGIN\n            IMintableContract(xETHAddress).mint(address(this), tokensToMint);\n            totalPending += amountEthers;\n            accountedManagerRevenue -= amountEthers;\n            // assert(ratio == _exchangeRatioInternal());          // RATIO GUARD END\n\n            emit ManagerRevenueCompounded(amountEthers);\n        }\n    }\n\n    /**\n     * @dev clear debts\n     */\n    function _clearDebts() internal {\n        uint256 maxUsable = (address(this).balance - totalPending) / 32 ether * 32 ether;\n        uint256 effectiveEthers = totalDebts < maxUsable? totalDebts:maxUsable;\n\n        if (effectiveEthers > 0) {\n            uint256 ratio = _exchangeRatioInternal();           // RATIO GUARD BEGIN\n\n            uint256 paid = _payDebts(effectiveEthers);\n            totalStaked -= paid;\n\n            assert(ratio == _exchangeRatioInternal());          // RATIO GUARD END\n        }\n    }\n\n\n    /**\n     * @dev balance sync, also moves the vector clock if it has different value\n     */\n    function syncBalance() external { _syncBalance(); }\n    \n    /**\n     * @dev balance sync, also moves the vector clock if it has different value\n     */\n    function _syncBalance() internal {\n        // account restaking values\n        IRestaking(restakingContract).update();\n\n        assert(SafeCast.toInt256(address(this).balance) >= accountedBalance);\n        uint256 diff = SafeCast.toUint256(SafeCast.toInt256(address(this).balance) - accountedBalance);\n        if (diff > 0) {\n            accountedBalance = SafeCast.toInt256(address(this).balance);\n            recentReceived += diff;\n            _vectorClockTick();\n            emit BalanceSynced(diff);\n        }\n    }\n    \n    /**\n     * @dev public invokable settlement to update exchangeRatio with default revenue limit.\n     */\n    function pushBeacon() external { _pushBeacon(vectorClock, SAFE_PUSH_REWARDS); }\n\n    /**\n     * @dev operators to settle revenue with custom revenue limit under abnormal conditions.\n     */\n    function pushBeacon(bytes32 clock, uint256 maxRewards) external onlyRole(ORACLE_ROLE) { _pushBeacon(clock, maxRewards); }\n\n\n    function _pushBeacon(bytes32 clock, uint256 maxRewards) internal {\n        _require(vectorClock == clock, \"SYS012\");\n\n        // Collect new revenue if there is any.\n        _syncBalance();\n        \n        // Check if new validators increased\n        // and adjust rewardBase to include the new validators' value\n        uint256 rewardBase = reportedValidatorBalance + reportedUnrealizedProfits;\n        uint256 _aliveValidators = nextValidatorId - stoppedValidators;\n        if (_aliveValidators + recentStopped > reportedValidators) {\n            // newly launched validators\n            uint256 newValidators = _aliveValidators + recentStopped - reportedValidators;\n            rewardBase += newValidators * DEPOSIT_SIZE;\n        }\n\n        // Rewards calculation, this also considers recentReceived ethers from \n        // either stopped validators or withdrawed ethers as rewards.\n        //\n        // During two consecutive pushBeacon operation, the ethers will ONLY: \n        //  1. staked to new validators\n        //  2. move from active validators to this contract\n        // \n        // so, at any time, revenue generated if:\n        //\n        //  current active validator balance \n        //      + recent received from validators(since last pushBeacon) \n        //  >（GREATER THAN) reward base(last active validator balance + new nodes balance)\n        uint256 _aliveBalance = _aliveValidators * DEPOSIT_SIZE;  // computed balance\n        uint256 _unrealizedProfits = IRestaking(restakingContract).getPendingWithdrawalAmount();   // get unrealized profits\n\n        _require(_aliveBalance + _unrealizedProfits + recentReceived >= rewardBase, \"SYS015\");\n        uint256 rewards = _aliveBalance + _unrealizedProfits + recentReceived - rewardBase;\n        _require(rewards <= maxRewards, \"SYS016\");\n\n        _distributeRewards(rewards);\n\n        // PRIORITY IN ETHER USAGE:\n        // 1. to clear off debts\n        // 2. to compound manager's revenue\n        // 3. to auto-compound\n        _clearDebts();\n        _compoundManagerRevenue();\n        _autocompound();\n\n        // Update reportedValidators & reportedValidatorBalance\n        // reset the recentReceived to 0\n        reportedValidatorBalance = _aliveBalance; \n        reportedValidators = _aliveValidators;\n        reportedUnrealizedProfits = _unrealizedProfits;\n        recentReceived = 0;\n        recentStopped = 0;\n    }\n\n    /**\n     * @dev notify some validators stopped, and pay the debts\n     */\n    function validatorStopped(bytes [] calldata _stoppedPubKeys, bytes32 clock) external nonReentrant onlyRole(ORACLE_ROLE) {\n        _require(vectorClock == clock, \"SYS012\");\n        uint256 amountUnstaked = _stoppedPubKeys.length * DEPOSIT_SIZE;\n        _require(_stoppedPubKeys.length > 0, \"SYS017\");\n        _require(_stoppedPubKeys.length + stoppedValidators <= nextValidatorId, \"SYS018\");\n        _require(maxToStop >= _stoppedPubKeys.length, \"SYS019\");\n\n        // track stopped validators\n        for (uint i=0;i<_stoppedPubKeys.length;i++) {\n            bytes32 pubkeyHash = keccak256(_stoppedPubKeys[i]);\n            _require(pubkeyIndices[pubkeyHash] > 0, \"SYS006\");\n            uint256 index = pubkeyIndices[pubkeyHash] - 1;\n            _require(!validatorRegistry[index].stopped, \"SYS020\");\n            validatorRegistry[index].stopped = true;\n        }\n        stoppedValidators += _stoppedPubKeys.length;\n        recentStopped += _stoppedPubKeys.length;\n        maxToStop -= _stoppedPubKeys.length;\n    \n        // log\n        emit ValidatorStopped(_stoppedPubKeys.length);\n\n        // vector clock moves\n        _vectorClockTick();\n    }\n\n    /**\n     * ======================================================================================\n     * \n     * VIEW FUNCTIONS\n     * \n     * ======================================================================================\n     */\n\n    /**\n     * @dev returns current reserve of ethers\n     */\n    function currentReserve() public view returns(uint256) {\n        return totalPending + totalStaked + accountedUserRevenue - totalDebts - rewardDebts;\n    }\n\n    /*\n     * @dev returns current vector clock\n     */\n    function getVectorClock() external view returns(bytes32) { return vectorClock; }\n\n    /*\n     * @dev returns current accounted balance\n     */\n    function getAccountedBalance() external view returns(int256) { return accountedBalance; }\n\n    /**\n     * @dev return total staked ethers\n     */\n    function getTotalStaked() external view returns (uint256) { return totalStaked; }\n\n    /**\n     * @dev return pending ethers\n     */\n    function getPendingEthers() external view returns (uint256) { return totalPending; }\n\n    /**\n     * @dev return reward debts(total compounded ethers)\n     */\n    function getRewardDebts() external view returns (uint256) { return rewardDebts; }\n\n    /**\n     * @dev return current debts\n     */\n    function getCurrentDebts() external view returns (uint256) { return totalDebts; }\n\n    /**\n     * @dev returns the accounted user revenue\n     */\n    function getAccountedUserRevenue() external view returns (uint256) { return accountedUserRevenue; }\n\n    /**\n     * @dev returns the accounted manager's revenue\n     */\n    function getAccountedManagerRevenue() external view returns (uint256) { return accountedManagerRevenue; }\n\n    /*\n     * @dev returns accumulated beacon validators\n     */\n    function getReportedValidators() external view returns (uint256) { return reportedValidators; }\n\n    /*\n     * @dev returns reported validator balance snapshot\n     */\n    function getReportedValidatorBalance() external view returns (uint256) { return reportedValidatorBalance; }\n\n    /*\n     * @dev returns maxToStop\n     */\n    function getMaxToStop() external view returns (uint256) { return maxToStop; }\n    \n    /*\n     * @dev returns recent received value\n     */\n    function getRecentReceived() external view returns (uint256) { return recentReceived; }\n    /*\n     * @dev returns recent received value\n     */\n    function getRecentStopped() external view returns (uint256) { return recentStopped; }\n\n    /**\n     * @dev return debt for an account\n     */\n    function debtOf(address account) external view returns (uint256) {\n        return userDebts[account];\n    }\n\n    /**\n     * @dev return number of registered validator\n     */\n    function getRegisteredValidatorsCount() external view returns (uint256) {\n        return validatorRegistry.length;\n    }\n    \n    /**\n     * @dev return a batch of validators credential\n     */\n    function getRegisteredValidators(uint256 idx_from, uint256 idx_to) external view returns (bytes [] memory pubkeys, bytes [] memory signatures, bool[] memory stopped) {\n        pubkeys = new bytes[](idx_to - idx_from);\n        signatures = new bytes[](idx_to - idx_from);\n        stopped = new bool[](idx_to - idx_from);\n\n\n        uint counter = 0;\n        for (uint i = idx_from; i < idx_to;i++) {\n            pubkeys[counter] = validatorRegistry[i].pubkey;\n            signatures[counter] = validatorRegistry[i].signature;\n            stopped[counter] = validatorRegistry[i].stopped;\n            counter++;\n        }\n    }\n\n    /**\n     * @dev return a batch of validators information\n     * UPDATE(20240119): V2 returns restaking info\n     */\n    function getRegisteredValidatorsV2(uint256 idx_from, uint256 idx_to) external view returns (\n         bytes [] memory pubkeys,\n         bytes [] memory signatures,\n         bool [] memory stopped,\n         bool [] memory restaking)\n    {\n        pubkeys = new bytes[](idx_to - idx_from);\n        signatures = new bytes[](idx_to - idx_from);\n        stopped = new bool[](idx_to - idx_from);\n        restaking = new bool[](idx_to - idx_from);\n\n        uint counter = 0;\n        for (uint i = idx_from; i < idx_to;i++) {\n            pubkeys[counter] = validatorRegistry[i].pubkey;\n            signatures[counter] = validatorRegistry[i].signature;\n            stopped[counter] = validatorRegistry[i].stopped;\n            restaking[counter] = validatorRegistry[i].restaking;\n            counter++;\n        }\n    }\n\n\n    /**\n     * @dev return next validator id\n     */\n    function getNextValidatorId() external view returns (uint256) { return nextValidatorId; }\n\n    /**\n     * @dev return exchange ratio for 1 uniETH to ETH, multiplied by 1e18\n     */\n    function exchangeRatio() external view returns (uint256) { return _exchangeRatioInternal(); }\n\n    function _exchangeRatioInternal() internal view returns (uint256) {\n        uint256 xETHAmount = IERC20(xETHAddress).totalSupply();\n        if (xETHAmount == 0) {\n            return 1 * MULTIPLIER;\n        }\n\n        uint256 ratio = currentReserve() * MULTIPLIER / xETHAmount;\n        return ratio;\n    }\n\n    /**\n     * @dev return debt of index\n     */\n    function checkDebt(uint256 index) external view returns (address account, uint256 amount) {\n        Debt memory debt = etherDebts[index];\n        return (debt.account, debt.amount);\n    }\n    /**\n     * @dev return debt queue index\n     */\n    function getDebtQueue() external view returns (uint256 first, uint256 last) {\n        return (firstDebt, lastDebt);\n    }\n\n    /**\n     * @dev get stopped validators count\n     */\n    function getStoppedValidatorsCount() external view returns (uint256) { return stoppedValidators; }\n\n    /**\n     * ======================================================================================\n     * \n     * EXTERNAL FUNCTIONS\n     * \n     * ======================================================================================\n     */\n    /**\n     * @dev mint xETH with ETH\n     */\n    function mint(uint256 minToMint, uint256 deadline) external payable nonReentrant whenNotPaused returns(uint256 minted) {\n        _require(block.timestamp < deadline, \"USR001\");\n        _require(msg.value > 0, \"USR002\");\n\n        // track balance\n        _balanceIncrease(msg.value);\n\n        // mint xETH while keeping the exchange ratio invariant\n        uint256 totalXETH = IERC20(xETHAddress).totalSupply();\n        uint256 totalEthers = currentReserve();\n        uint256 toMint = 1 * msg.value;  // default exchange ratio 1:1\n\n        if (totalEthers > 0) { // avert division overflow\n            toMint = totalXETH * msg.value / totalEthers;\n        }\n\n        _require(toMint >= minToMint, \"USR004\");\n\n        // mint token while keeping exchange ratio invariant\n        // uint256 ratio = _exchangeRatioInternal();           // RATIO GUARD BEGIN\n        IMintableContract(xETHAddress).mint(msg.sender, toMint);\n        totalPending += msg.value;\n        // assert(ratio == _exchangeRatioInternal());          // RATIO GUARD END\n\n        // try to initiate stake()\n        _stakeInternal();\n\n        return toMint;\n    }\n\n    /** \n     * @dev preview instant payment at CURRENT exchangeRatio\n     */\n    function previewInstantSwap(uint256 tokenAmount) external view returns(\n        uint256 maxEthersToSwap,\n        uint256 maxTokensToBurn\n    ) {\n        return _instantSwapRate(tokenAmount);\n    }\n\n\n    /** \n     * @dev instant payment as much as possbile from pending ethers at CURRENT exchangeRatio\n     */\n    function instantSwap(uint256 tokenAmount) external nonReentrant whenNotPaused {\n        (uint256 maxEthersToSwap, uint256 maxTokensToBurn) = _instantSwapRate(tokenAmount);\n        // _require(maxTokensToBurn > 0 && maxEthersToSwap > 0, \"USR007\");\n\n        // uint256 ratio = _exchangeRatioInternal();               // RATIO GUARD BEGIN\n        // transfer token from user and burn, substract ethers from pending ethers\n        IMintableContract(xETHAddress).burnFrom(msg.sender, maxTokensToBurn);\n        totalPending -= maxEthersToSwap;\n        // assert(ratio == _exchangeRatioInternal());              // RATIO GUARD END\n\n        // track balance change\n        _balanceDecrease(maxEthersToSwap);\n\n        // transfer ethers to users\n        payable(msg.sender).sendValue(maxEthersToSwap);\n    }\n\n    /**\n     * @dev internal function for the calculation of max allowed instant swap rate\n     */\n    function _instantSwapRate(uint256 tokenAmount) internal view returns (\n        uint256 maxEthersToSwap,\n        uint256 maxTokensToBurn\n    ) {\n        // find max instant swappable ethers\n        uint256 totalSupply = IERC20(xETHAddress).totalSupply();\n        uint256 r = currentReserve();\n        uint256 expectedEthersToSwap =  tokenAmount * r / totalSupply;\n        maxEthersToSwap = expectedEthersToSwap > totalPending ? totalPending:expectedEthersToSwap;\n        // reverse calculation for how much token to burn.\n        maxTokensToBurn = totalSupply * maxEthersToSwap / r;\n    }\n\n    /**\n     * @dev redeem N * 32Ethers, which will turn off validadators,\n     * note this function is asynchronous, the caller will only receive his ethers\n     * after the validator has turned off.\n     *\n     * this function is dedicated for institutional operations.\n     * \n     * redeem keeps the ratio invariant\n     */\n    function redeemFromValidators(uint256 ethersToRedeem, uint256 maxToBurn, uint256 deadline) external nonReentrant returns(uint256 burned) {\n        _require(block.timestamp < deadline, \"USR001\");\n        _require(ethersToRedeem % DEPOSIT_SIZE == 0, \"USR005\");\n        _require(ethersToRedeem > 0, \"USR005\");\n\n        uint256 totalXETH = IERC20(xETHAddress).totalSupply();\n        uint256 xETHToBurn = totalXETH * ethersToRedeem / currentReserve();\n        _require(xETHToBurn <= maxToBurn, \"USR004\");\n\n        // NOTE: the following procdure must keep exchangeRatio invariant:\n        // transfer xETH from sender & burn\n        // uint256 ratio = _exchangeRatioInternal();           // RATIO GUARD BEGIN\n        IMintableContract(xETHAddress).burnFrom(msg.sender, xETHToBurn);\n        _enqueueDebt(msg.sender, ethersToRedeem);           // queue ether debts\n        // assert(ratio == _exchangeRatioInternal());          // RATIO GUARD END\n        maxToStop += ethersToRedeem / DEPOSIT_SIZE;\n\n        // return burned \n        return xETHToBurn;\n    }\n\n    /** \n     * ======================================================================================\n     * \n     * INTERNAL FUNCTIONS\n     * \n     * ======================================================================================\n     */\n\n    function _balanceIncrease(uint256 amount) internal { accountedBalance += SafeCast.toInt256(amount); }\n    function _balanceDecrease(uint256 amount) internal { accountedBalance -= SafeCast.toInt256(amount); }\n\n    function _vectorClockTick() internal {\n        vectorClockTicks++;\n        vectorClock = keccak256(abi.encodePacked(vectorClock, block.timestamp, vectorClockTicks));\n    }\n\n    function _enqueueDebt(address account, uint256 amount) internal {\n        // debt is paid in FIFO queue\n        lastDebt += 1;\n        etherDebts[lastDebt] = Debt({account:account, amount:amount});\n\n        // track user debts\n        userDebts[account] += amount;\n        // track total debts\n        totalDebts += amount;\n\n        // log\n        emit DebtQueued(account, amount);\n    }\n\n    function _dequeueDebt() internal returns (Debt memory debt) {\n        _require(lastDebt >= firstDebt, \"SYS022\");  // non-empty queue\n        debt = etherDebts[firstDebt];\n        delete etherDebts[firstDebt];\n        firstDebt += 1;\n    }\n\n    /**\n     * @dev pay debts for a given amount\n     */\n    function _payDebts(uint256 total) internal returns(uint256 amountPaid) {\n        // ethers to pay\n        for (uint i=firstDebt;i<=lastDebt;i++) {\n            if (total == 0) {\n                break;\n            }\n\n            Debt storage debt = etherDebts[i];\n\n            // clean debts\n            uint256 toPay = debt.amount <= total? debt.amount:total;\n            debt.amount -= toPay;\n            total -= toPay;\n            userDebts[debt.account] -= toPay;\n            amountPaid += toPay;\n\n            // transfer money to debt contract\n            IRedeem(redeemContract).pay{value:toPay}(debt.account);\n\n            // dequeue if cleared \n            if (debt.amount == 0) {\n                _dequeueDebt();\n            }\n        }\n        \n        totalDebts -= amountPaid;\n        \n        // track balance\n        _balanceDecrease(amountPaid);\n    }\n\n    /**\n     * @dev distribute revenue\n     */\n    function _distributeRewards(uint256 rewards) internal {\n        // rewards distribution\n        uint256 fee = rewards * managerFeeShare / 1000;\n        accountedManagerRevenue += fee;\n        accountedUserRevenue += rewards - fee;\n\n        emit RevenueAccounted(rewards);\n    }\n\n    /**\n     * @dev auto compounding, after shanghai merge, called in pushBeacon\n     *  NOTE(20240406): this MUST be called in pushBeacon, to make sure debts are paied in priority, otherwise\n     *      debts may be used to pay as the users' revenue(that may take serveral months to come back).\n     */\n    function _autocompound() internal {\n        uint256 maxCompound = accountedUserRevenue - rewardDebts;\n        uint256 maxUsable = address(this).balance - totalPending;\n        uint256 effectiveEthers = maxCompound < maxUsable? maxCompound:maxUsable;\n\n        if (effectiveEthers > 0) {\n            totalPending += effectiveEthers;\n            rewardDebts += effectiveEthers;\n            emit UserRevenueCompounded(effectiveEthers);\n        }\n    }\n\n    /**\n     * @dev spin up the node\n     */\n    function _spinup() internal {\n         // load credential\n        ValidatorCredential memory cred = validatorRegistry[nextValidatorId];\n        \n        // UPDATE(20240115):\n        //  switch withdrawal credential based on it's registration\n        if (!cred.restaking) {\n            _stake(cred.pubkey, cred.signature, withdrawalCredentials);\n        } else {\n            address eigenPod = IRestaking(restakingContract).getPod(cred.eigenpod);\n            bytes memory eigenPodCred = abi.encodePacked(bytes1(0x01), new bytes(11), eigenPod);\n            bytes32 restakingWithdrawalCredentials = BytesLib.toBytes32(eigenPodCred, 0);\n\n            _stake(cred.pubkey, cred.signature, restakingWithdrawalCredentials);\n        }\n        nextValidatorId++;        \n\n        // track total staked & total pending ethers\n        totalStaked += DEPOSIT_SIZE;\n        totalPending -= DEPOSIT_SIZE;\n    }\n\n    /**\n     * @dev Invokes a deposit call to the official Deposit contract\n     *      UPDATE(20240115): add param withCred, instead of using contract variable\n     */\n    function _stake(bytes memory pubkey, bytes memory signature, bytes32 withCred) internal {\n        _require(withCred != bytes32(0x0), \"SYS024\");\n        uint256 value = DEPOSIT_SIZE;\n        uint256 depositAmount = DEPOSIT_SIZE / DEPOSIT_AMOUNT_UNIT;\n        assert(depositAmount * DEPOSIT_AMOUNT_UNIT == value);    // properly rounded\n\n        // Compute deposit data root (`DepositData` hash tree root)\n        // https://etherscan.io/address/0x00000000219ab540356cbb839cbe05303d7705fa#code\n        bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0)));\n        bytes32 signature_root = sha256(abi.encodePacked(\n            sha256(BytesLib.slice(signature, 0, 64)),\n            sha256(abi.encodePacked(BytesLib.slice(signature, 64, SIGNATURE_LENGTH - 64), bytes32(0)))\n        ));\n        \n        bytes memory amount = to_little_endian_64(uint64(depositAmount));\n\n        bytes32 depositDataRoot = sha256(abi.encodePacked(\n            sha256(abi.encodePacked(pubkey_root, withCred)),\n            sha256(abi.encodePacked(amount, bytes24(0), signature_root))\n        ));\n\n        IDepositContract(ethDepositContract).deposit{value:DEPOSIT_SIZE} (\n            pubkey, abi.encodePacked(withCred), signature, depositDataRoot);\n\n        // track balance\n        _balanceDecrease(DEPOSIT_SIZE);\n    }\n\n    /**\n     * @dev to little endian\n     * https://etherscan.io/address/0x00000000219ab540356cbb839cbe05303d7705fa#code\n     */\n    function to_little_endian_64(uint64 value) internal pure returns (bytes memory ret) {\n        ret = new bytes(8);\n        bytes8 bytesValue = bytes8(value);\n        // Byteswapping during copying to bytes.\n        ret[0] = bytesValue[7];\n        ret[1] = bytesValue[6];\n        ret[2] = bytesValue[5];\n        ret[3] = bytesValue[4];\n        ret[4] = bytesValue[3];\n        ret[5] = bytesValue[2];\n        ret[6] = bytesValue[1];\n        ret[7] = bytesValue[0];\n    }\n\n    /**\n     * @dev function version of _require, which could make the code size smaller\n     */\n    function _require(bool condition, string memory text) private pure {\n        require(condition, text);\n    }\n\n    /**\n     * ======================================================================================\n     * \n     * CONTRCT EVENTS\n     *\n     * ======================================================================================\n     */\n    event ValidatorActivated(uint256 nextValidatorId);\n    event ValidatorStopped(uint256 stoppedCount);\n    event RevenueAccounted(uint256 amount);\n    event ValidatorSlashedStopped(uint256 stoppedCount);\n    event ManagerAccountSet(address account);\n    event ManagerFeeSet(uint256 milli);\n    event ManagerFeeWithdrawed(uint256 amount, address);\n    event WithdrawCredentialSet(bytes32 withdrawCredential);\n    event RestakingAddressSet(address addr);\n    event DebtQueued(address creditor, uint256 amountEther);\n    event DepositContractSet(address addr);\n    event BalanceSynced(uint256 diff);\n    event WhiteListToggle(address account, bool enabled);\n    event ManagerRevenueCompounded(uint256 amount);\n    event UserRevenueCompounded(uint256 amount);\n}\n"
      },
      "iface.sol": {
        "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport \"IERC20.sol\";\n\ninterface IMintableContract is IERC20 {\n    function mint(address account, uint256 amount) external;\n    function burn(uint256 amount) external;\n    function burnFrom(address account, uint256 amount) external;\n}\n\n// This interface is designed to be compatible with the Vyper version.\n/// @notice This is the Ethereum 2.0 deposit contract interface.\n/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs\ninterface IDepositContract {\n    /// @notice A processed deposit event.\n    event DepositEvent(\n        bytes pubkey,\n        bytes withdrawal_credentials,\n        bytes amount,\n        bytes signature,\n        bytes index\n    );\n\n    /// @notice Submit a Phase 0 DepositData object.\n    /// @param pubkey A BLS12-381 public key.\n    /// @param withdrawal_credentials Commitment to a public key for withdrawals.\n    /// @param signature A BLS12-381 signature.\n    /// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object.\n    /// Used as a protection against malformed input.\n    function deposit(\n        bytes calldata pubkey,\n        bytes calldata withdrawal_credentials,\n        bytes calldata signature,\n        bytes32 deposit_data_root\n    ) external payable;\n\n    /// @notice Query the current deposit root hash.\n    /// @return The deposit root hash.\n    function get_deposit_root() external view returns (bytes32);\n\n    /// @notice Query the current deposit count.\n    /// @return The deposit count encoded as a little endian 64-bit number.\n    function get_deposit_count() external view returns (bytes memory);\n}\n\ninterface IRedeem {\n    function pay(address account) external payable;\n}\n\ninterface IRestaking {\n    function update() external;\n    function getPendingWithdrawalAmount() external view returns (uint256);\n    function eigenPod() external view returns (address);\n    function getPod(uint256 i) external view returns (address);\n    function getTotalPods() external view returns (uint256);\n}\n\ninterface IPodOwner {\n    function transfer(address target, uint256 amount) external;\n    function execute(address target, bytes memory data) external returns(bytes memory);\n}\n"
      },
      "IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) 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 `amount` as the allowance of `spender` over the 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 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` 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(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\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"
      },
      "BytesLib.sol": {
        "content": "// SPDX-License-Identifier: Unlicense\n/*\n * @title Solidity Bytes Arrays Utils\n * @author Gonçalo Sá <goncalo.sa@consensys.net>\n *\n * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\n *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\n */\npragma solidity >=0.8.0 <0.9.0;\n\n\nlibrary BytesLib {\n    function concat(\n        bytes memory _preBytes,\n        bytes memory _postBytes\n    )\n        internal\n        pure\n        returns (bytes memory)\n    {\n        bytes memory tempBytes;\n\n        assembly {\n            // Get a location of some free memory and store it in tempBytes as\n            // Solidity does for memory variables.\n            tempBytes := mload(0x40)\n\n            // Store the length of the first bytes array at the beginning of\n            // the memory for tempBytes.\n            let length := mload(_preBytes)\n            mstore(tempBytes, length)\n\n            // Maintain a memory counter for the current write location in the\n            // temp bytes array by adding the 32 bytes for the array length to\n            // the starting location.\n            let mc := add(tempBytes, 0x20)\n            // Stop copying when the memory counter reaches the length of the\n            // first bytes array.\n            let end := add(mc, length)\n\n            for {\n                // Initialize a copy counter to the start of the _preBytes data,\n                // 32 bytes into its memory.\n                let cc := add(_preBytes, 0x20)\n            } lt(mc, end) {\n                // Increase both counters by 32 bytes each iteration.\n                mc := add(mc, 0x20)\n                cc := add(cc, 0x20)\n            } {\n                // Write the _preBytes data into the tempBytes memory 32 bytes\n                // at a time.\n                mstore(mc, mload(cc))\n            }\n\n            // Add the length of _postBytes to the current length of tempBytes\n            // and store it as the new length in the first 32 bytes of the\n            // tempBytes memory.\n            length := mload(_postBytes)\n            mstore(tempBytes, add(length, mload(tempBytes)))\n\n            // Move the memory counter back from a multiple of 0x20 to the\n            // actual end of the _preBytes data.\n            mc := end\n            // Stop copying when the memory counter reaches the new combined\n            // length of the arrays.\n            end := add(mc, length)\n\n            for {\n                let cc := add(_postBytes, 0x20)\n            } lt(mc, end) {\n                mc := add(mc, 0x20)\n                cc := add(cc, 0x20)\n            } {\n                mstore(mc, mload(cc))\n            }\n\n            // Update the free-memory pointer by padding our last write location\n            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the\n            // next 32 byte block, then round down to the nearest multiple of\n            // 32. If the sum of the length of the two arrays is zero then add\n            // one before rounding down to leave a blank 32 bytes (the length block with 0).\n            mstore(0x40, and(\n              add(add(end, iszero(add(length, mload(_preBytes)))), 31),\n              not(31) // Round down to the nearest 32 bytes.\n            ))\n        }\n\n        return tempBytes;\n    }\n\n    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {\n        assembly {\n            // Read the first 32 bytes of _preBytes storage, which is the length\n            // of the array. (We don't need to use the offset into the slot\n            // because arrays use the entire slot.)\n            let fslot := sload(_preBytes.slot)\n            // Arrays of 31 bytes or less have an even value in their slot,\n            // while longer arrays have an odd value. The actual length is\n            // the slot divided by two for odd values, and the lowest order\n            // byte divided by two for even values.\n            // If the slot is even, bitwise and the slot with 255 and divide by\n            // two to get the length. If the slot is odd, bitwise and the slot\n            // with -1 and divide by two.\n            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n            let mlength := mload(_postBytes)\n            let newlength := add(slength, mlength)\n            // slength can contain both the length and contents of the array\n            // if length < 32 bytes so let's prepare for that\n            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n            switch add(lt(slength, 32), lt(newlength, 32))\n            case 2 {\n                // Since the new array still fits in the slot, we just need to\n                // update the contents of the slot.\n                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length\n                sstore(\n                    _preBytes.slot,\n                    // all the modifications to the slot are inside this\n                    // next block\n                    add(\n                        // we can just add to the slot contents because the\n                        // bytes we want to change are the LSBs\n                        fslot,\n                        add(\n                            mul(\n                                div(\n                                    // load the bytes from memory\n                                    mload(add(_postBytes, 0x20)),\n                                    // zero all bytes to the right\n                                    exp(0x100, sub(32, mlength))\n                                ),\n                                // and now shift left the number of bytes to\n                                // leave space for the length in the slot\n                                exp(0x100, sub(32, newlength))\n                            ),\n                            // increase length by the double of the memory\n                            // bytes length\n                            mul(mlength, 2)\n                        )\n                    )\n                )\n            }\n            case 1 {\n                // The stored value fits in the slot, but the combined value\n                // will exceed it.\n                // get the keccak hash to get the contents of the array\n                mstore(0x0, _preBytes.slot)\n                let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n                // save new length\n                sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n                // The contents of the _postBytes array start 32 bytes into\n                // the structure. Our first read should obtain the `submod`\n                // bytes that can fit into the unused space in the last word\n                // of the stored array. To get this, we read 32 bytes starting\n                // from `submod`, so the data we read overlaps with the array\n                // contents by `submod` bytes. Masking the lowest-order\n                // `submod` bytes allows us to add that value directly to the\n                // stored value.\n\n                let submod := sub(32, slength)\n                let mc := add(_postBytes, submod)\n                let end := add(_postBytes, mlength)\n                let mask := sub(exp(0x100, submod), 1)\n\n                sstore(\n                    sc,\n                    add(\n                        and(\n                            fslot,\n                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00\n                        ),\n                        and(mload(mc), mask)\n                    )\n                )\n\n                for {\n                    mc := add(mc, 0x20)\n                    sc := add(sc, 1)\n                } lt(mc, end) {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } {\n                    sstore(sc, mload(mc))\n                }\n\n                mask := exp(0x100, sub(mc, end))\n\n                sstore(sc, mul(div(mload(mc), mask), mask))\n            }\n            default {\n                // get the keccak hash to get the contents of the array\n                mstore(0x0, _preBytes.slot)\n                // Start copying to the last used word of the stored array.\n                let sc := add(keccak256(0x0, 0x20), div(slength, 32))\n\n                // save new length\n                sstore(_preBytes.slot, add(mul(newlength, 2), 1))\n\n                // Copy over the first `submod` bytes of the new data as in\n                // case 1 above.\n                let slengthmod := mod(slength, 32)\n                let mlengthmod := mod(mlength, 32)\n                let submod := sub(32, slengthmod)\n                let mc := add(_postBytes, submod)\n                let end := add(_postBytes, mlength)\n                let mask := sub(exp(0x100, submod), 1)\n\n                sstore(sc, add(sload(sc), and(mload(mc), mask)))\n\n                for {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } lt(mc, end) {\n                    sc := add(sc, 1)\n                    mc := add(mc, 0x20)\n                } {\n                    sstore(sc, mload(mc))\n                }\n\n                mask := exp(0x100, sub(mc, end))\n\n                sstore(sc, mul(div(mload(mc), mask), mask))\n            }\n        }\n    }\n\n    function slice(\n        bytes memory _bytes,\n        uint256 _start,\n        uint256 _length\n    )\n        internal\n        pure\n        returns (bytes memory)\n    {\n        require(_length + 31 >= _length, \"slice_overflow\");\n        require(_bytes.length >= _start + _length, \"slice_outOfBounds\");\n\n        bytes memory tempBytes;\n\n        assembly {\n            switch iszero(_length)\n            case 0 {\n                // Get a location of some free memory and store it in tempBytes as\n                // Solidity does for memory variables.\n                tempBytes := mload(0x40)\n\n                // The first word of the slice result is potentially a partial\n                // word read from the original array. To read it, we calculate\n                // the length of that partial word and start copying that many\n                // bytes into the array. The first word we copy will start with\n                // data we don't care about, but the last `lengthmod` bytes will\n                // land at the beginning of the contents of the new array. When\n                // we're done copying, we overwrite the full first word with\n                // the actual length of the slice.\n                let lengthmod := and(_length, 31)\n\n                // The multiplication in the next line is necessary\n                // because when slicing multiples of 32 bytes (lengthmod == 0)\n                // the following copy loop was copying the origin's length\n                // and then ending prematurely not copying everything it should.\n                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n                let end := add(mc, _length)\n\n                for {\n                    // The multiplication in the next line has the same exact purpose\n                    // as the one above.\n                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n                } lt(mc, end) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    mstore(mc, mload(cc))\n                }\n\n                mstore(tempBytes, _length)\n\n                //update free-memory pointer\n                //allocating the array padded to 32 bytes like the compiler does now\n                mstore(0x40, and(add(mc, 31), not(31)))\n            }\n            //if we want a zero-length slice let's just return a zero-length array\n            default {\n                tempBytes := mload(0x40)\n                //zero out the 32 bytes slice we are about to return\n                //we need to do it because Solidity does not garbage collect\n                mstore(tempBytes, 0)\n\n                mstore(0x40, add(tempBytes, 0x20))\n            }\n        }\n\n        return tempBytes;\n    }\n\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\n        require(_bytes.length >= _start + 20, \"toAddress_outOfBounds\");\n        address tempAddress;\n\n        assembly {\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\n        }\n\n        return tempAddress;\n    }\n\n    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\n        require(_bytes.length >= _start + 1 , \"toUint8_outOfBounds\");\n        uint8 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x1), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\n        require(_bytes.length >= _start + 2, \"toUint16_outOfBounds\");\n        uint16 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x2), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\n        require(_bytes.length >= _start + 4, \"toUint32_outOfBounds\");\n        uint32 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x4), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\n        require(_bytes.length >= _start + 8, \"toUint64_outOfBounds\");\n        uint64 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x8), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {\n        require(_bytes.length >= _start + 12, \"toUint96_outOfBounds\");\n        uint96 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0xc), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\n        require(_bytes.length >= _start + 16, \"toUint128_outOfBounds\");\n        uint128 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x10), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\n        require(_bytes.length >= _start + 32, \"toUint256_outOfBounds\");\n        uint256 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\n        require(_bytes.length >= _start + 32, \"toBytes32_outOfBounds\");\n        bytes32 tempBytes32;\n\n        assembly {\n            tempBytes32 := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempBytes32;\n    }\n\n    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {\n        bool success = true;\n\n        assembly {\n            let length := mload(_preBytes)\n\n            // if lengths don't match the arrays are not equal\n            switch eq(length, mload(_postBytes))\n            case 1 {\n                // cb is a circuit breaker in the for loop since there's\n                //  no said feature for inline assembly loops\n                // cb = 1 - don't breaker\n                // cb = 0 - break\n                let cb := 1\n\n                let mc := add(_preBytes, 0x20)\n                let end := add(mc, length)\n\n                for {\n                    let cc := add(_postBytes, 0x20)\n                // the next line is the loop condition:\n                // while(uint256(mc < end) + cb == 2)\n                } eq(add(lt(mc, end), cb), 2) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } {\n                    // if any of these checks fails then arrays are not equal\n                    if iszero(eq(mload(mc), mload(cc))) {\n                        // unsuccess:\n                        success := 0\n                        cb := 0\n                    }\n                }\n            }\n            default {\n                // unsuccess:\n                success := 0\n            }\n        }\n\n        return success;\n    }\n\n    function equalStorage(\n        bytes storage _preBytes,\n        bytes memory _postBytes\n    )\n        internal\n        view\n        returns (bool)\n    {\n        bool success = true;\n\n        assembly {\n            // we know _preBytes_offset is 0\n            let fslot := sload(_preBytes.slot)\n            // Decode the length of the stored array like in concatStorage().\n            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)\n            let mlength := mload(_postBytes)\n\n            // if lengths don't match the arrays are not equal\n            switch eq(slength, mlength)\n            case 1 {\n                // slength can contain both the length and contents of the array\n                // if length < 32 bytes so let's prepare for that\n                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage\n                if iszero(iszero(slength)) {\n                    switch lt(slength, 32)\n                    case 1 {\n                        // blank the last byte which is the length\n                        fslot := mul(div(fslot, 0x100), 0x100)\n\n                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {\n                            // unsuccess:\n                            success := 0\n                        }\n                    }\n                    default {\n                        // cb is a circuit breaker in the for loop since there's\n                        //  no said feature for inline assembly loops\n                        // cb = 1 - don't breaker\n                        // cb = 0 - break\n                        let cb := 1\n\n                        // get the keccak hash to get the contents of the array\n                        mstore(0x0, _preBytes.slot)\n                        let sc := keccak256(0x0, 0x20)\n\n                        let mc := add(_postBytes, 0x20)\n                        let end := add(mc, mlength)\n\n                        // the next line is the loop condition:\n                        // while(uint256(mc < end) + cb == 2)\n                        for {} eq(add(lt(mc, end), cb), 2) {\n                            sc := add(sc, 1)\n                            mc := add(mc, 0x20)\n                        } {\n                            if iszero(eq(sload(sc), mload(mc))) {\n                                // unsuccess:\n                                success := 0\n                                cb := 0\n                            }\n                        }\n                    }\n                }\n            }\n            default {\n                // unsuccess:\n                success := 0\n            }\n        }\n\n        return success;\n    }\n}\n"
      },
      "SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"IERC20.sol\";\nimport \"Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"
      },
      "Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
      },
      "Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"AddressUpgradeable.sol\";\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 * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\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 Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 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. Equivalent to `reinitializer(1)`.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = _setInitializedVersion(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     * `initializer` is equivalent to `reinitializer(1)`, so a reinitializer may be used after the original\n     * initialization step. This is essential to configure modules that are added through upgrades and that require\n     * initialization.\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    modifier reinitializer(uint8 version) {\n        bool isTopLevelCall = _setInitializedVersion(version);\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(version);\n        }\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        require(_initializing, \"Initializable: contract is not initializing\");\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    function _disableInitializers() internal virtual {\n        _setInitializedVersion(type(uint8).max);\n    }\n\n    function _setInitializedVersion(uint8 version) private returns (bool) {\n        // If the contract is initializing we ignore whether _initialized is set in order to support multiple\n        // inheritance patterns, but we only do this in the context of a constructor, and for the lowest level\n        // of initializers, because in other contexts the contract may have been reentered.\n        if (_initializing) {\n            require(\n                version == 1 && !AddressUpgradeable.isContract(address(this)),\n                \"Initializable: contract is already initialized\"\n            );\n            return false;\n        } else {\n            require(_initialized < version, \"Initializable: contract is already initialized\");\n            _initialized = version;\n            return true;\n        }\n    }\n}\n"
      },
      "AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
      },
      "AccessControlUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"IAccessControlUpgradeable.sol\";\nimport \"ContextUpgradeable.sol\";\nimport \"StringsUpgradeable.sol\";\nimport \"ERC165Upgradeable.sol\";\nimport \"Initializable.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {\n    function __AccessControl_init() internal onlyInitializing {\n    }\n\n    function __AccessControl_init_unchained() internal onlyInitializing {\n    }\n    struct RoleData {\n        mapping(address => bool) members;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with a standardized message including the required role.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     *\n     * _Available since v4.1._\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual override returns (bool) {\n        return _roles[role].members[account];\n    }\n\n    /**\n     * @dev Revert with a standard message if `_msgSender()` is missing `role`.\n     * Overriding this function changes the behavior of the {onlyRole} modifier.\n     *\n     * Format of the revert message is described in {_checkRole}.\n     *\n     * _Available since v4.6._\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Revert with a standard message if `account` is missing `role`.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        \"AccessControl: account \",\n                        StringsUpgradeable.toHexString(uint160(account), 20),\n                        \" is missing role \",\n                        StringsUpgradeable.toHexString(uint256(role), 32)\n                    )\n                )\n            );\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) public virtual override {\n        require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event. Note that unlike {grantRole}, this function doesn't perform any\n     * checks on the calling account.\n     *\n     * [WARNING]\n     * ====\n     * This function should only be called from the constructor when setting\n     * up the initial roles for the system.\n     *\n     * Using this function in any other way is effectively circumventing the admin\n     * system imposed by {AccessControl}.\n     * ====\n     *\n     * NOTE: This function is deprecated in favor of {_grantRole}.\n     */\n    function _setupRole(bytes32 role, address account) internal virtual {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * Internal function without access restriction.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual {\n        if (!hasRole(role, account)) {\n            _roles[role].members[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n        }\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * Internal function without access restriction.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual {\n        if (hasRole(role, account)) {\n            _roles[role].members[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n        }\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"
      },
      "IAccessControlUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControlUpgradeable {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"
      },
      "ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"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    /**\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[50] private __gap;\n}\n"
      },
      "StringsUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary StringsUpgradeable {\n    bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        // Inspired by OraclizeAPI's implementation - MIT licence\n        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n        if (value == 0) {\n            return \"0\";\n        }\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0x00\";\n        }\n        uint256 temp = value;\n        uint256 length = 0;\n        while (temp != 0) {\n            length++;\n            temp >>= 8;\n        }\n        return toHexString(value, length);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _HEX_SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n}\n"
      },
      "ERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"IERC165Upgradeable.sol\";\nimport \"Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {\n    function __ERC165_init() internal onlyInitializing {\n    }\n\n    function __ERC165_init_unchained() internal onlyInitializing {\n    }\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165Upgradeable).interfaceId;\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[50] private __gap;\n}\n"
      },
      "IERC165Upgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165Upgradeable {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
      },
      "PausableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"ContextUpgradeable.sol\";\nimport \"Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    function __Pausable_init() internal onlyInitializing {\n        __Pausable_init_unchained();\n    }\n\n    function __Pausable_init_unchained() internal onlyInitializing {\n        _paused = false;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        require(!paused(), \"Pausable: paused\");\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        require(paused(), \"Pausable: not paused\");\n        _;\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\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"
      },
      "ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"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        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\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 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"
      },
      "SafeCast.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n    /**\n     * @dev Returns the downcasted uint224 from uint256, reverting on\n     * overflow (when the input is greater than largest uint224).\n     *\n     * Counterpart to Solidity's `uint224` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 224 bits\n     */\n    function toUint224(uint256 value) internal pure returns (uint224) {\n        require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n        return uint224(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint128 from uint256, reverting on\n     * overflow (when the input is greater than largest uint128).\n     *\n     * Counterpart to Solidity's `uint128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     */\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return uint128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint96 from uint256, reverting on\n     * overflow (when the input is greater than largest uint96).\n     *\n     * Counterpart to Solidity's `uint96` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 96 bits\n     */\n    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n        return uint96(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint64 from uint256, reverting on\n     * overflow (when the input is greater than largest uint64).\n     *\n     * Counterpart to Solidity's `uint64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     */\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return uint64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint32 from uint256, reverting on\n     * overflow (when the input is greater than largest uint32).\n     *\n     * Counterpart to Solidity's `uint32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     */\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return uint32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint16 from uint256, reverting on\n     * overflow (when the input is greater than largest uint16).\n     *\n     * Counterpart to Solidity's `uint16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     */\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return uint16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted uint8 from uint256, reverting on\n     * overflow (when the input is greater than largest uint8).\n     *\n     * Counterpart to Solidity's `uint8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits.\n     */\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return uint8(value);\n    }\n\n    /**\n     * @dev Converts a signed int256 into an unsigned uint256.\n     *\n     * Requirements:\n     *\n     * - input must be greater than or equal to 0.\n     */\n    function toUint256(int256 value) internal pure returns (uint256) {\n        require(value >= 0, \"SafeCast: value must be positive\");\n        return uint256(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int128 from int256, reverting on\n     * overflow (when the input is less than smallest int128 or\n     * greater than largest int128).\n     *\n     * Counterpart to Solidity's `int128` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 128 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt128(int256 value) internal pure returns (int128) {\n        require(value >= type(int128).min && value <= type(int128).max, \"SafeCast: value doesn't fit in 128 bits\");\n        return int128(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int64 from int256, reverting on\n     * overflow (when the input is less than smallest int64 or\n     * greater than largest int64).\n     *\n     * Counterpart to Solidity's `int64` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 64 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt64(int256 value) internal pure returns (int64) {\n        require(value >= type(int64).min && value <= type(int64).max, \"SafeCast: value doesn't fit in 64 bits\");\n        return int64(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int32 from int256, reverting on\n     * overflow (when the input is less than smallest int32 or\n     * greater than largest int32).\n     *\n     * Counterpart to Solidity's `int32` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 32 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt32(int256 value) internal pure returns (int32) {\n        require(value >= type(int32).min && value <= type(int32).max, \"SafeCast: value doesn't fit in 32 bits\");\n        return int32(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int16 from int256, reverting on\n     * overflow (when the input is less than smallest int16 or\n     * greater than largest int16).\n     *\n     * Counterpart to Solidity's `int16` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 16 bits\n     *\n     * _Available since v3.1._\n     */\n    function toInt16(int256 value) internal pure returns (int16) {\n        require(value >= type(int16).min && value <= type(int16).max, \"SafeCast: value doesn't fit in 16 bits\");\n        return int16(value);\n    }\n\n    /**\n     * @dev Returns the downcasted int8 from int256, reverting on\n     * overflow (when the input is less than smallest int8 or\n     * greater than largest int8).\n     *\n     * Counterpart to Solidity's `int8` operator.\n     *\n     * Requirements:\n     *\n     * - input must fit into 8 bits.\n     *\n     * _Available since v3.1._\n     */\n    function toInt8(int256 value) internal pure returns (int8) {\n        require(value >= type(int8).min && value <= type(int8).max, \"SafeCast: value doesn't fit in 8 bits\");\n        return int8(value);\n    }\n\n    /**\n     * @dev Converts an unsigned uint256 into a signed int256.\n     *\n     * Requirements:\n     *\n     * - input must be less than or equal to maxInt256.\n     */\n    function toInt256(uint256 value) internal pure returns (int256) {\n        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n        require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n        return int256(value);\n    }\n}\n"
      }
    },
    "settings": {
      "evmVersion": "istanbul",
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "libraries": {
        "staking.sol": {}
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      }
    }
  }}