creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/NodeDelegator.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n// openzeppelin or other standard contracts\nimport { IERC20 } from \"@openzeppelin/contracts/interfaces/IERC20.sol\";\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\n// external libraries, interfaces, contracts\nimport { BeaconChainProofs } from \"./external/eigenlayer/libraries/BeaconChainProofs.sol\";\n\nimport { IEigenPod, IBeaconDeposit } from \"./external/eigenlayer/interfaces/IEigenPod.sol\";\nimport { IStrategy } from \"./external/eigenlayer/interfaces/IStrategy.sol\";\nimport { IEigenStrategyManager } from \"./external/eigenlayer/interfaces/IEigenStrategyManager.sol\";\nimport { IEigenPodManager } from \"./external/eigenlayer/interfaces/IEigenPodManager.sol\";\nimport { IEigenDelegationManager } from \"./external/eigenlayer/interfaces/IEigenDelegationManager.sol\";\nimport { IEigenDelayedWithdrawalRouter } from \"./external/eigenlayer/interfaces/IEigenDelayedWithdrawalRouter.sol\";\n\n// protocol libraries, interfaces, contracts\nimport { UtilLib } from \"./utils/UtilLib.sol\";\nimport { LRTConstants } from \"./utils/LRTConstants.sol\";\nimport { LRTConfigRoleChecker } from \"./utils/LRTConfigRoleChecker.sol\";\n\nimport { ILRTConfig } from \"./interfaces/ILRTConfig.sol\";\nimport { INodeDelegator } from \"./interfaces/INodeDelegator.sol\";\nimport { ILRTUnstakingVault } from \"./interfaces/ILRTUnstakingVault.sol\";\nimport { ILRTDepositPool } from \"./interfaces/ILRTDepositPool.sol\";\nimport { IFeeReceiver } from \"./interfaces/IFeeReceiver.sol\";\n\n/// @title NodeDelegator Contract\n/// @notice The contract that handles the depositing of assets into strategies\ncontract NodeDelegator is INodeDelegator, LRTConfigRoleChecker, PausableUpgradeable, ReentrancyGuardUpgradeable {\n    using SafeERC20 for IERC20;\n\n    /// @dev The EigenPod is created and owned by this contract\n    IEigenPod public eigenPod;\n\n    /// @dev Tracks the balance staked to validators and has yet to have the credentials verified with EigenLayer.\n    /// call verifyWithdrawalCredentialsAndBalance in EL to verify the validator credentials on EigenLayer\n    uint256 public stakedButUnverifiedNativeETH;\n\n    /// @dev address of eigenlayer operator to which all restaked funds are delegated to\n    /// @dev it is only possible to delegate fully to only one operator per NDC contract\n    address public elOperatorDelegatedTo;\n\n    /// @dev amount of eth expected to receive from extra eth staked for validators\n    uint256 public extraStakeToReceive;\n\n    /// @custom:oz-upgrades-unsafe-allow constructor\n    constructor() {\n        _disableInitializers();\n    }\n\n    /// @dev Initializes the contract\n    /// @param lrtConfigAddr LRT config address\n    function initialize(address lrtConfigAddr) external initializer {\n        UtilLib.checkNonZeroAddress(lrtConfigAddr);\n        __Pausable_init();\n        __ReentrancyGuard_init();\n\n        lrtConfig = ILRTConfig(lrtConfigAddr);\n        emit UpdatedLRTConfig(lrtConfigAddr);\n    }\n\n    /// @dev due to a bit heavy logic, eth transfer using `transfer()` and `send()` will fail\n    /// @dev hence please use `call()` to send eth to this contract\n    receive() external payable {\n        if (msg.sender != address(eigenPod)) {\n            // then these are extraStakes or rewards\n            uint256 extraStakeReceived = UtilLib.getMin(msg.value, extraStakeToReceive);\n            _reduceExtraStakes(extraStakeReceived);\n\n            // rest are rewards\n            _sendRewardsToRewardReceiver(msg.value - extraStakeReceived);\n        }\n        // else if received from eigenPod\n        // then these are assumed to be exit validators' eth\n        // just receive it here\n        emit ETHReceived(msg.sender, msg.value);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            EigenLayer Interactions\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Deposits an asset lying in this NDC into its strategy\n    /// @dev only supported assets can be deposited and only called by the LRT manager\n    /// @param asset the asset to deposit\n    function depositAssetIntoStrategy(address asset)\n        external\n        override\n        nonReentrant\n        whenNotPaused\n        onlySupportedAsset(asset)\n        onlyLRTManager\n    {\n        address strategy = lrtConfig.assetStrategy(asset);\n        if (strategy == address(0)) {\n            revert StrategyIsNotSetForAsset();\n        }\n\n        IERC20 token = IERC20(asset);\n        address eigenlayerStrategyManagerAddress = lrtConfig.getContract(LRTConstants.EIGEN_STRATEGY_MANAGER);\n\n        uint256 balance = token.balanceOf(address(this));\n\n        IEigenStrategyManager(eigenlayerStrategyManagerAddress).depositIntoStrategy(IStrategy(strategy), token, balance);\n\n        emit AssetDepositIntoStrategy(asset, strategy, balance);\n    }\n\n    /// @notice Delegates shares (accrued by restaking LSTs/native eth) to an EigenLayer operator\n    /// @param elOperator The address of the operator to delegate to\n    /// @param approverSignatureAndExpiry Verifies the operator approves of this delegation\n    /// @param approverSalt A unique single use value tied to an individual signature.\n    /// @dev delegationManager.delegateTo will check if the operator is valid, if ndc is already delegated to\n    function delegateTo(\n        address elOperator,\n        IEigenDelegationManager.SignatureWithExpiry memory approverSignatureAndExpiry,\n        bytes32 approverSalt\n    )\n        external\n        onlyLRTManager\n    {\n        UtilLib.checkNonZeroAddress(elOperator);\n        elOperatorDelegatedTo = elOperator;\n\n        IEigenDelegationManager elDelegationManager =\n            IEigenDelegationManager(lrtConfig.getContract(LRTConstants.EIGEN_DELEGATION_MANAGER));\n        elDelegationManager.delegateTo(elOperator, approverSignatureAndExpiry, approverSalt);\n        emit ElSharesDelegated(elOperator);\n    }\n\n    function createEigenPod() external onlyLRTManager {\n        IEigenPodManager eigenPodManager = IEigenPodManager(lrtConfig.getContract(LRTConstants.EIGEN_POD_MANAGER));\n        eigenPodManager.createPod();\n        eigenPod = eigenPodManager.ownerToPod(address(this));\n\n        emit EigenPodCreated(address(eigenPod), address(this));\n    }\n\n    /// @dev activates eigenPod, i.e. enables all M2 functions\n    /// restricts execution of few functions, check `hasEnabledRestaking` modifier in EigenPod\n    /// NOTE: creates a delayedWithdrawal for the eth accumulated on eigenPod (skimmed from beacon chain)\n    /// NOTE: newly created M2 pods are already activated\n    function activateRestaking() external onlyLRTManager {\n        eigenPod.activateRestaking();\n        emit RestakingActivated();\n    }\n\n    /// @notice Stake ETH from NDC into EigenLayer. it calls the stake function in the EigenPodManager\n    /// which in turn calls the stake function in the EigenPod\n    /// @param pubkey The pubkey of the validator\n    /// @param signature The signature of the validator\n    /// @param depositDataRoot The deposit data root of the validator\n    /// @dev Only LRT Operator should call this function\n    /// @dev Exactly 32 ether is allowed, hence it is hardcoded\n    /// @dev offchain checks withdraw credentials authenticity\n    function stake32Eth(\n        bytes calldata pubkey,\n        bytes calldata signature,\n        bytes32 depositDataRoot\n    )\n        external\n        whenNotPaused\n        onlyLRTOperator\n    {\n        // tracks staked but unverified native ETH\n        stakedButUnverifiedNativeETH += 32 ether;\n\n        IEigenPodManager eigenPodManager = IEigenPodManager(lrtConfig.getContract(LRTConstants.EIGEN_POD_MANAGER));\n        eigenPodManager.stake{ value: 32 ether }(pubkey, signature, depositDataRoot);\n\n        emit ETHStaked(pubkey, 32 ether);\n    }\n\n    /// @notice Stake ETH from NDC into EigenLayer\n    /// @param pubkey The pubkey of the validator\n    /// @param signature The signature of the validator\n    /// @param depositDataRoot The deposit data root of the validator\n    /// @param expectedDepositRoot The expected deposit data root, which is computed offchain\n    /// @dev Only LRT Operator should call this function\n    /// @dev Exactly 32 ether is allowed, hence it is hardcoded\n    /// @dev offchain checks withdraw credentials authenticity\n    /// @dev compares expected deposit root with actual deposit root\n    function stake32EthValidated(\n        bytes calldata pubkey,\n        bytes calldata signature,\n        bytes32 depositDataRoot,\n        bytes32 expectedDepositRoot\n    )\n        external\n        whenNotPaused\n        onlyLRTOperator\n    {\n        IBeaconDeposit depositContract = eigenPod.ethPOS();\n        bytes32 actualDepositRoot = depositContract.get_deposit_root();\n        if (expectedDepositRoot != actualDepositRoot) {\n            revert InvalidDepositRoot(expectedDepositRoot, actualDepositRoot);\n        }\n\n        // tracks staked but unverified native ETH\n        stakedButUnverifiedNativeETH += 32 ether;\n\n        IEigenPodManager eigenPodManager = IEigenPodManager(lrtConfig.getContract(LRTConstants.EIGEN_POD_MANAGER));\n        eigenPodManager.stake{ value: 32 ether }(pubkey, signature, depositDataRoot);\n\n        emit ETHStaked(pubkey, 32 ether);\n    }\n\n    /**\n     * @notice This function verifies that the withdrawal credentials of validator(s) owned by the this NDC are pointed\n     * to EigenPod. It also verifies the effective balance of the validator.  It verifies the provided proof of the\n     * ETH validator against the beacon chain state root, marks the validator as 'active' in EigenLayer, and credits the\n     * restaked ETH in Eigenlayer.\n     * @param oracleTimestamp is the Beacon Chain timestamp whose state root the `proof` will be proven against.\n     * @param validatorIndices is the list of indices of the validators being proven, refer to consensus specs\n     * @param withdrawalCredentialProofs is an array of proofs, where each proof proves each ETH validator's balance and\n     * withdrawal credentials against a beacon chain state root\n     * @param validatorFields are the fields of the \"Validator Container\", refer to consensus specs\n     * for details: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator\n     */\n    function verifyWithdrawalCredentials(\n        uint64 oracleTimestamp,\n        BeaconChainProofs.StateRootProof calldata stateRootProof,\n        uint40[] calldata validatorIndices,\n        bytes[] calldata withdrawalCredentialProofs,\n        bytes32[][] calldata validatorFields\n    )\n        external\n        onlyLRTOperator\n    {\n        // reduce the eth amount that is verified\n        stakedButUnverifiedNativeETH -= (validatorFields.length * (32 ether));\n\n        eigenPod.verifyWithdrawalCredentials(\n            oracleTimestamp, stateRootProof, validatorIndices, withdrawalCredentialProofs, validatorFields\n        );\n    }\n\n    /// @notice undelegates from operator and removes all currently active shares\n    function undelegate() external whenNotPaused onlyLRTManager {\n        elOperatorDelegatedTo = address(0);\n\n        IEigenDelegationManager elDelegationManager =\n            IEigenDelegationManager(lrtConfig.getContract(LRTConstants.EIGEN_DELEGATION_MANAGER));\n        ILRTUnstakingVault lrtUnstakingVault =\n            ILRTUnstakingVault(lrtConfig.getContract(LRTConstants.LRT_UNSTAKING_VAULT));\n        address beaconChainETHStrategy = lrtConfig.getContract(LRTConstants.BEACON_CHAIN_ETH_STRATEGY);\n\n        // Gather strategies and shares which will be removed from staker/operator during undelegation\n        (IStrategy[] memory strategies, uint256[] memory shares) =\n            elDelegationManager.getDelegatableShares(address(this));\n\n        // update shares unstaking in LRT unstaking vault\n        for (uint256 i = 0; i < strategies.length;) {\n            if (beaconChainETHStrategy == address(strategies[i])) {\n                lrtUnstakingVault.addSharesUnstaking(LRTConstants.ETH_TOKEN, shares[i]);\n            } else {\n                address token = address(strategies[i].underlyingToken());\n                lrtUnstakingVault.addSharesUnstaking(token, shares[i]);\n            }\n            unchecked {\n                ++i;\n            }\n        }\n\n        uint256 nonce = elDelegationManager.cumulativeWithdrawalsQueued(address(this));\n        bytes32[] memory withdrawalRoots = elDelegationManager.undelegate(address(this));\n\n        emit WithdrawalQueued(nonce, address(this), withdrawalRoots);\n        emit Undelegated();\n    }\n\n    /// @notice Queues a withdrawal from the strategies\n    /// @param strategies Array of strategies withdrawals\n    /// @param shares Array of shares to withdraw\n    function initiateUnstaking(\n        IStrategy[] calldata strategies,\n        uint256[] calldata shares\n    )\n        public\n        override\n        nonReentrant\n        whenNotPaused\n        onlyLRTOperator\n        returns (bytes32 withdrawalRoot)\n    {\n        IEigenDelegationManager.QueuedWithdrawalParams memory queuedWithdrawalParam = IEigenDelegationManager\n            .QueuedWithdrawalParams({ strategies: strategies, shares: shares, withdrawer: address(this) });\n\n        address beaconChainETHStrategy = lrtConfig.getContract(LRTConstants.BEACON_CHAIN_ETH_STRATEGY);\n\n        ILRTUnstakingVault lrtUnstakingVault =\n            ILRTUnstakingVault(lrtConfig.getContract(LRTConstants.LRT_UNSTAKING_VAULT));\n        for (uint256 i = 0; i < queuedWithdrawalParam.strategies.length;) {\n            if (beaconChainETHStrategy == address(queuedWithdrawalParam.strategies[i])) {\n                lrtUnstakingVault.addSharesUnstaking(LRTConstants.ETH_TOKEN, queuedWithdrawalParam.shares[i]);\n            } else {\n                address token = address(queuedWithdrawalParam.strategies[i].underlyingToken());\n                address strategy = lrtConfig.assetStrategy(token);\n\n                if (strategy != address(queuedWithdrawalParam.strategies[i])) {\n                    revert StrategyIsNotSetForAsset();\n                }\n                lrtUnstakingVault.addSharesUnstaking(token, queuedWithdrawalParam.shares[i]);\n            }\n\n            unchecked {\n                ++i;\n            }\n        }\n        address elDelegationManagerAddr = lrtConfig.getContract(LRTConstants.EIGEN_DELEGATION_MANAGER);\n        IEigenDelegationManager elDelegationManager = IEigenDelegationManager(elDelegationManagerAddr);\n\n        IEigenDelegationManager.QueuedWithdrawalParams[] memory queuedWithdrawalParams =\n            new IEigenDelegationManager.QueuedWithdrawalParams[](1);\n        queuedWithdrawalParams[0] = queuedWithdrawalParam;\n        uint256 nonce = elDelegationManager.cumulativeWithdrawalsQueued(address(this));\n        bytes32[] memory withdrawalRoots = elDelegationManager.queueWithdrawals(queuedWithdrawalParams);\n        withdrawalRoot = withdrawalRoots[0];\n\n        emit WithdrawalQueued(nonce, address(this), withdrawalRoots);\n    }\n\n    /// @notice Finalizes Eigenlayer withdrawal to enable processing of queued withdrawals\n    /// @param withdrawal Struct containing all data for the withdrawal\n    /// @param assets Array specifying the `token` input for each strategy's 'withdraw' function.\n    /// @param middlewareTimesIndex Index in the middleware times array for withdrawal eligibility check.\n    function completeUnstaking(\n        IEigenDelegationManager.Withdrawal calldata withdrawal,\n        IERC20[] calldata assets,\n        uint256 middlewareTimesIndex\n    )\n        external\n        nonReentrant\n        whenNotPaused\n        onlyLRTOperator\n    {\n        uint256 assetCount = assets.length;\n        if (assetCount == 0 || assetCount != withdrawal.shares.length) {\n            // asset length and strategies length is checked by eigenlayer contracts in `completeQueuedWithdrawal`\n            revert InvalidWithdrawalData();\n        }\n\n        address elDelegationManagerAddr = lrtConfig.getContract(LRTConstants.EIGEN_DELEGATION_MANAGER);\n        address beaconChainETHStrategy = lrtConfig.getContract(LRTConstants.BEACON_CHAIN_ETH_STRATEGY);\n        address lrtUnstakingVaultAddr = lrtConfig.getContract(LRTConstants.LRT_UNSTAKING_VAULT);\n\n        ILRTUnstakingVault lrtUnstakingVault = ILRTUnstakingVault(lrtUnstakingVaultAddr);\n\n        uint256[] memory balancesBefore = new uint256[](assetCount);\n        for (uint256 i = 0; i < assetCount;) {\n            lrtUnstakingVault.reduceSharesUnstaking(address(assets[i]), withdrawal.shares[i]);\n            if (address(beaconChainETHStrategy) != address(withdrawal.strategies[i])) {\n                balancesBefore[i] = assets[i].balanceOf(address(this));\n            } else {\n                balancesBefore[i] = address(this).balance;\n            }\n            unchecked {\n                i++;\n            }\n        }\n\n        // Finalize withdrawal with Eigenlayer Delegation Manager\n        IEigenDelegationManager(elDelegationManagerAddr).completeQueuedWithdrawal(\n            withdrawal, assets, middlewareTimesIndex, true\n        );\n\n        for (uint256 i = 0; i < assetCount;) {\n            if (address(beaconChainETHStrategy) != address(withdrawal.strategies[i])) {\n                uint256 amount = assets[i].balanceOf(address(this)) - balancesBefore[i];\n                assets[i].transfer(lrtUnstakingVaultAddr, amount);\n            }\n            unchecked {\n                i++;\n            }\n        }\n        emit EigenLayerWithdrawalCompleted(withdrawal.staker, withdrawal.nonce, msg.sender);\n    }\n\n    /// @notice initiate a delayed withdraw of ETH available at eigenPod\n    /// @dev this eth will be available to claim after withdrawalDelay blocks\n    /// @dev this method will be deprecated once eigenPod is activated\n    /// TODO: remove this function after eigenPod activation\n    function withdrawBeforeRestaking() external onlyLRTOperator {\n        eigenPod.withdrawBeforeRestaking();\n    }\n\n    /// @notice claim delayed withdrawal entries (rewards + extraStakes)\n    /// @param maxNumberOfDelayedWithdrawalsToClaim the max number of delayed withdrawals to claim\n    /// @dev available to claim after a waiting period of withdrawalBlockDelay set by eigenLayer\n    /// @dev permissionless call\n    function claimDelayedWithdrawals(uint256 maxNumberOfDelayedWithdrawalsToClaim) external {\n        address delayedRouterAddr = eigenPod.delayedWithdrawalRouter();\n        IEigenDelayedWithdrawalRouter elDelayedRouter = IEigenDelayedWithdrawalRouter(delayedRouterAddr);\n        elDelayedRouter.claimDelayedWithdrawals(address(this), maxNumberOfDelayedWithdrawalsToClaim);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    Operational Functions\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Sends ETH from the LRT deposit pool to this contract\n    function sendETHFromDepositPoolToNDC() external payable override {\n        // only allow LRT deposit pool to send ETH to this contract\n        address lrtDepositPool = lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL);\n        if (msg.sender != lrtDepositPool) {\n            revert InvalidETHSender();\n        }\n\n        emit ETHDepositFromDepositPool(msg.value);\n    }\n\n    /// @notice Transfers an asset back to the LRT deposit pool\n    /// @dev only supported assets can be transferred and only called by the LRT manager\n    /// @param asset the asset to transfer\n    /// @param amount the amount to transfer\n    function transferBackToLRTDepositPool(\n        address asset,\n        uint256 amount\n    )\n        external\n        nonReentrant\n        whenNotPaused\n        onlySupportedAsset(asset)\n        onlyLRTManager\n    {\n        address lrtDepositPool = lrtConfig.getContract(LRTConstants.LRT_DEPOSIT_POOL);\n\n        if (asset == LRTConstants.ETH_TOKEN) {\n            ILRTDepositPool(lrtDepositPool).receiveFromNodeDelegator{ value: amount }();\n            emit EthTransferred(lrtDepositPool, amount);\n        } else {\n            IERC20(asset).safeTransfer(lrtDepositPool, amount);\n        }\n    }\n\n    /// @notice Transfers ETH back to the LRT Unstaking Vault\n    /// @dev only supported assets can be transferred and only called by the LRT manager\n    /// @param amount the amount to transfer\n    function transferETHToLRTUnstakingVault(uint256 amount) external nonReentrant whenNotPaused onlyLRTManager {\n        address lrtUnstakingVault = lrtConfig.getContract(LRTConstants.LRT_UNSTAKING_VAULT);\n        ILRTUnstakingVault(lrtUnstakingVault).receiveFromNodeDelegator{ value: amount }();\n        emit EthTransferred(lrtUnstakingVault, amount);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    Other Write Functions\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Approves the maximum amount of an asset to the eigen strategy manager\n    /// @dev only supported assets can be deposited and only called by the LRT manager\n    /// @param asset the asset to deposit\n    function maxApproveToEigenStrategyManager(address asset)\n        external\n        override\n        onlySupportedAsset(asset)\n        onlyLRTManager\n    {\n        address eigenlayerStrategyManagerAddress = lrtConfig.getContract(LRTConstants.EIGEN_STRATEGY_MANAGER);\n        IERC20(asset).approve(eigenlayerStrategyManagerAddress, type(uint256).max);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                    Setters / Update Functions\n    //////////////////////////////////////////////////////////////*/\n\n    /// @dev increments the amount of eth expected to receive from extra eth staked for validators\n    /// @param amount the amount to increment\n    function incrementExtraStakeToReceive(uint256 amount) external onlyLRTOperator {\n        extraStakeToReceive += amount;\n        if (extraStakeToReceive > stakedButUnverifiedNativeETH) {\n            revert InsufficientStakedButUnverifiedNativeETH();\n        }\n        emit ETHExtraStakeToReceiveIncremented(amount);\n    }\n\n    /// @dev Triggers stopped state. Contract must not be paused.\n    function pause() external onlyLRTManager {\n        _pause();\n    }\n\n    /// @dev Returns to normal state. Contract must be paused\n    function unpause() external onlyLRTAdmin {\n        _unpause();\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            View Functions\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Fetches balance of all assets staked in eigen layer through this contract\n    /// @return assets the assets that the node delegator has deposited into strategies\n    /// @return assetBalances the balances of the assets that the node delegator has deposited into strategies\n    function getAssetBalances()\n        external\n        view\n        override\n        returns (address[] memory assets, uint256[] memory assetBalances)\n    {\n        address eigenlayerStrategyManagerAddress = lrtConfig.getContract(LRTConstants.EIGEN_STRATEGY_MANAGER);\n\n        (IStrategy[] memory strategies,) =\n            IEigenStrategyManager(eigenlayerStrategyManagerAddress).getDeposits(address(this));\n\n        uint256 strategiesLength = strategies.length;\n        assets = new address[](strategiesLength);\n        assetBalances = new uint256[](strategiesLength);\n\n        for (uint256 i = 0; i < strategiesLength;) {\n            assets[i] = address(IStrategy(strategies[i]).underlyingToken());\n            assetBalances[i] = IStrategy(strategies[i]).userUnderlyingView(address(this));\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    /// @dev Returns the balance of an asset that the node delegator has deposited into the strategy\n    /// @param asset the asset to get the balance of\n    /// @return stakedBalance the balance of the asset\n    function getAssetBalance(address asset) external view override returns (uint256) {\n        address strategy = lrtConfig.assetStrategy(asset);\n        if (strategy == address(0)) {\n            return 0;\n        }\n\n        return IStrategy(strategy).userUnderlyingView(address(this));\n    }\n\n    /// @dev Returns the amount of eth staked in eigenlayer through this ndc\n    function getETHEigenPodBalance() external view override returns (uint256 ethStaked) {\n        IEigenPodManager eigenPodManager = IEigenPodManager(lrtConfig.getContract(LRTConstants.EIGEN_POD_MANAGER));\n        int256 nativeEthShares = eigenPodManager.podOwnerShares(address(this));\n\n        if (nativeEthShares < 0) {\n            // native eth shares are negative due to slashing and queue of more amount of eth withdrawal\n            uint256 nativeEthSharesDeficit = uint256(-nativeEthShares);\n            if (nativeEthSharesDeficit > stakedButUnverifiedNativeETH) {\n                return 0;\n            } else {\n                return stakedButUnverifiedNativeETH - nativeEthSharesDeficit;\n            }\n        }\n\n        return stakedButUnverifiedNativeETH + uint256(nativeEthShares);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            internal functions\n    //////////////////////////////////////////////////////////////*/\n\n    function _reduceExtraStakes(uint256 extraStakeReceived) internal {\n        if (extraStakeReceived <= 0) return;\n\n        extraStakeToReceive -= extraStakeReceived;\n        stakedButUnverifiedNativeETH -= extraStakeReceived;\n        emit ExtraStakeReceived(extraStakeReceived);\n    }\n\n    function _sendRewardsToRewardReceiver(uint256 rewardsAmount) internal {\n        if (rewardsAmount == 0) return;\n\n        address rewardReceiver = lrtConfig.getContract(LRTConstants.REWARD_RECEIVER);\n        IFeeReceiver(rewardReceiver).receiveFromNodeDelegator{ value: rewardsAmount }();\n        emit ETHRewardsReceived(rewardsAmount);\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/interfaces/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../token/ERC20/IERC20.sol\";\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/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 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        _requireNotPaused();\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        _requirePaused();\n        _;\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 Throws if the contract is paused.\n     */\n    function _requireNotPaused() internal view virtual {\n        require(!paused(), \"Pausable: paused\");\n    }\n\n    /**\n     * @dev Throws if the contract is not paused.\n     */\n    function _requirePaused() internal view virtual {\n        require(paused(), \"Pausable: not paused\");\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"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/security/ReentrancyGuardUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    function __ReentrancyGuard_init() internal onlyInitializing {\n        __ReentrancyGuard_init_unchained();\n    }\n\n    function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and making it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        _nonReentrantBefore();\n        _;\n        _nonReentrantAfter();\n    }\n\n    function _nonReentrantBefore() private {\n        // On the first call to nonReentrant, _status will be _NOT_ENTERED\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n    }\n\n    function _nonReentrantAfter() private {\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n     * `nonReentrant` function in the call stack.\n     */\n    function _reentrancyGuardEntered() internal view returns (bool) {\n        return _status == _ENTERED;\n    }\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n     */\n    uint256[49] private __gap;\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/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    /**\n     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeTransfer(IERC20 token, address to, uint256 value) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    /**\n     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the\n     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.\n     */\n    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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    /**\n     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        uint256 oldAllowance = token.allowance(address(this), spender);\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n    }\n\n    /**\n     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful.\n     */\n    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\n        }\n    }\n\n    /**\n     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,\n     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval\n     * to be set to zero before setting it to a non-zero value, such as USDT.\n     */\n    function forceApprove(IERC20 token, address spender, uint256 value) internal {\n        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n        if (!_callOptionalReturnBool(token, approvalCall)) {\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n            _callOptionalReturn(token, approvalCall);\n        }\n    }\n\n    /**\n     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n     * Revert on invalid signature.\n     */\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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        require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\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     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.\n     */\n    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {\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 cannot use {Address-functionCall} here since this should return false\n        // and not revert is the subcall reverts.\n\n        (bool success, bytes memory returndata) = address(token).call(data);\n        return\n            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n    }\n}\n"
      },
      "contracts/external/eigenlayer/libraries/BeaconChainProofs.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"./Merkle.sol\";\nimport \"./Endian.sol\";\n\n//Utility library for parsing and PHASE0 beacon chain block headers\n//SSZ Spec: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization\n//BeaconBlockHeader Spec:\n// https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblockheader\n//BeaconState Spec: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconstate\nlibrary BeaconChainProofs {\n    // constants are the number of fields and the heights of the different merkle trees used in merkleizing beacon chain\n    // containers\n    uint256 internal constant BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT = 3;\n\n    uint256 internal constant BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT = 4;\n\n    uint256 internal constant BEACON_STATE_FIELD_TREE_HEIGHT = 5;\n\n    uint256 internal constant VALIDATOR_FIELD_TREE_HEIGHT = 3;\n\n    //Note: changed in the deneb hard fork from 4->5\n    uint256 internal constant EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT_DENEB = 5;\n    uint256 internal constant EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT_CAPELLA = 4;\n\n    // SLOTS_PER_HISTORICAL_ROOT = 2**13, so tree height is 13\n    uint256 internal constant BLOCK_ROOTS_TREE_HEIGHT = 13;\n\n    //HISTORICAL_ROOTS_LIMIT = 2**24, so tree height is 24\n    uint256 internal constant HISTORICAL_SUMMARIES_TREE_HEIGHT = 24;\n\n    //Index of block_summary_root in historical_summary container\n    uint256 internal constant BLOCK_SUMMARY_ROOT_INDEX = 0;\n\n    // tree height for hash tree of an individual withdrawal container\n    uint256 internal constant WITHDRAWAL_FIELD_TREE_HEIGHT = 2;\n\n    uint256 internal constant VALIDATOR_TREE_HEIGHT = 40;\n\n    // MAX_WITHDRAWALS_PER_PAYLOAD = 2**4, making tree height = 4\n    uint256 internal constant WITHDRAWALS_TREE_HEIGHT = 4;\n\n    //in beacon block body\n    // https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/beacon-chain.md#beaconblockbody\n    uint256 internal constant EXECUTION_PAYLOAD_INDEX = 9;\n\n    // in beacon block header\n    // https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblockheader\n    uint256 internal constant SLOT_INDEX = 0;\n    uint256 internal constant STATE_ROOT_INDEX = 3;\n    uint256 internal constant BODY_ROOT_INDEX = 4;\n    // in beacon state https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/beacon-chain.md#beaconstate\n    uint256 internal constant VALIDATOR_TREE_ROOT_INDEX = 11;\n    uint256 internal constant HISTORICAL_SUMMARIES_INDEX = 27;\n\n    // in validator https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator\n    uint256 internal constant VALIDATOR_PUBKEY_INDEX = 0;\n    uint256 internal constant VALIDATOR_WITHDRAWAL_CREDENTIALS_INDEX = 1;\n    uint256 internal constant VALIDATOR_BALANCE_INDEX = 2;\n    uint256 internal constant VALIDATOR_WITHDRAWABLE_EPOCH_INDEX = 7;\n\n    // in execution payload header\n    uint256 internal constant TIMESTAMP_INDEX = 9;\n\n    //in execution payload\n    uint256 internal constant WITHDRAWALS_INDEX = 14;\n\n    // in withdrawal\n    uint256 internal constant WITHDRAWAL_VALIDATOR_INDEX_INDEX = 1;\n    uint256 internal constant WITHDRAWAL_VALIDATOR_AMOUNT_INDEX = 3;\n\n    //Misc Constants\n\n    /// @notice The number of slots each epoch in the beacon chain\n    uint64 internal constant SLOTS_PER_EPOCH = 32;\n\n    /// @notice The number of seconds in a slot in the beacon chain\n    uint64 internal constant SECONDS_PER_SLOT = 12;\n\n    /// @notice Number of seconds per epoch: 384 == 32 slots/epoch * 12 seconds/slot\n    uint64 internal constant SECONDS_PER_EPOCH = SLOTS_PER_EPOCH * SECONDS_PER_SLOT;\n\n    bytes8 internal constant UINT64_MASK = 0xffffffffffffffff;\n\n    /// @notice This struct contains the merkle proofs and leaves needed to verify a partial/full withdrawal\n    struct WithdrawalProof {\n        bytes withdrawalProof;\n        bytes slotProof;\n        bytes executionPayloadProof;\n        bytes timestampProof;\n        bytes historicalSummaryBlockRootProof;\n        uint64 blockRootIndex;\n        uint64 historicalSummaryIndex;\n        uint64 withdrawalIndex;\n        bytes32 blockRoot;\n        bytes32 slotRoot;\n        bytes32 timestampRoot;\n        bytes32 executionPayloadRoot;\n    }\n\n    /// @notice This struct contains the root and proof for verifying the state root against the oracle block root\n    struct StateRootProof {\n        bytes32 beaconStateRoot;\n        bytes proof;\n    }\n\n    /**\n     * @notice This function verifies merkle proofs of the fields of a certain validator against a beacon chain state\n     * root\n     * @param validatorIndex the index of the proven validator\n     * @param beaconStateRoot is the beacon chain state root to be proven against.\n     * @param validatorFieldsProof is the data used in proving the validator's fields\n     * @param validatorFields the claimed fields of the validator\n     */\n    function verifyValidatorFields(\n        bytes32 beaconStateRoot,\n        bytes32[] calldata validatorFields,\n        bytes calldata validatorFieldsProof,\n        uint40 validatorIndex\n    )\n        internal\n        view\n    {\n        require(\n            validatorFields.length == 2 ** VALIDATOR_FIELD_TREE_HEIGHT,\n            \"BeaconChainProofs.verifyValidatorFields: Validator fields has incorrect length\"\n        );\n\n        /**\n         * Note: the length of the validator merkle proof is BeaconChainProofs.VALIDATOR_TREE_HEIGHT + 1.\n         * There is an additional layer added by hashing the root with the length of the validator list\n         */\n        require(\n            validatorFieldsProof.length == 32 * ((VALIDATOR_TREE_HEIGHT + 1) + BEACON_STATE_FIELD_TREE_HEIGHT),\n            \"BeaconChainProofs.verifyValidatorFields: Proof has incorrect length\"\n        );\n        uint256 index = (VALIDATOR_TREE_ROOT_INDEX << (VALIDATOR_TREE_HEIGHT + 1)) | uint256(validatorIndex);\n        // merkleize the validatorFields to get the leaf to prove\n        bytes32 validatorRoot = Merkle.merkleizeSha256(validatorFields);\n\n        // verify the proof of the validatorRoot against the beaconStateRoot\n        require(\n            Merkle.verifyInclusionSha256({\n                proof: validatorFieldsProof,\n                root: beaconStateRoot,\n                leaf: validatorRoot,\n                index: index\n            }),\n            \"BeaconChainProofs.verifyValidatorFields: Invalid merkle proof\"\n        );\n    }\n\n    /**\n     * @notice This function verifies the latestBlockHeader against the state root. the latestBlockHeader is\n     * a tracked in the beacon state.\n     * @param beaconStateRoot is the beacon chain state root to be proven against.\n     * @param stateRootProof is the provided merkle proof\n     * @param latestBlockRoot is hashtree root of the latest block header in the beacon state\n     */\n    function verifyStateRootAgainstLatestBlockRoot(\n        bytes32 latestBlockRoot,\n        bytes32 beaconStateRoot,\n        bytes calldata stateRootProof\n    )\n        internal\n        view\n    {\n        require(\n            stateRootProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT),\n            \"BeaconChainProofs.verifyStateRootAgainstLatestBlockRoot: Proof has incorrect length\"\n        );\n        //Next we verify the slot against the blockRoot\n        require(\n            Merkle.verifyInclusionSha256({\n                proof: stateRootProof,\n                root: latestBlockRoot,\n                leaf: beaconStateRoot,\n                index: STATE_ROOT_INDEX\n            }),\n            \"BeaconChainProofs.verifyStateRootAgainstLatestBlockRoot: Invalid latest block header root merkle proof\"\n        );\n    }\n\n    /**\n     * @notice This function verifies the slot and the withdrawal fields for a given withdrawal\n     * @param withdrawalProof is the provided set of merkle proofs\n     * @param withdrawalFields is the serialized withdrawal container to be proven\n     */\n    function verifyWithdrawal(\n        bytes32 beaconStateRoot,\n        bytes32[] calldata withdrawalFields,\n        WithdrawalProof calldata withdrawalProof,\n        uint64 denebForkTimestamp\n    )\n        internal\n        view\n    {\n        require(\n            withdrawalFields.length == 2 ** WITHDRAWAL_FIELD_TREE_HEIGHT,\n            \"BeaconChainProofs.verifyWithdrawal: withdrawalFields has incorrect length\"\n        );\n\n        require(\n            withdrawalProof.blockRootIndex < 2 ** BLOCK_ROOTS_TREE_HEIGHT,\n            \"BeaconChainProofs.verifyWithdrawal: blockRootIndex is too large\"\n        );\n        require(\n            withdrawalProof.withdrawalIndex < 2 ** WITHDRAWALS_TREE_HEIGHT,\n            \"BeaconChainProofs.verifyWithdrawal: withdrawalIndex is too large\"\n        );\n\n        require(\n            withdrawalProof.historicalSummaryIndex < 2 ** HISTORICAL_SUMMARIES_TREE_HEIGHT,\n            \"BeaconChainProofs.verifyWithdrawal: historicalSummaryIndex is too large\"\n        );\n\n        //Note: post deneb hard fork, the number of exection payload header fields increased from 15->17, adding an\n        // extra level to the tree height\n        uint256 executionPayloadHeaderFieldTreeHeight = (getWithdrawalTimestamp(withdrawalProof) < denebForkTimestamp)\n            ? EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT_CAPELLA\n            : EXECUTION_PAYLOAD_HEADER_FIELD_TREE_HEIGHT_DENEB;\n        require(\n            withdrawalProof.withdrawalProof.length\n                == 32 * (executionPayloadHeaderFieldTreeHeight + WITHDRAWALS_TREE_HEIGHT + 1),\n            \"BeaconChainProofs.verifyWithdrawal: withdrawalProof has incorrect length\"\n        );\n        require(\n            withdrawalProof.executionPayloadProof.length\n                == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT + BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT),\n            \"BeaconChainProofs.verifyWithdrawal: executionPayloadProof has incorrect length\"\n        );\n        require(\n            withdrawalProof.slotProof.length == 32 * (BEACON_BLOCK_HEADER_FIELD_TREE_HEIGHT),\n            \"BeaconChainProofs.verifyWithdrawal: slotProof has incorrect length\"\n        );\n        require(\n            withdrawalProof.timestampProof.length == 32 * (executionPayloadHeaderFieldTreeHeight),\n            \"BeaconChainProofs.verifyWithdrawal: timestampProof has incorrect length\"\n        );\n\n        require(\n            withdrawalProof.historicalSummaryBlockRootProof.length\n                == 32\n                    * (BEACON_STATE_FIELD_TREE_HEIGHT + (HISTORICAL_SUMMARIES_TREE_HEIGHT + 1) + 1 + (BLOCK_ROOTS_TREE_HEIGHT)),\n            \"BeaconChainProofs.verifyWithdrawal: historicalSummaryBlockRootProof has incorrect length\"\n        );\n        /**\n         * Note: Here, the \"1\" in \"1 + (BLOCK_ROOTS_TREE_HEIGHT)\" signifies that extra step of choosing the\n         * \"block_root_summary\" within the individual\n         * \"historical_summary\". Everywhere else it signifies merkelize_with_mixin, where the length of an array is\n         * hashed with the root of the array,\n         * but not here.\n         */\n        uint256 historicalBlockHeaderIndex = (\n            HISTORICAL_SUMMARIES_INDEX << ((HISTORICAL_SUMMARIES_TREE_HEIGHT + 1) + 1 + (BLOCK_ROOTS_TREE_HEIGHT))\n        ) | (uint256(withdrawalProof.historicalSummaryIndex) << (1 + (BLOCK_ROOTS_TREE_HEIGHT)))\n            | (BLOCK_SUMMARY_ROOT_INDEX << (BLOCK_ROOTS_TREE_HEIGHT)) | uint256(withdrawalProof.blockRootIndex);\n\n        require(\n            Merkle.verifyInclusionSha256({\n                proof: withdrawalProof.historicalSummaryBlockRootProof,\n                root: beaconStateRoot,\n                leaf: withdrawalProof.blockRoot,\n                index: historicalBlockHeaderIndex\n            }),\n            \"BeaconChainProofs.verifyWithdrawal: Invalid historicalsummary merkle proof\"\n        );\n\n        //Next we verify the slot against the blockRoot\n        require(\n            Merkle.verifyInclusionSha256({\n                proof: withdrawalProof.slotProof,\n                root: withdrawalProof.blockRoot,\n                leaf: withdrawalProof.slotRoot,\n                index: SLOT_INDEX\n            }),\n            \"BeaconChainProofs.verifyWithdrawal: Invalid slot merkle proof\"\n        );\n\n        {\n            // Next we verify the executionPayloadRoot against the blockRoot\n            uint256 executionPayloadIndex =\n                (BODY_ROOT_INDEX << (BEACON_BLOCK_BODY_FIELD_TREE_HEIGHT)) | EXECUTION_PAYLOAD_INDEX;\n            require(\n                Merkle.verifyInclusionSha256({\n                    proof: withdrawalProof.executionPayloadProof,\n                    root: withdrawalProof.blockRoot,\n                    leaf: withdrawalProof.executionPayloadRoot,\n                    index: executionPayloadIndex\n                }),\n                \"BeaconChainProofs.verifyWithdrawal: Invalid executionPayload merkle proof\"\n            );\n        }\n\n        // Next we verify the timestampRoot against the executionPayload root\n        require(\n            Merkle.verifyInclusionSha256({\n                proof: withdrawalProof.timestampProof,\n                root: withdrawalProof.executionPayloadRoot,\n                leaf: withdrawalProof.timestampRoot,\n                index: TIMESTAMP_INDEX\n            }),\n            \"BeaconChainProofs.verifyWithdrawal: Invalid timestamp merkle proof\"\n        );\n\n        {\n            /**\n             * Next we verify the withdrawal fields against the executionPayloadRoot:\n             * First we compute the withdrawal_index, then we merkleize the\n             * withdrawalFields container to calculate the withdrawalRoot.\n             *\n             * Note: Merkleization of the withdrawals root tree uses MerkleizeWithMixin, i.e., the length of the array\n             * is hashed with the root of\n             * the array.  Thus we shift the WITHDRAWALS_INDEX over by WITHDRAWALS_TREE_HEIGHT + 1 and not just\n             * WITHDRAWALS_TREE_HEIGHT.\n             */\n            uint256 withdrawalIndex =\n                (WITHDRAWALS_INDEX << (WITHDRAWALS_TREE_HEIGHT + 1)) | uint256(withdrawalProof.withdrawalIndex);\n            bytes32 withdrawalRoot = Merkle.merkleizeSha256(withdrawalFields);\n            require(\n                Merkle.verifyInclusionSha256({\n                    proof: withdrawalProof.withdrawalProof,\n                    root: withdrawalProof.executionPayloadRoot,\n                    leaf: withdrawalRoot,\n                    index: withdrawalIndex\n                }),\n                \"BeaconChainProofs.verifyWithdrawal: Invalid withdrawal merkle proof\"\n            );\n        }\n    }\n\n    /**\n     * @notice This function replicates the ssz hashing of a validator's pubkey, outlined below:\n     *  hh := ssz.NewHasher()\n     *  hh.PutBytes(validatorPubkey[:])\n     *  validatorPubkeyHash := hh.Hash()\n     *  hh.Reset()\n     */\n    function hashValidatorBLSPubkey(bytes memory validatorPubkey) internal pure returns (bytes32 pubkeyHash) {\n        require(validatorPubkey.length == 48, \"Input should be 48 bytes in length\");\n        return sha256(abi.encodePacked(validatorPubkey, bytes16(0)));\n    }\n\n    /**\n     * @dev Retrieve the withdrawal timestamp\n     */\n    function getWithdrawalTimestamp(WithdrawalProof memory withdrawalProof) internal pure returns (uint64) {\n        return Endian.fromLittleEndianUint64(withdrawalProof.timestampRoot);\n    }\n\n    /**\n     * @dev Converts the withdrawal's slot to an epoch\n     */\n    function getWithdrawalEpoch(WithdrawalProof memory withdrawalProof) internal pure returns (uint64) {\n        return Endian.fromLittleEndianUint64(withdrawalProof.slotRoot) / SLOTS_PER_EPOCH;\n    }\n\n    /**\n     * Indices for validator fields (refer to consensus specs):\n     * 0: pubkey\n     * 1: withdrawal credentials\n     * 2: effective balance\n     * 3: slashed?\n     * 4: activation elligibility epoch\n     * 5: activation epoch\n     * 6: exit epoch\n     * 7: withdrawable epoch\n     */\n\n    /**\n     * @dev Retrieves a validator's pubkey hash\n     */\n    function getPubkeyHash(bytes32[] memory validatorFields) internal pure returns (bytes32) {\n        return validatorFields[VALIDATOR_PUBKEY_INDEX];\n    }\n\n    function getWithdrawalCredentials(bytes32[] memory validatorFields) internal pure returns (bytes32) {\n        return validatorFields[VALIDATOR_WITHDRAWAL_CREDENTIALS_INDEX];\n    }\n\n    /**\n     * @dev Retrieves a validator's effective balance (in gwei)\n     */\n    function getEffectiveBalanceGwei(bytes32[] memory validatorFields) internal pure returns (uint64) {\n        return Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_BALANCE_INDEX]);\n    }\n\n    /**\n     * @dev Retrieves a validator's withdrawable epoch\n     */\n    function getWithdrawableEpoch(bytes32[] memory validatorFields) internal pure returns (uint64) {\n        return Endian.fromLittleEndianUint64(validatorFields[VALIDATOR_WITHDRAWABLE_EPOCH_INDEX]);\n    }\n\n    /**\n     * Indices for withdrawal fields (refer to consensus specs):\n     * 0: withdrawal index\n     * 1: validator index\n     * 2: execution address\n     * 3: withdrawal amount\n     */\n\n    /**\n     * @dev Retrieves a withdrawal's validator index\n     */\n    function getValidatorIndex(bytes32[] memory withdrawalFields) internal pure returns (uint40) {\n        return uint40(Endian.fromLittleEndianUint64(withdrawalFields[WITHDRAWAL_VALIDATOR_INDEX_INDEX]));\n    }\n\n    /**\n     * @dev Retrieves a withdrawal's withdrawal amount (in gwei)\n     */\n    function getWithdrawalAmountGwei(bytes32[] memory withdrawalFields) internal pure returns (uint64) {\n        return Endian.fromLittleEndianUint64(withdrawalFields[WITHDRAWAL_VALIDATOR_AMOUNT_INDEX]);\n    }\n}\n"
      },
      "contracts/external/eigenlayer/interfaces/IEigenPod.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { BeaconChainProofs } from \"../libraries/BeaconChainProofs.sol\";\n\ninterface IBeaconDeposit {\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\ninterface IEigenPod {\n    enum VALIDATOR_STATUS {\n        INACTIVE, // doesnt exist\n        ACTIVE, // staked on ethpos and withdrawal credentials are pointed to the EigenPod\n        WITHDRAWN // withdrawn from the Beacon Chain\n\n    }\n\n    struct ValidatorInfo {\n        // index of the validator in the beacon chain\n        uint64 validatorIndex;\n        // amount of beacon chain ETH restaked on EigenLayer in gwei\n        uint64 restakedBalanceGwei;\n        //timestamp of the validator's most recent balance update\n        uint64 mostRecentBalanceUpdateTimestamp;\n        // status of the validator\n        VALIDATOR_STATUS status;\n    }\n    /// @notice This is the beacon chain deposit contract\n\n    function ethPOS() external view returns (IBeaconDeposit);\n\n    /// @return delayedWithdrawalRouter address of eigenlayer delayedWithdrawalRouter,\n    /// which does book keeping of delayed withdrawls\n    function delayedWithdrawalRouter() external view returns (address);\n\n    /// @notice an indicator of whether or not the podOwner has ever \"fully restaked\" by successfully calling\n    /// `verifyCorrectWithdrawalCredentials`.\n    function hasRestaked() external view returns (bool);\n\n    /// @notice Called by the pod owner to withdraw the balance of the pod when `hasRestaked` is set to false\n    function withdrawBeforeRestaking() external;\n\n    /**\n     * @notice Called by the pod owner to activate restaking by withdrawing\n     * all existing ETH from the pod and preventing further withdrawals via\n     * \"withdrawBeforeRestaking()\"\n     */\n    function activateRestaking() external;\n\n    /**\n     * @notice This function verifies that the withdrawal credentials of validator(s) owned by the podOwner are pointed\n     * to\n     * this contract. It also verifies the effective balance  of the validator.  It verifies the provided proof of the\n     * ETH validator against the beacon chain state\n     * root, marks the validator as 'active' in EigenLayer, and credits the restaked ETH in Eigenlayer.\n     * @param oracleTimestamp is the Beacon Chain timestamp whose state root the `proof` will be proven against.\n     * @param validatorIndices is the list of indices of the validators being proven, refer to consensus specs\n     * @param withdrawalCredentialProofs is an array of proofs, where each proof proves each ETH validator's balance and\n     * withdrawal credentials\n     * against a beacon chain state root\n     * @param validatorFields are the fields of the \"Validator Container\", refer to consensus specs\n     * for details: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator\n     */\n    function verifyWithdrawalCredentials(\n        uint64 oracleTimestamp,\n        BeaconChainProofs.StateRootProof calldata stateRootProof,\n        uint40[] calldata validatorIndices,\n        bytes[] calldata withdrawalCredentialProofs,\n        bytes32[][] calldata validatorFields\n    )\n        external;\n\n    /**\n     * @notice This function records an update (either increase or decrease) in the pod's balance in the\n     * StrategyManager.\n     *            It also verifies a merkle proof of the validator's current beacon chain balance.\n     * @param oracleTimestamp The oracleTimestamp whose state root the `proof` will be proven against.\n     *        Must be within `VERIFY_BALANCE_UPDATE_WINDOW_SECONDS` of the current block.\n     * @param validatorIndices is the list of indices of the validators being proven, refer to consensus specs\n     * @param validatorFieldsProofs proofs against the `beaconStateRoot` for each validator in `validatorFields`\n     * @param validatorFields are the fields of the \"Validator Container\", refer to consensus specs\n     * @dev For more details on the Beacon Chain spec, see:\n     * https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#validator\n     */\n    function verifyBalanceUpdates(\n        uint64 oracleTimestamp,\n        uint40[] calldata validatorIndices,\n        BeaconChainProofs.StateRootProof calldata stateRootProof,\n        bytes[] calldata validatorFieldsProofs,\n        bytes32[][] calldata validatorFields\n    )\n        external;\n\n    /**\n     * @notice This function records full and partial withdrawals on behalf of one of the Ethereum validators for this\n     * EigenPod\n     * @param oracleTimestamp is the timestamp of the oracle slot that the withdrawal is being proven against\n     * @param withdrawalProofs is the information needed to check the veracity of the block numbers and withdrawals\n     * being proven\n     * @param validatorFieldsProofs is the proof of the validator's fields' in the validator tree\n     * @param withdrawalFields are the fields of the withdrawals being proven\n     * @param validatorFields are the fields of the validators being proven\n     */\n    function verifyAndProcessWithdrawals(\n        uint64 oracleTimestamp,\n        BeaconChainProofs.StateRootProof calldata stateRootProof,\n        BeaconChainProofs.WithdrawalProof[] calldata withdrawalProofs,\n        bytes[] calldata validatorFieldsProofs,\n        bytes32[][] calldata validatorFields,\n        bytes32[][] calldata withdrawalFields\n    )\n        external;\n\n    function mostRecentWithdrawalTimestamp() external view returns (uint64);\n\n    function withdrawableRestakedExecutionLayerGwei() external view returns (uint64);\n\n    function validatorPubkeyHashToInfo(bytes32) external view returns (ValidatorInfo memory);\n}\n"
      },
      "contracts/external/eigenlayer/interfaces/IStrategy.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity >=0.5.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title Minimal interface for an `Strategy` contract.\n * @author Layr Labs, Inc.\n * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service\n * @notice Custom `Strategy` implementations may expand extensively on this interface.\n */\ninterface IStrategy {\n    // packed struct for queued withdrawals; helps deal with stack-too-deep errors\n    struct WithdrawerAndNonce {\n        address withdrawer;\n        uint96 nonce;\n    }\n\n    struct QueuedWithdrawal {\n        IStrategy[] strategies;\n        uint256[] shares;\n        address depositor;\n        WithdrawerAndNonce withdrawerAndNonce;\n        uint32 withdrawalStartBlock;\n        address delegatedAddress;\n    }\n\n    /**\n     * @notice Used to deposit tokens into this Strategy\n     * @param token is the ERC20 token being deposited\n     * @param amount is the amount of token being deposited\n     * @dev This function is only callable by the strategyManager contract. It is invoked inside of the\n     * strategyManager's\n     * `depositIntoStrategy` function, and individual share balances are recorded in the strategyManager as well.\n     * @return newShares is the number of new shares issued at the current exchange ratio.\n     */\n    function deposit(IERC20 token, uint256 amount) external returns (uint256);\n\n    /**\n     * @notice Used to withdraw tokens from this Strategy, to the `depositor`'s address\n     * @param depositor is the address to receive the withdrawn funds\n     * @param token is the ERC20 token being transferred out\n     * @param amountShares is the amount of shares being withdrawn\n     * @dev This function is only callable by the strategyManager contract. It is invoked inside of the\n     * strategyManager's\n     * other functions, and individual share balances are recorded in the strategyManager as well.\n     */\n    function withdraw(address depositor, IERC20 token, uint256 amountShares) external;\n\n    /**\n     * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy.\n     * @notice In contrast to `sharesToUnderlyingView`, this function **may** make state modifications\n     * @param amountShares is the amount of shares to calculate its conversion into the underlying token\n     * @return The amount of underlying tokens corresponding to the input `amountShares`\n     * @dev Implementation for these functions in particular may vary significantly for different strategies\n     */\n    function sharesToUnderlying(uint256 amountShares) external returns (uint256);\n\n    /**\n     * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy.\n     * @notice In contrast to `underlyingToSharesView`, this function **may** make state modifications\n     * @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares\n     * @return The amount of underlying tokens corresponding to the input `amountShares`\n     * @dev Implementation for these functions in particular may vary significantly for different strategies\n     */\n    function underlyingToShares(uint256 amountUnderlying) external returns (uint256);\n\n    /**\n     * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in\n     * this strategy. In contrast to `userUnderlyingView`, this function **may** make state modifications\n     */\n    function userUnderlying(address user) external returns (uint256);\n\n    /**\n     * @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy.\n     * @notice In contrast to `sharesToUnderlying`, this function guarantees no state modifications\n     * @param amountShares is the amount of shares to calculate its conversion into the underlying token\n     * @return The amount of shares corresponding to the input `amountUnderlying`\n     * @dev Implementation for these functions in particular may vary significantly for different strategies\n     */\n    function sharesToUnderlyingView(uint256 amountShares) external view returns (uint256);\n\n    /**\n     * @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy.\n     * @notice In contrast to `underlyingToShares`, this function guarantees no state modifications\n     * @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares\n     * @return The amount of shares corresponding to the input `amountUnderlying`\n     * @dev Implementation for these functions in particular may vary significantly for different strategies\n     */\n    function underlyingToSharesView(uint256 amountUnderlying) external view returns (uint256);\n\n    /**\n     * @notice convenience function for fetching the current underlying value of all of the `user`'s shares in\n     * this strategy. In contrast to `userUnderlying`, this function guarantees no state modifications\n     */\n    function userUnderlyingView(address user) external view returns (uint256);\n\n    /// @notice The underlying token for shares in this Strategy\n    function underlyingToken() external view returns (IERC20);\n\n    /// @notice The total number of extant shares in this Strategy\n    function totalShares() external view returns (uint256);\n\n    /// @notice Returns either a brief string explaining the strategy's goal & purpose, or a link to metadata that\n    /// explains in more detail.\n    function explanation() external view returns (string memory);\n}\n"
      },
      "contracts/external/eigenlayer/interfaces/IEigenStrategyManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"./IStrategy.sol\";\nimport { IEigenDelegationManager } from \"./IEigenDelegationManager.sol\";\nimport \"./ISlasher.sol\";\n\ninterface IEigenStrategyManager {\n    function slasher() external returns (ISlasher);\n\n    function withdrawalRootPending(bytes32 withdrawalRoot) external view returns (bool);\n\n    function withdrawalDelayBlocks() external view returns (uint256);\n\n    /**\n     * @notice Deposits `amount` of `token` into the specified `strategy`, with the resultant shares credited to\n     * `msg.sender`\n     * @param strategy is the specified strategy where deposit is to be made,\n     * @param token is the denomination in which the deposit is to be made,\n     * @param amount is the amount of token to be deposited in the strategy by the depositor\n     * @return shares The amount of new shares in the `strategy` created as part of the action.\n     * @dev The `msg.sender` must have previously approved this contract to transfer at least `amount` of `token` on\n     * their behalf.\n     * @dev Cannot be called by an address that is 'frozen' (this function will revert if the `msg.sender` is frozen).\n     *\n     * WARNING: Depositing tokens that allow reentrancy (eg. ERC-777) into a strategy is not recommended.  This can lead\n     * to attack vectors\n     *          where the token balance and corresponding strategy shares are not in sync upon reentrancy.\n     */\n    function depositIntoStrategy(IStrategy strategy, IERC20 token, uint256 amount) external returns (uint256 shares);\n\n    /**\n     * @notice Get all details on the depositor's deposits and corresponding shares\n     * @return (depositor's strategies, shares in these strategies)\n     */\n    function getDeposits(address depositor) external view returns (IStrategy[] memory, uint256[] memory);\n\n    function stakerStrategyShares(address staker, IStrategy strategy) external view returns (uint256);\n\n    function stakerStrategyList(address staker, uint256 index) external view returns (IStrategy);\n\n    /// @notice Simple getter function that returns `stakerStrategyList[staker].length`.\n    function stakerStrategyListLength(address staker) external view returns (uint256);\n\n    function numWithdrawalsQueued(address staker) external view returns (uint256);\n\n    /// @notice Returns the keccak256 hash of `queuedWithdrawal`.\n    function calculateWithdrawalRoot(IStrategy.QueuedWithdrawal memory queuedWithdrawal)\n        external\n        pure\n        returns (bytes32);\n\n    /// @notice Returns the single, central Delegation contract of EigenLayer\n    function delegation() external view returns (IEigenDelegationManager);\n\n    /**\n     * @notice Called by a staker to queue a withdrawal of the given amount of `shares` from each of the respective\n     * given `strategies`.\n     * @dev Stakers will complete their withdrawal by calling the 'completeQueuedWithdrawal' function.\n     * User shares are decreased in this function, but the total number of shares in each strategy remains the same.\n     * The total number of shares is decremented in the 'completeQueuedWithdrawal' function instead, which is where\n     * the funds are actually sent to the user through use of the strategies' 'withdrawal' function. This ensures\n     * that the value per share reported by each strategy will remain consistent, and that the shares will continue\n     * to accrue gains during the enforced withdrawal waiting period.\n     * @param strategyIndexes is a list of the indices in `stakerStrategyList[msg.sender]` that correspond to the\n     * strategies\n     * for which `msg.sender` is withdrawing 100% of their shares\n     * @param strategies The Strategies to withdraw from\n     * @param shares The amount of shares to withdraw from each of the respective Strategies in the `strategies` array\n     * @param withdrawer The address that can complete the withdrawal and will receive any withdrawn funds or shares\n     * upon completing the withdrawal\n     * @param undelegateIfPossible If this param is marked as 'true' *and the withdrawal will result in `msg.sender`\n     * having no shares in any Strategy,*\n     * then this function will also make an internal call to `undelegate(msg.sender)` to undelegate the `msg.sender`.\n     * @return The 'withdrawalRoot' of the newly created Queued Withdrawal\n     * @dev Strategies are removed from `stakerStrategyList` by swapping the last entry with the entry to be removed,\n     * then\n     * popping off the last entry in `stakerStrategyList`. The simplest way to calculate the correct `strategyIndexes`\n     * to input\n     * is to order the strategies *for which `msg.sender` is withdrawing 100% of their shares* from highest index in\n     * `stakerStrategyList` to lowest index\n     * @dev Note that if the withdrawal includes shares in the enshrined 'beaconChainETH' strategy, then it must *only*\n     * include shares in this strategy, and\n     * `withdrawer` must match the caller's address. The first condition is because slashing of queued withdrawals\n     * cannot be guaranteed\n     * for Beacon Chain ETH (since we cannot trigger a withdrawal from the beacon chain through a smart contract) and\n     * the second condition is because shares in\n     * the enshrined 'beaconChainETH' strategy technically represent non-fungible positions (deposits to the Beacon\n     * Chain, each pointed at a specific EigenPod).\n     */\n    function queueWithdrawal(\n        uint256[] calldata strategyIndexes,\n        IStrategy[] calldata strategies,\n        uint256[] calldata shares,\n        address withdrawer,\n        bool undelegateIfPossible\n    )\n        external\n        returns (bytes32);\n\n    /**\n     * @notice Used to complete the specified `queuedWithdrawal`. The function caller must match\n     * `queuedWithdrawal.withdrawer`\n     * @param queuedWithdrawal The QueuedWithdrawal to complete.\n     * @param tokens Array in which the i-th entry specifies the `token` input to the 'withdraw' function of the i-th\n     * Strategy in the `strategies` array\n     * of the `queuedWithdrawal`. This input can be provided with zero length if `receiveAsTokens` is set to 'false'\n     * (since in that case, this input will be unused)\n     * @param middlewareTimesIndex is the index in the operator that the staker who triggered the withdrawal was\n     * delegated to's middleware times array\n     * @param receiveAsTokens If true, the shares specified in the queued withdrawal will be withdrawn from the\n     * specified strategies themselves\n     * and sent to the caller, through calls to `queuedWithdrawal.strategies[i].withdraw`. If false, then the shares in\n     * the specified strategies\n     * will simply be transferred to the caller directly.\n     * @dev middlewareTimesIndex should be calculated off chain before calling this function by finding the first index\n     * that satisfies `slasher.canWithdraw`\n     */\n    function completeQueuedWithdrawal(\n        IStrategy.QueuedWithdrawal calldata queuedWithdrawal,\n        IERC20[] calldata tokens,\n        uint256 middlewareTimesIndex,\n        bool receiveAsTokens\n    )\n        external;\n}\n"
      },
      "contracts/external/eigenlayer/interfaces/IEigenPodManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IEigenPod } from \"./IEigenPod.sol\";\n\ninterface IEigenPodManager {\n    /// @notice Returns the address of the `podOwner`'s EigenPod (whether it is deployed yet or not).\n    function getPod(address podOwner) external view returns (IEigenPod);\n    /**\n     * @notice Creates an EigenPod for the sender.\n     * @dev Function will revert if the `msg.sender` already has an EigenPod.\n     */\n    function createPod() external;\n\n    /// @notice Returns the address of the `podOwner`'s EigenPod if it has been deployed.\n    function ownerToPod(address podOwner) external view returns (IEigenPod);\n\n    /**\n     * @notice Mapping from Pod owner owner to the number of shares they have in the virtual beacon chain ETH strategy.\n     * @dev The share amount can become negative. This is necessary to accommodate the fact that a pod owner's virtual\n     * beacon chain ETH shares can\n     * decrease between the pod owner queuing and completing a withdrawal.\n     * When the pod owner's shares would otherwise increase, this \"deficit\" is decreased first _instead_.\n     * Likewise, when a withdrawal is completed, this \"deficit\" is decreased and the withdrawal amount is decreased; We\n     * can think of this\n     * as the withdrawal \"paying off the deficit\".\n     */\n    function podOwnerShares(address podOwner) external view returns (int256);\n\n    /**\n     * @notice Stakes for a new beacon chain validator on the sender's EigenPod.\n     * Also creates an EigenPod for the sender if they don't have one already.\n     * @param pubkey The 48 bytes public key of the beacon chain validator.\n     * @param signature The validator's signature of the deposit data.\n     * @param depositDataRoot The root/hash of the deposit data for the validator's deposit.\n     */\n    function stake(bytes calldata pubkey, bytes calldata signature, bytes32 depositDataRoot) external payable;\n}\n"
      },
      "contracts/external/eigenlayer/interfaces/IEigenDelegationManager.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport \"./IStrategy.sol\";\n\n/**\n * @title DelegationManager\n * @author Layr Labs, Inc.\n * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service\n * @notice  This is the contract for delegation in EigenLayer. The main functionalities of this contract are\n * - enabling anyone to register as an operator in EigenLayer\n * - allowing operators to specify parameters related to stakers who delegate to them\n * - enabling any staker to delegate its stake to the operator of its choice (a given staker can only delegate to a\n * single operator at a time)\n * - enabling a staker to undelegate its assets from the operator it is delegated to (performed as part of the\n * withdrawal process, initiated through the StrategyManager)\n */\ninterface IEigenDelegationManager {\n    // @notice Struct used for storing information about a single operator who has registered with EigenLayer\n    struct OperatorDetails {\n        // @notice address to receive the rewards that the operator earns via serving applications built on EigenLayer.\n        address earningsReceiver;\n        /**\n         * @notice Address to verify signatures when a staker wishes to delegate to the operator, as well as controlling\n         * \"forced undelegations\".\n         * @dev Signature verification follows these rules:\n         * 1) If this address is left as address(0), then any staker will be free to delegate to the operator, i.e. no\n         * signature verification will be performed.\n         * 2) If this address is an EOA (i.e. it has no code), then we follow standard ECDSA signature verification for\n         * delegations to the operator.\n         * 3) If this address is a contract (i.e. it has code) then we forward a call to the contract and verify that it\n         * returns the correct EIP-1271 \"magic value\".\n         */\n        address delegationApprover;\n        /**\n         * @notice A minimum delay -- measured in blocks -- enforced between:\n         * 1) the operator signalling their intent to register for a service, via calling `Slasher.optIntoSlashing`\n         * and\n         * 2) the operator completing registration for the service, via the service ultimately calling\n         * `Slasher.recordFirstStakeUpdate`\n         * @dev note that for a specific operator, this value *cannot decrease*, i.e. if the operator wishes to modify\n         * their OperatorDetails,\n         * then they are only allowed to either increase this value or keep it the same.\n         */\n        uint32 stakerOptOutWindowBlocks;\n    }\n\n    /**\n     * @notice Abstract struct used in calculating an EIP712 signature for a staker to approve that they (the staker\n     * themselves) delegate to a specific operator.\n     * @dev Used in computing the `STAKER_DELEGATION_TYPEHASH` and as a reference in the computation of the\n     * stakerDigestHash in the `delegateToBySignature` function.\n     */\n    struct StakerDelegation {\n        // the staker who is delegating\n        address staker;\n        // the operator being delegated to\n        address operator;\n        // the staker's nonce\n        uint256 nonce;\n        // the expiration timestamp (UTC) of the signature\n        uint256 expiry;\n    }\n\n    /**\n     * @notice Abstract struct used in calculating an EIP712 signature for an operator's delegationApprover to approve\n     * that a specific staker delegate to the operator.\n     * @dev Used in computing the `DELEGATION_APPROVAL_TYPEHASH` and as a reference in the computation of the\n     * approverDigestHash in the `_delegate` function.\n     */\n    struct DelegationApproval {\n        // the staker who is delegating\n        address staker;\n        // the operator being delegated to\n        address operator;\n        // the operator's provided salt\n        bytes32 salt;\n        // the expiration timestamp (UTC) of the signature\n        uint256 expiry;\n    }\n\n    /**\n     * Struct type used to specify an existing queued withdrawal. Rather than storing the entire struct, only a hash is\n     * stored.\n     * In functions that operate on existing queued withdrawals -- e.g. completeQueuedWithdrawal`, the data is\n     * resubmitted and the hash of the submitted\n     * data is computed by `calculateWithdrawalRoot` and checked against the stored hash in order to confirm the\n     * integrity of the submitted data.\n     */\n    struct Withdrawal {\n        // The address that originated the Withdrawal\n        address staker;\n        // The address that the staker was delegated to at the time that the Withdrawal was created\n        address delegatedTo;\n        // The address that can complete the Withdrawal + will receive funds when completing the withdrawal\n        address withdrawer;\n        // Nonce used to guarantee that otherwise identical withdrawals have unique hashes\n        uint256 nonce;\n        // Block number when the Withdrawal was created\n        uint32 startBlock;\n        // Array of strategies that the Withdrawal contains\n        IStrategy[] strategies;\n        // Array containing the amount of shares in each Strategy in the `strategies` array\n        uint256[] shares;\n    }\n\n    struct QueuedWithdrawalParams {\n        // Array of strategies that the QueuedWithdrawal contains\n        IStrategy[] strategies;\n        // Array containing the amount of shares in each Strategy in the `strategies` array\n        uint256[] shares;\n        // The address of the withdrawer\n        address withdrawer;\n    }\n\n    // @notice Emitted when a new operator registers in EigenLayer and provides their OperatorDetails.\n    event OperatorRegistered(address indexed operator, OperatorDetails operatorDetails);\n\n    /// @notice Emitted when an operator updates their OperatorDetails to @param newOperatorDetails\n    event OperatorDetailsModified(address indexed operator, OperatorDetails newOperatorDetails);\n\n    /**\n     * @notice Emitted when @param operator indicates that they are updating their MetadataURI string\n     * @dev Note that these strings are *never stored in storage* and are instead purely emitted in events for off-chain\n     * indexing\n     */\n    event OperatorMetadataURIUpdated(address indexed operator, string metadataURI);\n\n    /// @notice Emitted whenever an operator's shares are increased for a given strategy. Note that shares is the delta\n    /// in the operator's shares.\n    event OperatorSharesIncreased(address indexed operator, address staker, IStrategy strategy, uint256 shares);\n\n    /// @notice Emitted whenever an operator's shares are decreased for a given strategy. Note that shares is the delta\n    /// in the operator's shares.\n    event OperatorSharesDecreased(address indexed operator, address staker, IStrategy strategy, uint256 shares);\n\n    /// @notice Emitted when @param staker delegates to @param operator.\n    event StakerDelegated(address indexed staker, address indexed operator);\n\n    /// @notice Emitted when @param staker undelegates from @param operator.\n    event StakerUndelegated(address indexed staker, address indexed operator);\n\n    /// @notice Emitted when @param staker is undelegated via a call not originating from the staker themself\n    event StakerForceUndelegated(address indexed staker, address indexed operator);\n\n    /**\n     * @notice Emitted when a new withdrawal is queued.\n     * @param withdrawalRoot Is the hash of the `withdrawal`.\n     * @param withdrawal Is the withdrawal itself.\n     */\n    event WithdrawalQueued(bytes32 withdrawalRoot, Withdrawal withdrawal);\n\n    /// @notice Emitted when a queued withdrawal is completed\n    event WithdrawalCompleted(bytes32 withdrawalRoot);\n\n    /// @notice Emitted when a queued withdrawal is *migrated* from the StrategyManager to the DelegationManager\n    event WithdrawalMigrated(bytes32 oldWithdrawalRoot, bytes32 newWithdrawalRoot);\n\n    /// @notice Emitted when the `minWithdrawalDelayBlocks` variable is modified from `previousValue` to `newValue`.\n    event MinWithdrawalDelayBlocksSet(uint256 previousValue, uint256 newValue);\n\n    /// @notice Emitted when the `strategyWithdrawalDelayBlocks` variable is modified from `previousValue` to\n    /// `newValue`.\n    event StrategyWithdrawalDelayBlocksSet(IStrategy strategy, uint256 previousValue, uint256 newValue);\n\n    function pendingWithdrawals(bytes32 withdrawalRoot) external view returns (bool);\n\n    /**\n     * @notice Registers the caller as an operator in EigenLayer.\n     * @param registeringOperatorDetails is the `OperatorDetails` for the operator.\n     * @param metadataURI is a URI for the operator's metadata, i.e. a link providing more details on the operator.\n     *\n     * @dev Once an operator is registered, they cannot 'deregister' as an operator, and they will forever be considered\n     * \"delegated to themself\".\n     * @dev This function will revert if the caller attempts to set their `earningsReceiver` to address(0).\n     * @dev Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event\n     */\n    function registerAsOperator(\n        OperatorDetails calldata registeringOperatorDetails,\n        string calldata metadataURI\n    )\n        external;\n\n    /**\n     * @notice Updates an operator's stored `OperatorDetails`.\n     * @param newOperatorDetails is the updated `OperatorDetails` for the operator, to replace their current\n     * OperatorDetails`.\n     *\n     * @dev The caller must have previously registered as an operator in EigenLayer.\n     * @dev This function will revert if the caller attempts to set their `earningsReceiver` to address(0).\n     */\n    function modifyOperatorDetails(OperatorDetails calldata newOperatorDetails) external;\n\n    /**\n     * @notice Called by an operator to emit an `OperatorMetadataURIUpdated` event indicating the information has\n     * updated.\n     * @param metadataURI The URI for metadata associated with an operator\n     * @dev Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event\n     */\n    function updateOperatorMetadataURI(string calldata metadataURI) external;\n\n    /**\n     * @notice Undelegates the staker from the operator who they are delegated to. Puts the staker into the\n     * \"undelegation limbo\" mode of the EigenPodManager\n     * and queues a withdrawal of all of the staker's shares in the StrategyManager (to the staker), if necessary.\n     * @param staker The account to be undelegated.\n     * @return withdrawalRoot The root of the newly queued withdrawal, if a withdrawal was queued. Otherwise just\n     * bytes32(0).\n     *\n     * @dev Reverts if the `staker` is also an operator, since operators are not allowed to undelegate from themselves.\n     * @dev Reverts if the caller is not the staker, nor the operator who the staker is delegated to, nor the operator's\n     * specified \"delegationApprover\"\n     * @dev Reverts if the `staker` is already undelegated.\n     */\n    function undelegate(address staker) external returns (bytes32[] memory withdrawalRoot);\n\n    /**\n     * Allows a staker to withdraw some shares. Withdrawn shares/strategies are immediately removed\n     * from the staker. If the staker is delegated, withdrawn shares/strategies are also removed from\n     * their operator.\n     *\n     * All withdrawn shares/strategies are placed in a queue and can be fully withdrawn after a delay.\n     */\n    function queueWithdrawals(QueuedWithdrawalParams[] calldata queuedWithdrawalParams)\n        external\n        returns (bytes32[] memory);\n\n    /**\n     * @notice Used to complete the specified `withdrawal`. The caller must match `withdrawal.withdrawer`\n     * @param withdrawal The Withdrawal to complete.\n     * @param tokens Array in which the i-th entry specifies the `token` input to the 'withdraw' function of the i-th\n     * Strategy in the `withdrawal.strategies` array.\n     * This input can be provided with zero length if `receiveAsTokens` is set to 'false' (since in that case, this\n     * input will be unused)\n     * @param middlewareTimesIndex is the index in the operator that the staker who triggered the withdrawal was\n     * delegated to's middleware times array\n     * @param receiveAsTokens If true, the shares specified in the withdrawal will be withdrawn from the specified\n     * strategies themselves\n     * and sent to the caller, through calls to `withdrawal.strategies[i].withdraw`. If false, then the shares in the\n     * specified strategies\n     * will simply be transferred to the caller directly.\n     * @dev middlewareTimesIndex should be calculated off chain before calling this function by finding the first index\n     * that satisfies `slasher.canWithdraw`\n     * @dev beaconChainETHStrategy shares are non-transferrable, so if `receiveAsTokens = false` and\n     * `withdrawal.withdrawer != withdrawal.staker`, note that\n     * any beaconChainETHStrategy shares in the `withdrawal` will be _returned to the staker_, rather than transferred\n     * to the withdrawer, unlike shares in\n     * any other strategies, which will be transferred to the withdrawer.\n     */\n    function completeQueuedWithdrawal(\n        Withdrawal calldata withdrawal,\n        IERC20[] calldata tokens,\n        uint256 middlewareTimesIndex,\n        bool receiveAsTokens\n    )\n        external;\n\n    /**\n     * @notice Array-ified version of `completeQueuedWithdrawal`.\n     * Used to complete the specified `withdrawals`. The function caller must match `withdrawals[...].withdrawer`\n     * @param withdrawals The Withdrawals to complete.\n     * @param tokens Array of tokens for each Withdrawal. See `completeQueuedWithdrawal` for the usage of a single\n     * array.\n     * @param middlewareTimesIndexes One index to reference per Withdrawal. See `completeQueuedWithdrawal` for the usage\n     * of a single index.\n     * @param receiveAsTokens Whether or not to complete each withdrawal as tokens. See `completeQueuedWithdrawal` for\n     * the usage of a single boolean.\n     * @dev See `completeQueuedWithdrawal` for relevant dev tags\n     */\n    function completeQueuedWithdrawals(\n        Withdrawal[] calldata withdrawals,\n        IERC20[][] calldata tokens,\n        uint256[] calldata middlewareTimesIndexes,\n        bool[] calldata receiveAsTokens\n    )\n        external;\n\n    /**\n     * @notice Increases a staker's delegated share balance in a strategy.\n     * @param staker The address to increase the delegated shares for their operator.\n     * @param strategy The strategy in which to increase the delegated shares.\n     * @param shares The number of shares to increase.\n     *\n     * @dev *If the staker is actively delegated*, then increases the `staker`'s delegated shares in `strategy` by\n     * `shares`. Otherwise does nothing.\n     * @dev Callable only by the StrategyManager or EigenPodManager.\n     */\n    function increaseDelegatedShares(address staker, IStrategy strategy, uint256 shares) external;\n\n    /**\n     * @notice Decreases a staker's delegated share balance in a strategy.\n     * @param staker The address to increase the delegated shares for their operator.\n     * @param strategy The strategy in which to decrease the delegated shares.\n     * @param shares The number of shares to decrease.\n     *\n     * @dev *If the staker is actively delegated*, then decreases the `staker`'s delegated shares in `strategy` by\n     * `shares`. Otherwise does nothing.\n     * @dev Callable only by the StrategyManager or EigenPodManager.\n     */\n    function decreaseDelegatedShares(address staker, IStrategy strategy, uint256 shares) external;\n\n    /**\n     * @notice returns the address of the operator that `staker` is delegated to.\n     * @notice Mapping: staker => operator whom the staker is currently delegated to.\n     * @dev Note that returning address(0) indicates that the staker is not actively delegated to any operator.\n     */\n    function delegatedTo(address staker) external view returns (address);\n\n    /**\n     * @notice Returns the OperatorDetails struct associated with an `operator`.\n     */\n    function operatorDetails(address operator) external view returns (OperatorDetails memory);\n\n    /*\n     * @notice Returns the earnings receiver address for an operator\n     */\n    function earningsReceiver(address operator) external view returns (address);\n\n    /**\n     * @notice Returns the delegationApprover account for an operator\n     */\n    function delegationApprover(address operator) external view returns (address);\n\n    /**\n     * @notice Returns the stakerOptOutWindowBlocks for an operator\n     */\n    function stakerOptOutWindowBlocks(address operator) external view returns (uint256);\n\n    /**\n     * @notice Given array of strategies, returns array of shares for the operator\n     */\n    function getOperatorShares(\n        address operator,\n        IStrategy[] memory strategies\n    )\n        external\n        view\n        returns (uint256[] memory);\n\n    /**\n     * @notice Given a list of strategies, return the minimum number of blocks that must pass to withdraw\n     * from all the inputted strategies. Return value is >= minWithdrawalDelayBlocks as this is the global min\n     * withdrawal delay.\n     * @param strategies The strategies to check withdrawal delays for\n     */\n    function getWithdrawalDelay(IStrategy[] calldata strategies) external view returns (uint256);\n\n    /**\n     * @notice returns the total number of shares in `strategy` that are delegated to `operator`.\n     * @notice Mapping: operator => strategy => total number of shares in the strategy delegated to the operator.\n     * @dev By design, the following invariant should hold for each Strategy:\n     * (operator's shares in delegation manager) = sum (shares above zero of all stakers delegated to operator)\n     * = sum (delegateable shares of all stakers delegated to the operator)\n     */\n    function operatorShares(address operator, IStrategy strategy) external view returns (uint256);\n\n    /**\n     * @notice Returns 'true' if `staker` *is* actively delegated, and 'false' otherwise.\n     */\n    function isDelegated(address staker) external view returns (bool);\n\n    /**\n     * @notice Returns true is an operator has previously registered for delegation.\n     */\n    function isOperator(address operator) external view returns (bool);\n\n    /// @notice Mapping: staker => number of signed delegation nonces (used in `delegateToBySignature`) from the staker\n    /// that the contract has already checked\n    function stakerNonce(address staker) external view returns (uint256);\n\n    /**\n     * @notice Mapping: delegationApprover => 32-byte salt => whether or not the salt has already been used by the\n     * delegationApprover.\n     * @dev Salts are used in the `delegateTo` and `delegateToBySignature` functions. Note that these functions only\n     * process the delegationApprover's\n     * signature + the provided salt if the operator being delegated to has specified a nonzero address as their\n     * `delegationApprover`.\n     */\n    function delegationApproverSaltIsSpent(address _delegationApprover, bytes32 salt) external view returns (bool);\n\n    /**\n     * @notice Minimum delay enforced by this contract for completing queued withdrawals. Measured in blocks, and\n     * adjustable by this contract's owner,\n     * up to a maximum of `MAX_WITHDRAWAL_DELAY_BLOCKS`. Minimum value is 0 (i.e. no delay enforced).\n     * Note that strategies each have a separate withdrawal delay, which can be greater than this value. So the minimum\n     * number of blocks that must pass\n     * to withdraw a strategy is MAX(minWithdrawalDelayBlocks, strategyWithdrawalDelayBlocks[strategy])\n     */\n    function minWithdrawalDelayBlocks() external view returns (uint256);\n\n    /**\n     * @notice Minimum delay enforced by this contract per Strategy for completing queued withdrawals. Measured in\n     * blocks, and adjustable by this contract's owner,\n     * up to a maximum of `MAX_WITHDRAWAL_DELAY_BLOCKS`. Minimum value is 0 (i.e. no delay enforced).\n     */\n    function strategyWithdrawalDelayBlocks(IStrategy strategy) external view returns (uint256);\n\n    /**\n     * @notice Calculates the digestHash for a `staker` to sign to delegate to an `operator`\n     * @param staker The signing staker\n     * @param operator The operator who is being delegated to\n     * @param expiry The desired expiry time of the staker's signature\n     */\n    function calculateCurrentStakerDelegationDigestHash(\n        address staker,\n        address operator,\n        uint256 expiry\n    )\n        external\n        view\n        returns (bytes32);\n\n    /**\n     * @notice Calculates the digest hash to be signed and used in the `delegateToBySignature` function\n     * @param staker The signing staker\n     * @param _stakerNonce The nonce of the staker. In practice we use the staker's current nonce, stored at\n     * `stakerNonce[staker]`\n     * @param operator The operator who is being delegated to\n     * @param expiry The desired expiry time of the staker's signature\n     */\n    function calculateStakerDelegationDigestHash(\n        address staker,\n        uint256 _stakerNonce,\n        address operator,\n        uint256 expiry\n    )\n        external\n        view\n        returns (bytes32);\n\n    /**\n     * @notice Calculates the digest hash to be signed by the operator's delegationApprove and used in the `delegateTo`\n     * and `delegateToBySignature` functions.\n     * @param staker The account delegating their stake\n     * @param operator The account receiving delegated stake\n     * @param _delegationApprover the operator's `delegationApprover` who will be signing the delegationHash (in\n     * general)\n     * @param approverSalt A unique and single use value associated with the approver signature.\n     * @param expiry Time after which the approver's signature becomes invalid\n     */\n    function calculateDelegationApprovalDigestHash(\n        address staker,\n        address operator,\n        address _delegationApprover,\n        bytes32 approverSalt,\n        uint256 expiry\n    )\n        external\n        view\n        returns (bytes32);\n\n    /// @notice The EIP-712 typehash for the contract's domain\n    function DOMAIN_TYPEHASH() external view returns (bytes32);\n\n    /// @notice The EIP-712 typehash for the StakerDelegation struct used by the contract\n    function STAKER_DELEGATION_TYPEHASH() external view returns (bytes32);\n\n    /// @notice The EIP-712 typehash for the DelegationApproval struct used by the contract\n    function DELEGATION_APPROVAL_TYPEHASH() external view returns (bytes32);\n\n    /**\n     * @notice Getter function for the current EIP-712 domain separator for this contract.\n     *\n     * @dev The domain separator will change in the event of a fork that changes the ChainID.\n     * @dev By introducing a domain separator the DApp developers are guaranteed that there can be no signature\n     * collision.\n     * for more detailed information please read EIP-712.\n     */\n    function domainSeparator() external view returns (bytes32);\n\n    /// @notice Mapping: staker => cumulative number of queued withdrawals they have ever initiated.\n    /// @dev This only increments (doesn't decrement), and is used to help ensure that otherwise identical withdrawals\n    /// have unique hashes.\n    function cumulativeWithdrawalsQueued(address staker) external view returns (uint256);\n\n    /// @notice Returns the keccak256 hash of `withdrawal`.\n    function calculateWithdrawalRoot(Withdrawal memory withdrawal) external pure returns (bytes32);\n\n    // @notice Struct that bundles together a signature and an expiration time for the signature. Used primarily for\n    // stack management.\n    struct SignatureWithExpiry {\n        // the signature itself, formatted as a single bytes object\n        bytes signature;\n        // the expiration timestamp (UTC) of the signature\n        uint256 expiry;\n    }\n\n    /**\n     * @notice Caller delegates their stake to an operator.\n     * @param operator The account (`msg.sender`) is delegating its assets to for use in serving applications built on\n     * EigenLayer.\n     * @param approverSignatureAndExpiry Verifies the operator approves of this delegation\n     * @param approverSalt A unique single use value tied to an individual signature.\n     * @dev The approverSignatureAndExpiry is used in the event that:\n     *          1) the operator's `delegationApprover` address is set to a non-zero value.\n     *                  AND\n     *          2) neither the operator nor their `delegationApprover` is the `msg.sender`, since in the event that the\n     * operator\n     *             or their delegationApprover is the `msg.sender`, then approval is assumed.\n     * @dev In the event that `approverSignatureAndExpiry` is not checked, its content is ignored entirely; it's\n     * recommended to use an empty input\n     * in this case to save on complexity + gas costs\n     */\n    function delegateTo(\n        address operator,\n        SignatureWithExpiry memory approverSignatureAndExpiry,\n        bytes32 approverSalt\n    )\n        external;\n\n    /**\n     * @notice Delegates from `staker` to `operator`.\n     * @dev requires that:\n     * 1) if `staker` is an EOA, then `signature` is valid ECDSA signature from `staker`, indicating their intention for\n     * this action\n     * 2) if `staker` is a contract, then `signature` must will be checked according to EIP-1271\n     */\n    function delegateToBySignature(address staker, address operator, uint256 expiry, bytes memory signature) external;\n\n    /**\n     * @notice Returns the number of actively-delegatable shares a staker has across all strategies.\n     * @dev Returns two empty arrays in the case that the Staker has no actively-delegateable shares.\n     */\n    function getDelegatableShares(address staker) external view returns (IStrategy[] memory, uint256[] memory);\n\n    /// @notice Returns 'true' if `staker` is *not* actively delegated, and 'false' otherwise.\n    function isNotDelegated(address staker) external view returns (bool);\n}\n"
      },
      "contracts/external/eigenlayer/interfaces/IEigenDelayedWithdrawalRouter.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ninterface IEigenDelayedWithdrawalRouter {\n    // struct used to pack data into a single storage slot\n    struct DelayedWithdrawal {\n        uint224 amount;\n        uint32 blockCreated;\n    }\n\n    // struct used to store a single users delayedWithdrawal data\n    struct UserDelayedWithdrawals {\n        uint256 delayedWithdrawalsCompleted;\n        DelayedWithdrawal[] delayedWithdrawals;\n    }\n\n    function getUserDelayedWithdrawals(address user) external view returns (DelayedWithdrawal[] memory);\n\n    function claimDelayedWithdrawals(address recipient, uint256 maxNumberOfDelayedWithdrawalsToClaim) external;\n\n    function userWithdrawals(address user) external view returns (UserDelayedWithdrawals memory);\n\n    function userWithdrawalsLength(address user) external view returns (uint256);\n}\n"
      },
      "contracts/utils/UtilLib.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/// @title UtilLib - Utility library\n/// @notice Utility functions\nlibrary UtilLib {\n    error ZeroAddressNotAllowed();\n\n    /// @dev zero address check modifier\n    /// @param address_ address to check\n    function checkNonZeroAddress(address address_) internal pure {\n        if (address_ == address(0)) revert ZeroAddressNotAllowed();\n    }\n\n    function getMin(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (a < b) return a;\n        return b;\n    }\n\n    function getMax(uint256 a, uint256 b) internal pure returns (uint256) {\n        if (a > b) return a;\n        return b;\n    }\n}\n"
      },
      "contracts/utils/LRTConstants.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary LRTConstants {\n    //tokens\n    //rETH token\n    bytes32 public constant R_ETH_TOKEN = keccak256(\"R_ETH_TOKEN\");\n    //stETH token\n    bytes32 public constant ST_ETH_TOKEN = keccak256(\"ST_ETH_TOKEN\");\n    //cbETH token\n    bytes32 public constant CB_ETH_TOKEN = keccak256(\"CB_ETH_TOKEN\");\n    //ETHX token\n    bytes32 public constant ETHX_TOKEN = keccak256(\"ETHX_TOKEN\");\n    //sfrxETH\n    bytes32 public constant SFRX_ETH_TOKEN = keccak256(\"SFRX_ETH_TOKEN\");\n\n    bytes32 public constant BEACON_CHAIN_ETH_STRATEGY = keccak256(\"BEACON_CHAIN_ETH_STRATEGY\");\n\n    //contracts\n    bytes32 public constant LRT_ORACLE = keccak256(\"LRT_ORACLE\");\n    bytes32 public constant LRT_DEPOSIT_POOL = keccak256(\"LRT_DEPOSIT_POOL\");\n    bytes32 public constant LRT_WITHDRAW_MANAGER = keccak256(\"LRT_WITHDRAW_MANAGER\");\n    bytes32 public constant LRT_UNSTAKING_VAULT = keccak256(\"LRT_UNSTAKING_VAULT\");\n    bytes32 public constant LRT_CONVERTER = keccak256(\"LRT_CONVERTER\");\n\n    bytes32 public constant EIGEN_STRATEGY_MANAGER = keccak256(\"EIGEN_STRATEGY_MANAGER\");\n\n    //Roles\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n    bytes32 public constant MANAGER = keccak256(\"MANAGER\");\n    bytes32 public constant PAUSER_ROLE = keccak256(\"PAUSER_ROLE\");\n    bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n    bytes32 public constant BURNER_ROLE = keccak256(\"BURNER_ROLE\");\n\n    // updated library variables\n    bytes32 public constant SFRXETH_TOKEN = keccak256(\"SFRXETH_TOKEN\");\n    // add new vars below\n    bytes32 public constant EIGEN_POD_MANAGER = keccak256(\"EIGEN_POD_MANAGER\");\n\n    // native ETH as ERC20 for ease of implementation\n    address public constant ETH_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n    // Operator Role\n    bytes32 public constant OPERATOR_ROLE = keccak256(\"OPERATOR_ROLE\");\n\n    // reward receiver contract\n    bytes32 public constant REWARD_RECEIVER = keccak256(\"REWARD_RECEIVER\");\n\n    // EigenLayer Delegation Manager\n    bytes32 public constant EIGEN_DELEGATION_MANAGER = keccak256(\"EIGEN_DELEGATION_MANAGER\");\n\n    uint256 public constant ONE_E_9 = 1e9;\n}\n"
      },
      "contracts/utils/LRTConfigRoleChecker.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { UtilLib } from \"./UtilLib.sol\";\nimport { LRTConstants } from \"./LRTConstants.sol\";\n\nimport { ILRTConfig } from \"../interfaces/ILRTConfig.sol\";\n\nimport { IAccessControl } from \"@openzeppelin/contracts/access/IAccessControl.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/interfaces/IERC20.sol\";\n\n/// @title LRTConfigRoleChecker - LRT Config Role Checker Contract\n/// @notice Handles LRT config role checks\nabstract contract LRTConfigRoleChecker {\n    ILRTConfig public lrtConfig;\n\n    // events\n    event UpdatedLRTConfig(address indexed lrtConfig);\n\n    // modifiers\n    modifier onlyRole(bytes32 role) {\n        if (!IAccessControl(address(lrtConfig)).hasRole(role, msg.sender)) {\n            string memory roleStr = string(abi.encodePacked(role));\n            revert ILRTConfig.CallerNotLRTConfigAllowedRole(roleStr);\n        }\n        _;\n    }\n\n    modifier onlyLRTManager() {\n        if (!IAccessControl(address(lrtConfig)).hasRole(LRTConstants.MANAGER, msg.sender)) {\n            revert ILRTConfig.CallerNotLRTConfigManager();\n        }\n        _;\n    }\n\n    modifier onlyLRTOperator() {\n        if (!IAccessControl(address(lrtConfig)).hasRole(LRTConstants.OPERATOR_ROLE, msg.sender)) {\n            revert ILRTConfig.CallerNotLRTConfigOperator();\n        }\n        _;\n    }\n\n    modifier onlyLRTAdmin() {\n        if (!IAccessControl(address(lrtConfig)).hasRole(LRTConstants.DEFAULT_ADMIN_ROLE, msg.sender)) {\n            revert ILRTConfig.CallerNotLRTConfigAdmin();\n        }\n        _;\n    }\n\n    modifier onlySupportedAsset(address asset) {\n        if (!lrtConfig.isSupportedAsset(asset)) {\n            revert ILRTConfig.AssetNotSupported();\n        }\n        _;\n    }\n\n    // setters\n\n    /// @notice Updates the LRT config contract\n    /// @dev only callable by LRT admin\n    /// @param lrtConfigAddr the new LRT config contract Address\n    function updateLRTConfig(address lrtConfigAddr) external virtual onlyLRTAdmin {\n        if (address(lrtConfig) != address(0)) revert ILRTConfig.ValueAlreadyInUse();\n\n        UtilLib.checkNonZeroAddress(lrtConfigAddr);\n        lrtConfig = ILRTConfig(lrtConfigAddr);\n        emit UpdatedLRTConfig(lrtConfigAddr);\n    }\n}\n"
      },
      "contracts/interfaces/ILRTConfig.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ninterface ILRTConfig {\n    // Errors\n    error ValueAlreadyInUse();\n    error AssetAlreadySupported();\n    error AssetNotSupported();\n    error CallerNotLRTConfigAdmin();\n    error CallerNotLRTConfigManager();\n    error CallerNotLRTConfigOperator();\n    error CallerNotLRTConfigAllowedRole(string role);\n    error CannotUpdateStrategyAsItHasFundsNDCFunds(address ndc, uint256 amount);\n    error InvalidMaxRewardAmount();\n\n    // Events\n    event SetToken(bytes32 key, address indexed tokenAddr);\n    event SetContract(bytes32 key, address indexed contractAddr);\n    event AddedNewSupportedAsset(address indexed asset, uint256 depositLimit);\n    event RemovedSupportedAsset(address indexed asset);\n    event AssetDepositLimitUpdate(address indexed asset, uint256 depositLimit);\n    event AssetStrategyUpdate(address indexed asset, address indexed strategy);\n    event SetRSETH(address indexed rsETH);\n    event UpdateMaxRewardAmount(uint256 maxRewardAmount);\n\n    // methods\n\n    function rsETH() external view returns (address);\n\n    function assetStrategy(address asset) external view returns (address);\n\n    function isSupportedAsset(address asset) external view returns (bool);\n\n    function getLSTToken(bytes32 tokenId) external view returns (address);\n\n    function getContract(bytes32 contractId) external view returns (address);\n\n    function getSupportedAssetList() external view returns (address[] memory);\n\n    function depositLimitByAsset(address asset) external view returns (uint256);\n}\n"
      },
      "contracts/interfaces/INodeDelegator.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IStrategy, IERC20 } from \"contracts/external/eigenlayer/interfaces/IStrategy.sol\";\nimport { IEigenDelegationManager } from \"contracts/external/eigenlayer/interfaces/IEigenDelegationManager.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface INodeDelegator {\n    // event\n    event AssetDepositIntoStrategy(address indexed asset, address indexed strategy, uint256 depositAmount);\n    event ETHDepositFromDepositPool(uint256 depositAmount);\n    event EigenPodCreated(address indexed eigenPod, address indexed podOwner);\n    event ETHStaked(bytes valPubKey, uint256 amount);\n    event WithdrawalQueued(uint256 nonce, address withdrawer, bytes32[] withdrawalRoots);\n    event EthTransferred(address to, uint256 amount);\n    event EigenLayerWithdrawalCompleted(address indexed depositor, uint256 nonce, address indexed caller);\n    event ETHRewardsReceived(uint256 amount);\n    event ETHExtraStakeToReceiveIncremented(uint256 amount);\n    event ExtraStakeReceived(uint256 amount);\n    event ETHRewardsWithdrawInitiated(uint256 amount);\n    event ElSharesDelegated(address indexed elOperator);\n    event RestakingActivated();\n    event ETHReceived(address indexed sender, uint256 amount);\n    event Undelegated();\n\n    // errors\n    error TokenTransferFailed();\n    error StrategyIsNotSetForAsset();\n    error InvalidETHSender();\n    error InvalidDepositRoot(bytes32 expectedDepositRoot, bytes32 actualDepositRoot);\n    error StrategyMustNotBeBeaconChain();\n    error InsufficientStakedButUnverifiedNativeETH();\n    error InvalidWithdrawalData();\n\n    // getter\n    function stakedButUnverifiedNativeETH() external view returns (uint256);\n\n    // write functions\n    function depositAssetIntoStrategy(address asset) external;\n    function maxApproveToEigenStrategyManager(address asset) external;\n    function initiateUnstaking(\n        IStrategy[] calldata strategies,\n        uint256[] calldata shares\n    )\n        external\n        returns (bytes32 withdrawalRoot);\n\n    function completeUnstaking(\n        IEigenDelegationManager.Withdrawal calldata withdrawal,\n        IERC20[] calldata assets,\n        uint256 middlewareTimesIndex\n    )\n        external;\n\n    // view functions\n    function getAssetBalances() external view returns (address[] memory, uint256[] memory);\n\n    function getAssetBalance(address asset) external view returns (uint256);\n\n    function getETHEigenPodBalance() external view returns (uint256);\n\n    function transferBackToLRTDepositPool(address asset, uint256 amount) external;\n\n    function sendETHFromDepositPoolToNDC() external payable;\n}\n"
      },
      "contracts/interfaces/ILRTUnstakingVault.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nimport { IStrategy } from \"contracts/external/eigenlayer/interfaces/IStrategy.sol\";\nimport { IEigenDelegationManager } from \"contracts/external/eigenlayer/interfaces/IEigenDelegationManager.sol\";\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ILRTUnstakingVault {\n    error CallerNotLRTNodeDelegator();\n    error EthTransferFailed();\n    error CallerNotLRTWithdrawalManager();\n\n    event EthReceived(address sender, uint256 amount);\n\n    // functions\n    function sharesUnstaking(address asset) external view returns (uint256);\n\n    function getAssetsUnstaking(address asset) external view returns (uint256);\n\n    function balanceOf(address asset) external view returns (uint256);\n\n    function addSharesUnstaking(address asset, uint256 amount) external;\n\n    function reduceSharesUnstaking(address asset, uint256 amount) external;\n\n    function redeem(address asset, uint256 amount) external;\n\n    // receive functions\n    function receiveFromLRTDepositPool() external payable;\n    function receiveFromNodeDelegator() external payable;\n}\n"
      },
      "contracts/interfaces/ILRTDepositPool.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ninterface ILRTDepositPool {\n    //errors\n    error InvalidAmountToDeposit();\n    error NotEnoughAssetToTransfer();\n    error MaximumDepositLimitReached();\n    error MaximumNodeDelegatorLimitReached();\n    error InvalidMaximumNodeDelegatorLimit();\n    error MinimumAmountToReceiveNotMet();\n    error NodeDelegatorNotFound();\n    error NodeDelegatorHasAssetBalance(address assetAddress, uint256 assetBalance);\n    error NodeDelegatorHasETH();\n    error EthTransferFailed();\n\n    //events\n    event MaxNodeDelegatorLimitUpdated(uint256 maxNodeDelegatorLimit);\n    event NodeDelegatorAddedinQueue(address[] nodeDelegatorContracts);\n    event NodeDelegatorRemovedFromQueue(address nodeDelegatorContracts);\n    event AssetDeposit(\n        address indexed depositor,\n        address indexed asset,\n        uint256 depositAmount,\n        uint256 rsethMintAmount,\n        string referralId\n    );\n    event ETHDeposit(address indexed depositor, uint256 depositAmount, uint256 rsethMintAmount, string referralId);\n    event MinAmountToDepositUpdated(uint256 minAmountToDeposit);\n    event MaxNegligibleAmountUpdated(uint256 maxNegligibleAmount);\n    event ETHSwappedForLST(uint256 ethAmount, address indexed toAsset, uint256 returnAmount);\n    event EthTransferred(address to, uint256 amount);\n\n    // functions\n    function depositAsset(\n        address asset,\n        uint256 depositAmount,\n        uint256 minRSETHAmountExpected,\n        string calldata referralId\n    )\n        external;\n\n    function getSwapETHToAssetReturnAmount(\n        address toAsset,\n        uint256 ethAmountToSend\n    )\n        external\n        view\n        returns (uint256 returnAmount);\n\n    function getTotalAssetDeposits(address asset) external view returns (uint256);\n\n    function getAssetCurrentLimit(address asset) external view returns (uint256);\n\n    function getRsETHAmountToMint(address asset, uint256 depositAmount) external view returns (uint256);\n\n    function addNodeDelegatorContractToQueue(address[] calldata nodeDelegatorContract) external;\n\n    function transferAssetToNodeDelegator(uint256 ndcIndex, address asset, uint256 amount) external;\n\n    function updateMaxNodeDelegatorLimit(uint256 maxNodeDelegatorLimit) external;\n\n    function getNodeDelegatorQueue() external view returns (address[] memory);\n\n    function getAssetDistributionData(address asset)\n        external\n        view\n        returns (\n            uint256 assetLyingInDepositPool,\n            uint256 assetLyingInNDCs,\n            uint256 assetStakedInEigenLayer,\n            uint256 assetUnstakingFromEigenLayer,\n            uint256 assetLyingInConverter,\n            uint256 assetLyingUnstakingVault\n        );\n\n    function getETHDistributionData()\n        external\n        view\n        returns (\n            uint256 ethLyingInDepositPool,\n            uint256 ethLyingInNDCs,\n            uint256 ethStakedInEigenLayer,\n            uint256 ethUnstakingFromEigenLayer,\n            uint256 ethLyingInConverter,\n            uint256 ethLyingInUnstakingVault\n        );\n\n    function isNodeDelegator(address nodeDelegatorContract) external view returns (uint256);\n\n    // receivers\n    function receiveFromRewardReceiver() external payable;\n    function receiveFromLRTConverter() external payable;\n    function receiveFromNodeDelegator() external payable;\n}\n"
      },
      "contracts/interfaces/IFeeReceiver.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\ninterface IFeeReceiver {\n    // Errors\n    error InvalidEmptyValue();\n\n    // functions\n    function receiveFromNodeDelegator() external payable;\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (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 Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the 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 `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 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 `from` to `to` 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(address from, address to, uint256 amount) external returns (bool);\n}\n"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n    function __Context_init() internal onlyInitializing {\n    }\n\n    function __Context_init_unchained() internal onlyInitializing {\n    }\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    /**\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"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/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 * ```solidity\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev 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.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        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     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized != type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/utils/Address.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, \"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(address target, bytes memory data, uint256 value) 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        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or 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            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\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            /// @solidity memory-safe-assembly\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"
      },
      "contracts/external/eigenlayer/libraries/Merkle.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// Adapted from OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/MerkleProof.sol)\n\npragma solidity 0.8.21;\n\n/**\n * @dev These functions deal with verification of Merkle Tree proofs.\n *\n * The tree and the proofs can be generated using our\n * https://github.com/OpenZeppelin/merkle-tree[JavaScript library].\n * You will find a quickstart guide in the readme.\n *\n * WARNING: You should avoid using leaf values that are 64 bytes long prior to\n * hashing, or use a hash function other than keccak256 for hashing leaves.\n * This is because the concatenation of a sorted pair of internal nodes in\n * the merkle tree could be reinterpreted as a leaf value.\n * OpenZeppelin's JavaScript library generates merkle trees that are safe\n * against this attack out of the box.\n */\nlibrary Merkle {\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. The tree is built assuming `leaf` is\n     * the 0 indexed `index`'th leaf from the bottom left of the tree.\n     *\n     * Note this is for a Merkle tree using the keccak/sha3 hash function\n     */\n    function verifyInclusionKeccak(\n        bytes memory proof,\n        bytes32 root,\n        bytes32 leaf,\n        uint256 index\n    )\n        internal\n        pure\n        returns (bool)\n    {\n        return processInclusionProofKeccak(proof, leaf, index) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. The tree is built assuming `leaf` is\n     * the 0 indexed `index`'th leaf from the bottom left of the tree.\n     *\n     * _Available since v4.4._\n     *\n     * Note this is for a Merkle tree using the keccak/sha3 hash function\n     */\n    function processInclusionProofKeccak(\n        bytes memory proof,\n        bytes32 leaf,\n        uint256 index\n    )\n        internal\n        pure\n        returns (bytes32)\n    {\n        require(\n            proof.length != 0 && proof.length % 32 == 0,\n            \"Merkle.processInclusionProofKeccak: proof length should be a non-zero multiple of 32\"\n        );\n        bytes32 computedHash = leaf;\n        for (uint256 i = 32; i <= proof.length; i += 32) {\n            if (index % 2 == 0) {\n                // if ith bit of index is 0, then computedHash is a left sibling\n                assembly {\n                    mstore(0x00, computedHash)\n                    mstore(0x20, mload(add(proof, i)))\n                    computedHash := keccak256(0x00, 0x40)\n                    index := div(index, 2)\n                }\n            } else {\n                // if ith bit of index is 1, then computedHash is a right sibling\n                assembly {\n                    mstore(0x00, mload(add(proof, i)))\n                    mstore(0x20, computedHash)\n                    computedHash := keccak256(0x00, 0x40)\n                    index := div(index, 2)\n                }\n            }\n        }\n        return computedHash;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. The tree is built assuming `leaf` is\n     * the 0 indexed `index`'th leaf from the bottom left of the tree.\n     *\n     * Note this is for a Merkle tree using the sha256 hash function\n     */\n    function verifyInclusionSha256(\n        bytes memory proof,\n        bytes32 root,\n        bytes32 leaf,\n        uint256 index\n    )\n        internal\n        view\n        returns (bool)\n    {\n        return processInclusionProofSha256(proof, leaf, index) == root;\n    }\n\n    /**\n     * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up\n     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt\n     * hash matches the root of the tree. The tree is built assuming `leaf` is\n     * the 0 indexed `index`'th leaf from the bottom left of the tree.\n     *\n     * _Available since v4.4._\n     *\n     * Note this is for a Merkle tree using the sha256 hash function\n     */\n    function processInclusionProofSha256(\n        bytes memory proof,\n        bytes32 leaf,\n        uint256 index\n    )\n        internal\n        view\n        returns (bytes32)\n    {\n        require(\n            proof.length != 0 && proof.length % 32 == 0,\n            \"Merkle.processInclusionProofSha256: proof length should be a non-zero multiple of 32\"\n        );\n        bytes32[1] memory computedHash = [leaf];\n        for (uint256 i = 32; i <= proof.length; i += 32) {\n            if (index % 2 == 0) {\n                // if ith bit of index is 0, then computedHash is a left sibling\n                assembly {\n                    mstore(0x00, mload(computedHash))\n                    mstore(0x20, mload(add(proof, i)))\n                    if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { revert(0, 0) }\n                    index := div(index, 2)\n                }\n            } else {\n                // if ith bit of index is 1, then computedHash is a right sibling\n                assembly {\n                    mstore(0x00, mload(add(proof, i)))\n                    mstore(0x20, mload(computedHash))\n                    if iszero(staticcall(sub(gas(), 2000), 2, 0x00, 0x40, computedHash, 0x20)) { revert(0, 0) }\n                    index := div(index, 2)\n                }\n            }\n        }\n        return computedHash[0];\n    }\n\n    /**\n     * @notice this function returns the merkle root of a tree created from a set of leaves using sha256 as its hash\n     * function\n     *  @param leaves the leaves of the merkle tree\n     *  @return The computed Merkle root of the tree.\n     *  @dev A pre-condition to this function is that leaves.length is a power of two.  If not, the function will\n     * merkleize the inputs incorrectly.\n     */\n    function merkleizeSha256(bytes32[] memory leaves) internal pure returns (bytes32) {\n        //there are half as many nodes in the layer above the leaves\n        uint256 numNodesInLayer = leaves.length / 2;\n        //create a layer to store the internal nodes\n        bytes32[] memory layer = new bytes32[](numNodesInLayer);\n        //fill the layer with the pairwise hashes of the leaves\n        for (uint256 i = 0; i < numNodesInLayer; i++) {\n            layer[i] = sha256(abi.encodePacked(leaves[2 * i], leaves[2 * i + 1]));\n        }\n        //the next layer above has half as many nodes\n        numNodesInLayer /= 2;\n        //while we haven't computed the root\n        while (numNodesInLayer != 0) {\n            //overwrite the first numNodesInLayer nodes in layer with the pairwise hashes of their children\n            for (uint256 i = 0; i < numNodesInLayer; i++) {\n                layer[i] = sha256(abi.encodePacked(layer[2 * i], layer[2 * i + 1]));\n            }\n            //the next layer above has half as many nodes\n            numNodesInLayer /= 2;\n        }\n        //the first node in the layer is the root\n        return layer[0];\n    }\n}\n"
      },
      "contracts/external/eigenlayer/libraries/Endian.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\nlibrary Endian {\n    /**\n     * @notice Converts a little endian-formatted uint64 to a big endian-formatted uint64\n     * @param lenum little endian-formatted uint64 input, provided as 'bytes32' type\n     * @return n The big endian-formatted uint64\n     * @dev Note that the input is formatted as a 'bytes32' type (i.e. 256 bits), but it is immediately truncated to a\n     * uint64 (i.e. 64 bits)\n     * through a right-shift/shr operation.\n     */\n    function fromLittleEndianUint64(bytes32 lenum) internal pure returns (uint64 n) {\n        // the number needs to be stored in little-endian encoding (ie in bytes 0-8)\n        n = uint64(uint256(lenum >> 192));\n        return (n >> 56) | ((0x00FF000000000000 & n) >> 40) | ((0x0000FF0000000000 & n) >> 24)\n            | ((0x000000FF00000000 & n) >> 8) | ((0x00000000FF000000 & n) << 8) | ((0x0000000000FF0000 & n) << 24)\n            | ((0x000000000000FF00 & n) << 40) | ((0x00000000000000FF & n) << 56);\n    }\n}\n"
      },
      "contracts/external/eigenlayer/interfaces/ISlasher.sol": {
        "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.21;\n\n/**\n * @title Interface for the primary 'slashing' contract for EigenLayer.\n * @author Layr Labs, Inc.\n * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service\n * @notice See the `Slasher` contract itself for implementation details.\n */\ninterface ISlasher {\n    // struct used to store information about the current state of an operator's obligations to middlewares they are\n    // serving\n    struct MiddlewareTimes {\n        // The update block for the middleware whose most recent update was earliest, i.e. the 'stalest' update out of\n        // all middlewares the operator is serving\n        uint32 stalestUpdateBlock;\n        // The latest 'serveUntilBlock' from all of the middleware that the operator is serving\n        uint32 latestServeUntilBlock;\n    }\n\n    // struct used to store details relevant to a single middleware that an operator has opted-in to serving\n    struct MiddlewareDetails {\n        // the block before which the contract is allowed to slash the user\n        uint32 contractCanSlashOperatorUntilBlock;\n        // the block at which the middleware's view of the operator's stake was most recently updated\n        uint32 latestUpdateBlock;\n    }\n\n    /**\n     * @notice Gives the `contractAddress` permission to slash the funds of the caller.\n     * @dev Typically, this function must be called prior to registering for a middleware.\n     */\n    function optIntoSlashing(address contractAddress) external;\n\n    /**\n     * @notice Used for 'slashing' a certain operator.\n     * @param toBeFrozen The operator to be frozen.\n     * @dev Technically the operator is 'frozen' (hence the name of this function), and then subject to slashing pending\n     * a decision by a human-in-the-loop.\n     * @dev The operator must have previously given the caller (which should be a contract) the ability to slash them,\n     * through a call to `optIntoSlashing`.\n     */\n    function freezeOperator(address toBeFrozen) external;\n\n    /**\n     * @notice Removes the 'frozen' status from each of the `frozenAddresses`\n     * @dev Callable only by the contract owner (i.e. governance).\n     */\n    function resetFrozenStatus(address[] calldata frozenAddresses) external;\n\n    /**\n     * @notice this function is a called by middlewares during an operator's registration to make sure the operator's\n     * stake at registration\n     *         is slashable until serveUntil\n     * @param operator the operator whose stake update is being recorded\n     * @param serveUntilBlock the block until which the operator's stake at the current block is slashable\n     * @dev adds the middleware's slashing contract to the operator's linked list\n     */\n    function recordFirstStakeUpdate(address operator, uint32 serveUntilBlock) external;\n\n    /**\n     * @notice this function is a called by middlewares during a stake update for an operator (perhaps to free pending\n     * withdrawals)\n     *         to make sure the operator's stake at updateBlock is slashable until serveUntil\n     * @param operator the operator whose stake update is being recorded\n     * @param updateBlock the block for which the stake update is being recorded\n     * @param serveUntilBlock the block until which the operator's stake at updateBlock is slashable\n     * @param insertAfter the element of the operators linked list that the currently updating middleware should be\n     * inserted after\n     * @dev insertAfter should be calculated offchain before making the transaction that calls this. this is subject to\n     * race conditions,\n     *      but it is anticipated to be rare and not detrimental.\n     */\n    function recordStakeUpdate(\n        address operator,\n        uint32 updateBlock,\n        uint32 serveUntilBlock,\n        uint256 insertAfter\n    )\n        external;\n\n    /**\n     * @notice this function is a called by middlewares during an operator's deregistration to make sure the operator's\n     * stake at deregistration\n     *         is slashable until serveUntil\n     * @param operator the operator whose stake update is being recorded\n     * @param serveUntilBlock the block until which the operator's stake at the current block is slashable\n     * @dev removes the middleware's slashing contract to the operator's linked list and revokes the middleware's (i.e.\n     * caller's) ability to\n     * slash `operator` once `serveUntil` is reached\n     */\n    function recordLastStakeUpdateAndRevokeSlashingAbility(address operator, uint32 serveUntilBlock) external;\n\n    /**\n     * @notice Used to determine whether `staker` is actively 'frozen'. If a staker is frozen, then they are potentially\n     * subject to\n     * slashing of their funds, and cannot cannot deposit or withdraw from the strategyManager until the slashing\n     * process is completed\n     * and the staker's status is reset (to 'unfrozen').\n     * @param staker The staker of interest.\n     * @return Returns 'true' if `staker` themselves has their status set to frozen, OR if the staker is delegated\n     * to an operator who has their status set to frozen. Otherwise returns 'false'.\n     */\n    function isFrozen(address staker) external view returns (bool);\n\n    /// @notice Returns true if `slashingContract` is currently allowed to slash `toBeSlashed`.\n    function canSlash(address toBeSlashed, address slashingContract) external view returns (bool);\n\n    /// @notice Returns the block until which `serviceContract` is allowed to slash the `operator`.\n    function contractCanSlashOperatorUntilBlock(\n        address operator,\n        address serviceContract\n    )\n        external\n        view\n        returns (uint32);\n\n    /// @notice Returns the block at which the `serviceContract` last updated its view of the `operator`'s stake\n    function latestUpdateBlock(address operator, address serviceContract) external view returns (uint32);\n\n    /// @notice A search routine for finding the correct input value of `insertAfter` to `recordStakeUpdate` /\n    /// `_updateMiddlewareList`.\n    function getCorrectValueForInsertAfter(address operator, uint32 updateBlock) external view returns (uint256);\n\n    /**\n     * @notice Returns 'true' if `operator` can currently complete a withdrawal started at the `withdrawalStartBlock`,\n     * with `middlewareTimesIndex` used\n     * to specify the index of a `MiddlewareTimes` struct in the operator's list (i.e. an index in\n     * `operatorToMiddlewareTimes[operator]`). The specified\n     * struct is consulted as proof of the `operator`'s ability (or lack thereof) to complete the withdrawal.\n     * This function will return 'false' if the operator cannot currently complete a withdrawal started at the\n     * `withdrawalStartBlock`, *or* in the event\n     * that an incorrect `middlewareTimesIndex` is supplied, even if one or more correct inputs exist.\n     * @param operator Either the operator who queued the withdrawal themselves, or if the withdrawing party is a staker\n     * who delegated to an operator,\n     * this address is the operator *who the staker was delegated to* at the time of the `withdrawalStartBlock`.\n     * @param withdrawalStartBlock The block number at which the withdrawal was initiated.\n     * @param middlewareTimesIndex Indicates an index in `operatorToMiddlewareTimes[operator]` to consult as proof of\n     * the `operator`'s ability to withdraw\n     * @dev The correct `middlewareTimesIndex` input should be computable off-chain.\n     */\n    function canWithdraw(\n        address operator,\n        uint32 withdrawalStartBlock,\n        uint256 middlewareTimesIndex\n    )\n        external\n        returns (bool);\n\n    /**\n     * operator =>\n     *  [\n     *      (\n     *          the least recent update block of all of the middlewares it's serving/served,\n     *          latest time that the stake bonded at that update needed to serve until\n     *      )\n     *  ]\n     */\n    function operatorToMiddlewareTimes(\n        address operator,\n        uint256 arrayIndex\n    )\n        external\n        view\n        returns (MiddlewareTimes memory);\n\n    /// @notice Getter function for fetching `operatorToMiddlewareTimes[operator].length`\n    function middlewareTimesLength(address operator) external view returns (uint256);\n\n    /// @notice Getter function for fetching `operatorToMiddlewareTimes[operator][index].stalestUpdateBlock`.\n    function getMiddlewareTimesIndexBlock(address operator, uint32 index) external view returns (uint32);\n\n    /// @notice Getter function for fetching `operatorToMiddlewareTimes[operator][index].latestServeUntil`.\n    function getMiddlewareTimesIndexServeUntilBlock(address operator, uint32 index) external view returns (uint32);\n\n    /// @notice Getter function for fetching `_operatorToWhitelistedContractsByUpdate[operator].size`.\n    function operatorWhitelistedContractsLinkedListSize(address operator) external view returns (uint256);\n\n    /// @notice Getter function for fetching a single node in the operator's linked list\n    /// (`_operatorToWhitelistedContractsByUpdate[operator]`).\n    function operatorWhitelistedContractsLinkedListEntry(\n        address operator,\n        address node\n    )\n        external\n        view\n        returns (bool, uint256, uint256);\n}\n"
      },
      "lib/openzeppelin-contracts/contracts/access/IAccessControl.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 IAccessControl {\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"
      },
      "lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.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     * Furthermore, `isContract` will also return true if the target contract within\n     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n     * which only has an effect at the end of a transaction.\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://consensys.net/diligence/blog/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.8.0/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 functionCallWithValue(target, data, 0, \"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(address target, bytes memory data, uint256 value) 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        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, 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        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or 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            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\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            /// @solidity memory-safe-assembly\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"
      }
    },
    "settings": {
      "remappings": [
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
        "eth-gas-reporter/=node_modules/eth-gas-reporter/",
        "hardhat/=node_modules/hardhat/",
        "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/",
        "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/",
        "solidity-code-metrics/=node_modules/solidity-code-metrics/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "shanghai",
      "viaIR": false,
      "libraries": {}
    }
  }}