ETH Price: $2,058.44 (+1.06%)

Contract

0x0D4e5723daAD06510CFd6864b8eB8a08CF0c4a34
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AllocationManagerView

Compiler Version
v0.8.30+commit.73712a01

Optimization Enabled:
Yes with 200 runs

Other Settings:
prague EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.29; // Minimum for `layout at` directive.

import "./storage/AllocationManagerStorage.sol";

/// @notice Non-state mutating view functions, (static) called by the `AllocationManager`.
/// @dev The `layout at 151` directive specifies that `AllocationManagerStorage` should be placed
///      starting at storage slot 151. This slot number is calculated based on the storage layout
///      of the main `AllocationManager` contract, which inherits from multiple contracts in this order:
///
///      1. Initializable
///      2. Deprecated_OwnableUpgradeable
///      3. Pausable
///      4. AllocationManagerStorage
///
///      Since `AllocationManagerView` only needs access to the storage variables from
///      `AllocationManagerStorage` (without the other mixins), it uses `layout at 151` to
///      align its storage layout with the main `AllocationManager` contract.
contract AllocationManagerView layout at 151 is IAllocationManagerView, AllocationManagerStorage {
    using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
    using Snapshots for Snapshots.DefaultWadHistory;
    using OperatorSetLib for OperatorSet;
    using SlashingLib for uint256;
    using EnumerableSet for *;
    using SafeCast for *;

    ///
    ///                         INITIALIZING FUNCTIONS
    ///

    /// @dev Initializes the DelegationManager address, the deallocation delay, and the allocation configuration delay.
    constructor(
        IDelegationManager _delegation,
        IStrategy _eigenStrategy,
        uint32 _DEALLOCATION_DELAY,
        uint32 _ALLOCATION_CONFIGURATION_DELAY
    ) AllocationManagerStorage(_delegation, _eigenStrategy, _DEALLOCATION_DELAY, _ALLOCATION_CONFIGURATION_DELAY) {}

    ///
    ///                         INTERNAL FUNCTIONS
    ///

    /// @dev For an operator set, get the operator's effective allocated magnitude.
    /// If the operator set has a pending deallocation that can be completed at the
    /// current block number, this method returns a view of the allocation as if the deallocation
    /// was completed.
    /// @return info the effective allocated and pending magnitude for the operator set, and
    /// the effective encumbered magnitude for all operator sets belonging to this strategy
    function _getUpdatedAllocation(
        address operator,
        bytes32 operatorSetKey,
        IStrategy strategy
    ) internal view returns (StrategyInfo memory, Allocation memory) {
        StrategyInfo memory info = StrategyInfo({
            maxMagnitude: _maxMagnitudeHistory[operator][strategy].latest(),
            encumberedMagnitude: encumberedMagnitude[operator][strategy]
        });

        Allocation memory allocation = allocations[operator][operatorSetKey][strategy];

        // If the pending change can't be completed yet, return as-is
        if (block.number < allocation.effectBlock) {
            return (info, allocation);
        }

        // Otherwise, complete the pending change and return updated info
        allocation.currentMagnitude = _addInt128(allocation.currentMagnitude, allocation.pendingDiff);

        // If the completed change was a deallocation, update used magnitude
        if (allocation.pendingDiff < 0) {
            info.encumberedMagnitude = _addInt128(info.encumberedMagnitude, allocation.pendingDiff);
        }

        allocation.effectBlock = 0;
        allocation.pendingDiff = 0;

        return (info, allocation);
    }

    /// @dev Returns the minimum allocated stake at the future block.
    /// @param operatorSet The operator set to get the minimum allocated stake for.
    /// @param operators The operators to get the minimum allocated stake for.
    /// @param strategies The strategies to get the minimum allocated stake for.
    /// @param futureBlock The future block to get the minimum allocated stake for.
    function _getMinimumAllocatedStake(
        OperatorSet memory operatorSet,
        address[] memory operators,
        IStrategy[] memory strategies,
        uint32 futureBlock
    ) internal view returns (uint256[][] memory allocatedStake) {
        allocatedStake = new uint256[][](operators.length);
        uint256[][] memory delegatedStake = delegation.getOperatorsShares(operators, strategies);

        for (uint256 i = 0; i < operators.length; i++) {
            address operator = operators[i];

            allocatedStake[i] = new uint256[](strategies.length);

            for (uint256 j = 0; j < strategies.length; j++) {
                IStrategy strategy = strategies[j];

                // Fetch the max magnitude and allocation for the operator/strategy.
                // Prevent division by 0 if needed. This mirrors the "FullySlashed" checks
                // in the DelegationManager
                uint64 maxMagnitude = _maxMagnitudeHistory[operator][strategy].latest();
                if (maxMagnitude == 0) {
                    continue;
                }

                Allocation memory alloc = getAllocation(operator, operatorSet, strategy);

                // If the pending change takes effect before `futureBlock`, include it in `currentMagnitude`
                // However, ONLY include the pending change if it is a deallocation, since this method
                // is supposed to return the minimum slashable stake between now and `futureBlock`
                if (alloc.effectBlock <= futureBlock && alloc.pendingDiff < 0) {
                    alloc.currentMagnitude = _addInt128(alloc.currentMagnitude, alloc.pendingDiff);
                }

                uint256 slashableProportion = uint256(alloc.currentMagnitude).divWad(maxMagnitude);
                allocatedStake[i][j] = delegatedStake[i][j].mulWad(slashableProportion);
            }
        }
    }

    /// @dev Use safe casting when downcasting to uint64
    function _addInt128(
        uint64 a,
        int128 b
    ) internal pure returns (uint64) {
        return uint256(int256(int128(uint128(a)) + b)).toUint64();
    }

    /// @notice Helper function to check if an operator is redistributable from a list of operator sets
    /// @param operator The operator to check
    /// @param operatorSets The list of operator sets to check
    /// @return True if the operator is redistributable from any of the operator sets, false otherwise
    function _isOperatorRedistributable(
        address operator,
        OperatorSet[] memory operatorSets
    ) internal view returns (bool) {
        for (uint256 i = 0; i < operatorSets.length; ++i) {
            if (isOperatorSlashable(operator, operatorSets[i]) && isRedistributingOperatorSet(operatorSets[i])) {
                return true;
            }
        }
        return false;
    }

    ///
    ///                         VIEW FUNCTIONS
    ///

    /// @inheritdoc IAllocationManagerView
    function getOperatorSetCount(
        address avs
    ) external view returns (uint256) {
        return _operatorSets[avs].length();
    }

    /// @inheritdoc IAllocationManagerView
    function getAllocatedSets(
        address operator
    ) public view returns (OperatorSet[] memory) {
        uint256 length = allocatedSets[operator].length();

        OperatorSet[] memory operatorSets = new OperatorSet[](length);
        for (uint256 i = 0; i < length; i++) {
            operatorSets[i] = OperatorSetLib.decode(allocatedSets[operator].at(i));
        }

        return operatorSets;
    }

    /// @inheritdoc IAllocationManagerView
    function getAllocatedStrategies(
        address operator,
        OperatorSet memory operatorSet
    ) external view returns (IStrategy[] memory) {
        address[] memory values = allocatedStrategies[operator][operatorSet.key()].values();
        IStrategy[] memory strategies;

        assembly {
            strategies := values
        }

        return strategies;
    }

    /// @inheritdoc IAllocationManagerView
    function getAllocation(
        address operator,
        OperatorSet memory operatorSet,
        IStrategy strategy
    ) public view returns (Allocation memory) {
        (, Allocation memory allocation) = _getUpdatedAllocation(operator, operatorSet.key(), strategy);

        return allocation;
    }

    /// @inheritdoc IAllocationManagerView
    function getAllocations(
        address[] memory operators,
        OperatorSet memory operatorSet,
        IStrategy strategy
    ) external view returns (Allocation[] memory) {
        Allocation[] memory _allocations = new Allocation[](operators.length);

        for (uint256 i = 0; i < operators.length; i++) {
            _allocations[i] = getAllocation(operators[i], operatorSet, strategy);
        }

        return _allocations;
    }

    /// @inheritdoc IAllocationManagerView
    function getStrategyAllocations(
        address operator,
        IStrategy strategy
    ) external view returns (OperatorSet[] memory, Allocation[] memory) {
        uint256 length = allocatedSets[operator].length();

        OperatorSet[] memory operatorSets = new OperatorSet[](length);
        Allocation[] memory _allocations = new Allocation[](length);

        for (uint256 i = 0; i < length; i++) {
            OperatorSet memory operatorSet = OperatorSetLib.decode(allocatedSets[operator].at(i));

            operatorSets[i] = operatorSet;
            _allocations[i] = getAllocation(operator, operatorSet, strategy);
        }

        return (operatorSets, _allocations);
    }

    /// @inheritdoc IAllocationManagerView
    function getEncumberedMagnitude(
        address operator,
        IStrategy strategy
    ) external view returns (uint64) {
        (uint64 curEncumberedMagnitude,) = _getFreeAndUsedMagnitude(operator, strategy);
        return curEncumberedMagnitude;
    }

    /// @inheritdoc IAllocationManagerView
    function getAllocatableMagnitude(
        address operator,
        IStrategy strategy
    ) external view returns (uint64) {
        (, uint64 curAllocatableMagnitude) = _getFreeAndUsedMagnitude(operator, strategy);
        return curAllocatableMagnitude;
    }

    /// @dev For an operator, returns up-to-date amounts for current encumbered and available
    /// magnitude. Note that these two values will always add up to the operator's max magnitude
    /// for the strategy
    function _getFreeAndUsedMagnitude(
        address operator,
        IStrategy strategy
    ) internal view returns (uint64 curEncumberedMagnitude, uint64 curAllocatableMagnitude) {
        // This method needs to simulate clearing any pending deallocations.
        // This roughly mimics the calculations done in `_clearDeallocationQueue` and
        // `_getUpdatedAllocation`, while operating on a `curEncumberedMagnitude`
        // rather than continually reading/updating state.
        curEncumberedMagnitude = encumberedMagnitude[operator][strategy];

        uint256 length = deallocationQueue[operator][strategy].length();
        for (uint256 i = 0; i < length; ++i) {
            bytes32 operatorSetKey = deallocationQueue[operator][strategy].at(i);
            Allocation memory allocation = allocations[operator][operatorSetKey][strategy];

            // If we've reached a pending deallocation that isn't completable yet,
            // we can stop. Any subsequent modifications will also be uncompletable.
            if (block.number < allocation.effectBlock) {
                break;
            }

            // The diff is a deallocation. Add to encumbered magnitude. Note that this is a deallocation
            // queue and allocations aren't considered because encumbered magnitude
            // is updated as soon as the allocation is created.
            curEncumberedMagnitude = _addInt128(curEncumberedMagnitude, allocation.pendingDiff);
        }

        // The difference between the operator's max magnitude and its encumbered magnitude
        // is the magnitude that can be allocated.
        curAllocatableMagnitude = _maxMagnitudeHistory[operator][strategy].latest() - curEncumberedMagnitude;
        return (curEncumberedMagnitude, curAllocatableMagnitude);
    }

    /// @inheritdoc IAllocationManagerView
    function getMaxMagnitude(
        address operator,
        IStrategy strategy
    ) public view returns (uint64) {
        return _maxMagnitudeHistory[operator][strategy].latest();
    }

    /// @inheritdoc IAllocationManagerView
    function getMaxMagnitudes(
        address operator,
        IStrategy[] memory strategies
    ) external view returns (uint64[] memory) {
        uint64[] memory maxMagnitudes = new uint64[](strategies.length);

        for (uint256 i = 0; i < strategies.length; ++i) {
            maxMagnitudes[i] = getMaxMagnitude(operator, strategies[i]);
        }

        return maxMagnitudes;
    }

    /// @inheritdoc IAllocationManagerView
    function getMaxMagnitudes(
        address[] memory operators,
        IStrategy strategy
    ) external view returns (uint64[] memory) {
        uint64[] memory maxMagnitudes = new uint64[](operators.length);

        for (uint256 i = 0; i < operators.length; ++i) {
            maxMagnitudes[i] = getMaxMagnitude(operators[i], strategy);
        }

        return maxMagnitudes;
    }

    /// @inheritdoc IAllocationManagerView
    function getMaxMagnitudesAtBlock(
        address operator,
        IStrategy[] memory strategies,
        uint32 blockNumber
    ) external view returns (uint64[] memory) {
        uint64[] memory maxMagnitudes = new uint64[](strategies.length);

        for (uint256 i = 0; i < strategies.length; ++i) {
            maxMagnitudes[i] = _maxMagnitudeHistory[operator][strategies[i]].upperLookup({key: blockNumber});
        }

        return maxMagnitudes;
    }

    /// @inheritdoc IAllocationManagerView
    function getAllocationDelay(
        address operator
    ) public view returns (bool, uint32) {
        AllocationDelayInfo memory info = _allocationDelayInfo[operator];

        uint32 delay = info.delay;
        bool isSet = info.isSet;

        // If there is a pending delay that can be applied, apply it
        if (info.effectBlock != 0 && block.number >= info.effectBlock) {
            delay = info.pendingDelay;
            isSet = true;
        }

        return (isSet, delay);
    }

    /// @inheritdoc IAllocationManagerView
    function getRegisteredSets(
        address operator
    ) public view returns (OperatorSet[] memory) {
        uint256 length = registeredSets[operator].length();
        OperatorSet[] memory operatorSets = new OperatorSet[](length);

        for (uint256 i = 0; i < length; ++i) {
            operatorSets[i] = OperatorSetLib.decode(registeredSets[operator].at(i));
        }

        return operatorSets;
    }

    /// @inheritdoc IAllocationManagerView
    function isMemberOfOperatorSet(
        address operator,
        OperatorSet memory operatorSet
    ) public view returns (bool) {
        return _operatorSetMembers[operatorSet.key()].contains(operator);
    }

    /// @inheritdoc IAllocationManagerView
    function isOperatorSet(
        OperatorSet memory operatorSet
    ) external view returns (bool) {
        return _operatorSets[operatorSet.avs].contains(operatorSet.id);
    }

    /// @inheritdoc IAllocationManagerView
    function getMembers(
        OperatorSet memory operatorSet
    ) external view returns (address[] memory) {
        return _operatorSetMembers[operatorSet.key()].values();
    }

    /// @inheritdoc IAllocationManagerView
    function getMemberCount(
        OperatorSet memory operatorSet
    ) external view returns (uint256) {
        return _operatorSetMembers[operatorSet.key()].length();
    }

    /// @inheritdoc IAllocationManagerView
    function getAVSRegistrar(
        address avs
    ) public view returns (IAVSRegistrar) {
        IAVSRegistrar registrar = _avsRegistrar[avs];

        return address(registrar) == address(0) ? IAVSRegistrar(avs) : registrar;
    }

    /// @inheritdoc IAllocationManagerView
    function getStrategiesInOperatorSet(
        OperatorSet memory operatorSet
    ) external view returns (IStrategy[] memory) {
        address[] memory values = _operatorSetStrategies[operatorSet.key()].values();
        IStrategy[] memory strategies;

        assembly {
            strategies := values
        }

        return strategies;
    }

    /// @inheritdoc IAllocationManagerView
    function getMinimumSlashableStake(
        OperatorSet memory operatorSet,
        address[] memory operators,
        IStrategy[] memory strategies,
        uint32 futureBlock
    ) external view returns (uint256[][] memory slashableStake) {
        slashableStake = _getMinimumAllocatedStake(operatorSet, operators, strategies, futureBlock);

        for (uint256 i = 0; i < operators.length; i++) {
            // If the operator is not slashable by the opSet, all strategies should have a slashable stake of 0
            if (!isOperatorSlashable(operators[i], operatorSet)) {
                for (uint256 j = 0; j < strategies.length; j++) {
                    slashableStake[i][j] = 0;
                }
            }
        }
    }

    /// @inheritdoc IAllocationManagerView
    function getAllocatedStake(
        OperatorSet memory operatorSet,
        address[] memory operators,
        IStrategy[] memory strategies
    ) external view returns (uint256[][] memory) {
        /// This helper function returns the minimum allocated stake by taking into account deallocations at some `futureBlock`.
        /// We use the block.number, as the `futureBlock`, meaning that no **future** deallocations are considered.
        return _getMinimumAllocatedStake(operatorSet, operators, strategies, uint32(block.number));
    }

    /// @inheritdoc IAllocationManagerView
    function isOperatorSlashable(
        address operator,
        OperatorSet memory operatorSet
    ) public view returns (bool) {
        RegistrationStatus memory status = registrationStatus[operator][operatorSet.key()];

        // slashableUntil returns the last block the operator is slashable in so we check for
        // less than or equal to
        return status.registered || block.number <= status.slashableUntil;
    }

    /// @inheritdoc IAllocationManagerView
    function getRedistributionRecipient(
        OperatorSet memory operatorSet
    ) public view returns (address) {
        // Load the redistribution recipient and return it if set, otherwise return the default burn address.
        address redistributionRecipient = _redistributionRecipients[operatorSet.key()];
        return redistributionRecipient == address(0) ? DEFAULT_BURN_ADDRESS : redistributionRecipient;
    }

    /// @inheritdoc IAllocationManagerView
    function isRedistributingOperatorSet(
        OperatorSet memory operatorSet
    ) public view returns (bool) {
        return getRedistributionRecipient(operatorSet) != DEFAULT_BURN_ADDRESS;
    }

    /// @inheritdoc IAllocationManagerView
    function getSlashCount(
        OperatorSet memory operatorSet
    ) external view returns (uint256) {
        return _slashIds[operatorSet.key()];
    }

    /// @inheritdoc IAllocationManagerView
    function isOperatorRedistributable(
        address operator
    ) external view returns (bool) {
        // Get the registered and allocated sets for the operator.
        // We get both sets, since:
        //    - Upon registration the operator allocation will be pending to a redistributing operator set, and as such not yet in RegisteredSets.
        //    - Upon deregistration the operator is removed from RegisteredSets, but is still allocated.
        OperatorSet[] memory registeredSets = getRegisteredSets(operator);
        OperatorSet[] memory allocatedSets = getAllocatedSets(operator);

        // Check if the operator is redistributable from any of the registered or allocated sets
        return
            _isOperatorRedistributable(operator, registeredSets) || _isOperatorRedistributable(operator, allocatedSets);
    }

    /// @inheritdoc IAllocationManagerView
    /// @dev Returns (address(0), 0) for non-existent operator sets or when no pending slasher change exists.
    function getPendingSlasher(
        OperatorSet memory operatorSet
    ) external view returns (address, uint32) {
        // Initialize the pending slasher and effect block to the address(0) and 0 respectively
        address pendingSlasher;
        uint32 effectBlock;

        // If there is a pending slasher, set it
        SlasherParams memory params = _slashers[operatorSet.key()];
        if (block.number < params.effectBlock) {
            pendingSlasher = params.pendingSlasher;
            effectBlock = params.effectBlock;
        }

        return (pendingSlasher, effectBlock);
    }

    /// @inheritdoc IAllocationManagerView
    /// @dev Returns address(0) for non-existent operator sets.
    function getSlasher(
        OperatorSet memory operatorSet
    ) public view returns (address) {
        SlasherParams memory params = _slashers[operatorSet.key()];

        address slasher = params.slasher;

        // If there is a pending slasher that can be applied, apply it
        if (params.effectBlock != 0 && block.number >= params.effectBlock) {
            slasher = params.pendingSlasher;
        }

        return slasher;
    }
}

File 2 of 19 : AllocationManagerStorage.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;

import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/utils/structs/DoubleEndedQueue.sol";

import "../../interfaces/IAllocationManager.sol";
import {Snapshots} from "../../libraries/Snapshots.sol";

abstract contract AllocationManagerStorage is IAllocationManagerStorage {
    using Snapshots for Snapshots.DefaultWadHistory;

    // Constants

    /// @dev The default burn address for slashed funds.
    address internal constant DEFAULT_BURN_ADDRESS = 0x00000000000000000000000000000000000E16E4;

    /// @dev The beacon chain ETH strategy.
    IStrategy internal constant BEACONCHAIN_ETH_STRAT = IStrategy(0xbeaC0eeEeeeeEEeEeEEEEeeEEeEeeeEeeEEBEaC0);

    /// @dev Index for flag that pauses operator allocations/deallocations when set.
    uint8 internal constant PAUSED_MODIFY_ALLOCATIONS = 0;

    /// @dev Index for flag that pauses operator register/deregister to operator sets when set.
    uint8 internal constant PAUSED_OPERATOR_SLASHING = 1;

    /// @dev Index for flag that pauses operator register/deregister to operator sets when set.
    uint8 internal constant PAUSED_OPERATOR_SET_REGISTRATION_AND_DEREGISTRATION = 2;

    // Immutables

    /// @notice The DelegationManager contract for EigenLayer
    IDelegationManager public immutable delegation;

    /// @notice The Eigen strategy contract
    /// @dev Cannot be added to redistributing operator sets
    IStrategy public immutable eigenStrategy;

    /// @notice Delay before deallocations are clearable and can be added back into freeMagnitude
    /// In this window, deallocations still remain slashable by the operatorSet they were allocated to.
    uint32 public immutable DEALLOCATION_DELAY;

    /// @notice Delay before allocation delay modifications take effect.
    uint32 public immutable ALLOCATION_CONFIGURATION_DELAY;

    /// @notice Delay before slasher changes take effect.
    /// @dev Currently set to the same value as ALLOCATION_CONFIGURATION_DELAY.
    uint32 public immutable SLASHER_CONFIGURATION_DELAY;

    // Mutatables

    /// AVS => OPERATOR SET

    /// @dev Contains the AVS's configured registrar contract that handles registration/deregistration
    /// Note: if set to 0, defaults to the AVS's address
    mapping(address avs => IAVSRegistrar) internal _avsRegistrar;

    /// @dev Lists the operator set ids an AVS has created
    mapping(address avs => EnumerableSet.UintSet) internal _operatorSets;

    /// @dev Lists the strategies an AVS supports for an operator set
    mapping(bytes32 operatorSetKey => EnumerableSet.AddressSet) internal _operatorSetStrategies;

    /// @dev Lists the members of an AVS's operator set
    mapping(bytes32 operatorSetKey => EnumerableSet.AddressSet) internal _operatorSetMembers;

    /// OPERATOR => OPERATOR SET (REGISTRATION/DEREGISTRATION)

    /// @notice Returns the allocation delay info for each `operator`; the delay and whether or not it's previously been set.
    mapping(address operator => IAllocationManagerTypes.AllocationDelayInfo) internal _allocationDelayInfo;

    /// @dev Lists the operator sets the operator is registered for. Note that an operator
    /// can be registered without allocated stake. Likewise, an operator can allocate
    /// without being registered.
    mapping(address operator => EnumerableSet.Bytes32Set) internal registeredSets;

    /// @dev Lists the operator sets the operator has outstanding allocations in.
    mapping(address operator => EnumerableSet.Bytes32Set) internal allocatedSets;

    /// @dev Contains the operator's registration status for an operator set.
    mapping(address operator => mapping(bytes32 operatorSetKey => IAllocationManagerTypes.RegistrationStatus)) internal
        registrationStatus;

    /// @dev For an operator set, lists all strategies an operator has outstanding allocations from.
    mapping(address operator => mapping(bytes32 operatorSetKey => EnumerableSet.AddressSet)) internal
        allocatedStrategies;

    /// @dev For an operator set and strategy, the current allocated magnitude and any pending modification
    mapping(
        address operator
            => mapping(bytes32 operatorSetKey => mapping(IStrategy strategy => IAllocationManagerTypes.Allocation))
    ) internal allocations;

    /// OPERATOR => STRATEGY (MAX/USED AND DEALLOCATIONS)

    /// @dev Contains a history of the operator's maximum magnitude for a given strategy
    mapping(address operator => mapping(IStrategy strategy => Snapshots.DefaultWadHistory)) internal
        _maxMagnitudeHistory;

    /// @dev For a strategy, contains the amount of magnitude an operator has allocated to operator sets
    mapping(address operator => mapping(IStrategy strategy => uint64)) internal encumberedMagnitude;

    /// @dev For a strategy, keeps an ordered queue of operator sets that have pending deallocations
    /// These must be completed in order to free up magnitude for future allocation
    mapping(address operator => mapping(IStrategy strategy => DoubleEndedQueue.Bytes32Deque)) internal
        deallocationQueue;

    /// @dev Lists the AVSs who has registered metadata and claimed itself as an AVS
    /// @notice bool is not used and is always true if the avs has registered metadata
    mapping(address avs => bool) internal _avsRegisteredMetadata;

    /// @notice Returns the number of slashes for a given operator set.
    /// @dev This is also used as a unique slash identifier.
    /// @dev This tracks the number of slashes after the redistribution release.
    mapping(bytes32 operatorSetKey => uint256 slashId) internal _slashIds;

    /// @notice Returns the address where slashed funds will be sent for a given operator set.
    /// @dev For redistributing Operator Sets, returns the configured redistribution address set during Operator Set creation.
    ///      For non-redistributing or non-existing operator sets, the public getter for this function `getRedistributionRecipient`
    ///      returns `DEFAULT_BURN_ADDRESS`
    mapping(bytes32 operatorSetKey => address redistributionAddr) internal _redistributionRecipients;

    /// @notice Returns the address that can slash a given operator set.
    mapping(bytes32 operatorSetKey => SlasherParams params) internal _slashers;

    // Construction

    constructor(
        IDelegationManager _delegation,
        IStrategy _eigenStrategy,
        uint32 _DEALLOCATION_DELAY,
        uint32 _ALLOCATION_CONFIGURATION_DELAY
    ) {
        delegation = _delegation;
        eigenStrategy = _eigenStrategy;
        DEALLOCATION_DELAY = _DEALLOCATION_DELAY;
        ALLOCATION_CONFIGURATION_DELAY = _ALLOCATION_CONFIGURATION_DELAY;
        SLASHER_CONFIGURATION_DELAY = _ALLOCATION_CONFIGURATION_DELAY;
    }

    /// @dev This empty reserved space is put in place to allow future versions to add new
    /// variables without shifting down storage in the inheritance chain.
    /// See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
    uint256[33] private __gap;
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping(bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            if (lastIndex != toDeleteIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the last value to the index where the value to delete is
                set._values[toDeleteIndex] = lastValue;
                // Update the index for the moved value
                set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/DoubleEndedQueue.sol)
pragma solidity ^0.8.4;

import "../math/SafeCast.sol";

/**
 * @dev A sequence of items with the ability to efficiently push and pop items (i.e. insert and remove) on both ends of
 * the sequence (called front and back). Among other access patterns, it can be used to implement efficient LIFO and
 * FIFO queues. Storage use is optimized, and all operations are O(1) constant time. This includes {clear}, given that
 * the existing queue contents are left in storage.
 *
 * The struct is called `Bytes32Deque`. Other types can be cast to and from `bytes32`. This data structure can only be
 * used in storage, and not in memory.
 * ```solidity
 * DoubleEndedQueue.Bytes32Deque queue;
 * ```
 *
 * _Available since v4.6._
 */
library DoubleEndedQueue {
    /**
     * @dev An operation (e.g. {front}) couldn't be completed due to the queue being empty.
     */
    error Empty();

    /**
     * @dev An operation (e.g. {at}) couldn't be completed due to an index being out of bounds.
     */
    error OutOfBounds();

    /**
     * @dev Indices are signed integers because the queue can grow in any direction. They are 128 bits so begin and end
     * are packed in a single storage slot for efficient access. Since the items are added one at a time we can safely
     * assume that these 128-bit indices will not overflow, and use unchecked arithmetic.
     *
     * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to
     * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and
     * lead to unexpected behavior.
     *
     * Indices are in the range [begin, end) which means the first item is at data[begin] and the last item is at
     * data[end - 1].
     */
    struct Bytes32Deque {
        int128 _begin;
        int128 _end;
        mapping(int128 => bytes32) _data;
    }

    /**
     * @dev Inserts an item at the end of the queue.
     */
    function pushBack(Bytes32Deque storage deque, bytes32 value) internal {
        int128 backIndex = deque._end;
        deque._data[backIndex] = value;
        unchecked {
            deque._end = backIndex + 1;
        }
    }

    /**
     * @dev Removes the item at the end of the queue and returns it.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function popBack(Bytes32Deque storage deque) internal returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 backIndex;
        unchecked {
            backIndex = deque._end - 1;
        }
        value = deque._data[backIndex];
        delete deque._data[backIndex];
        deque._end = backIndex;
    }

    /**
     * @dev Inserts an item at the beginning of the queue.
     */
    function pushFront(Bytes32Deque storage deque, bytes32 value) internal {
        int128 frontIndex;
        unchecked {
            frontIndex = deque._begin - 1;
        }
        deque._data[frontIndex] = value;
        deque._begin = frontIndex;
    }

    /**
     * @dev Removes the item at the beginning of the queue and returns it.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function popFront(Bytes32Deque storage deque) internal returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 frontIndex = deque._begin;
        value = deque._data[frontIndex];
        delete deque._data[frontIndex];
        unchecked {
            deque._begin = frontIndex + 1;
        }
    }

    /**
     * @dev Returns the item at the beginning of the queue.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function front(Bytes32Deque storage deque) internal view returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 frontIndex = deque._begin;
        return deque._data[frontIndex];
    }

    /**
     * @dev Returns the item at the end of the queue.
     *
     * Reverts with `Empty` if the queue is empty.
     */
    function back(Bytes32Deque storage deque) internal view returns (bytes32 value) {
        if (empty(deque)) revert Empty();
        int128 backIndex;
        unchecked {
            backIndex = deque._end - 1;
        }
        return deque._data[backIndex];
    }

    /**
     * @dev Return the item at a position in the queue given by `index`, with the first item at 0 and last item at
     * `length(deque) - 1`.
     *
     * Reverts with `OutOfBounds` if the index is out of bounds.
     */
    function at(Bytes32Deque storage deque, uint256 index) internal view returns (bytes32 value) {
        // int256(deque._begin) is a safe upcast
        int128 idx = SafeCast.toInt128(int256(deque._begin) + SafeCast.toInt256(index));
        if (idx >= deque._end) revert OutOfBounds();
        return deque._data[idx];
    }

    /**
     * @dev Resets the queue back to being empty.
     *
     * NOTE: The current items are left behind in storage. This does not affect the functioning of the queue, but misses
     * out on potential gas refunds.
     */
    function clear(Bytes32Deque storage deque) internal {
        deque._begin = 0;
        deque._end = 0;
    }

    /**
     * @dev Returns the number of items in the queue.
     */
    function length(Bytes32Deque storage deque) internal view returns (uint256) {
        // The interface preserves the invariant that begin <= end so we assume this will not overflow.
        // We also assume there are at most int256.max items in the queue.
        unchecked {
            return uint256(int256(deque._end) - int256(deque._begin));
        }
    }

    /**
     * @dev Returns true if the queue is empty.
     */
    function empty(Bytes32Deque storage deque) internal view returns (bool) {
        return deque._end <= deque._begin;
    }
}

File 5 of 19 : IAllocationManager.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

import {OperatorSet} from "../libraries/OperatorSetLib.sol";
import "./IDelegationManager.sol";
import "./IPauserRegistry.sol";
import "./IPausable.sol";
import "./IStrategy.sol";
import "./IAVSRegistrar.sol";

interface IAllocationManagerErrors {
    /// Input Validation
    /// @dev Thrown when `wadToSlash` is zero or greater than 1e18
    error InvalidWadToSlash();
    /// @dev Thrown when two array parameters have mismatching lengths.
    error InputArrayLengthMismatch();
    /// @dev Thrown when the AVSRegistrar is not correctly configured to prevent an AVSRegistrar contract
    /// from being used with the wrong AVS
    error InvalidAVSRegistrar();
    /// @dev Thrown when an invalid strategy is provided.
    error InvalidStrategy();
    /// @dev Thrown when an invalid redistribution recipient is provided.
    error InvalidRedistributionRecipient();
    /// @dev Thrown when an operatorSet is already migrated
    error OperatorSetAlreadyMigrated();

    /// Caller

    /// @dev Thrown when caller is not authorized to call a function.
    error InvalidCaller();

    /// Operator Status

    /// @dev Thrown when an invalid operator is provided.
    error InvalidOperator();
    /// @dev Thrown when an invalid avs whose metadata is not registered is provided.
    error NonexistentAVSMetadata();
    /// @dev Thrown when an operator's allocation delay has yet to be set.
    error UninitializedAllocationDelay();
    /// @dev Thrown when attempting to slash an operator when they are not slashable.
    error OperatorNotSlashable();
    /// @dev Thrown when trying to add an operator to a set they are already a member of
    error AlreadyMemberOfSet();
    /// @dev Thrown when trying to slash/remove an operator from a set they are not a member of
    error NotMemberOfSet();

    /// Operator Set Status

    /// @dev Thrown when an invalid operator set is provided.
    error InvalidOperatorSet();
    /// @dev Thrown when provided `strategies` are not in ascending order.
    error StrategiesMustBeInAscendingOrder();
    /// @dev Thrown when trying to add a strategy to an operator set that already contains it.
    error StrategyAlreadyInOperatorSet();
    /// @dev Thrown when a strategy is referenced that does not belong to an operator set.
    error StrategyNotInOperatorSet();

    /// Modifying Allocations

    /// @dev Thrown when an operator attempts to set their allocation for an operatorSet to the same value
    error SameMagnitude();
    /// @dev Thrown when an allocation is attempted for a given operator when they have pending allocations or deallocations.
    error ModificationAlreadyPending();
    /// @dev Thrown when an allocation is attempted that exceeds a given operators total allocatable magnitude.
    error InsufficientMagnitude();

    /// SlasherStatus

    /// @dev Thrown when an operator set does not have a slasher set
    error SlasherNotSet();
}

interface IAllocationManagerTypes {
    /// @notice Defines allocation information from a strategy to an operator set, for an operator
    /// @param currentMagnitude the current magnitude allocated from the strategy to the operator set
    /// @param pendingDiff a pending change in magnitude, if it exists (0 otherwise)
    /// @param effectBlock the block at which the pending magnitude diff will take effect
    struct Allocation {
        uint64 currentMagnitude;
        int128 pendingDiff;
        uint32 effectBlock;
    }

    /// @notice Slasher configuration for an operator set.
    /// @param slasher The current effective slasher address. Updated immediately when instantEffectBlock=true
    ///        (e.g., during operator set creation or migration).
    /// @param pendingSlasher The slasher address that will become effective at effectBlock.
    /// @param effectBlock The block number at which pendingSlasher becomes the effective slasher.
    /// @dev It is not possible for the slasher to be the 0 address, which is used to denote if the slasher is not set
    struct SlasherParams {
        address slasher;
        address pendingSlasher;
        uint32 effectBlock;
    }

    /// @notice Allocation delay configuration for an operator.
    /// @param delay The current effective allocation delay. Updated immediately for newly registered operators.
    /// @param isSet Whether the allocation delay has been configured. True immediately for newly registered operators.
    /// @param pendingDelay The allocation delay that will become effective at effectBlock.
    /// @param effectBlock The block number at which pendingDelay becomes the effective delay.
    struct AllocationDelayInfo {
        uint32 delay;
        bool isSet;
        uint32 pendingDelay;
        uint32 effectBlock;
    }

    /// @notice Contains registration details for an operator pertaining to an operator set
    /// @param registered Whether the operator is currently registered for the operator set
    /// @param slashableUntil If the operator is not registered, they are still slashable until
    /// this block is reached.
    struct RegistrationStatus {
        bool registered;
        uint32 slashableUntil;
    }

    /// @notice Contains allocation info for a specific strategy
    /// @param maxMagnitude the maximum magnitude that can be allocated between all operator sets
    /// @param encumberedMagnitude the currently-allocated magnitude for the strategy
    struct StrategyInfo {
        uint64 maxMagnitude;
        uint64 encumberedMagnitude;
    }

    /// @notice Struct containing parameters to slashing
    /// @param operator the address to slash
    /// @param operatorSetId the ID of the operatorSet the operator is being slashed on behalf of
    /// @param strategies the set of strategies to slash
    /// @param wadsToSlash the parts in 1e18 to slash, this will be proportional to the operator's
    /// slashable stake allocation for the operatorSet
    /// @param description the description of the slashing provided by the AVS for legibility
    struct SlashingParams {
        address operator;
        uint32 operatorSetId;
        IStrategy[] strategies;
        uint256[] wadsToSlash;
        string description;
    }

    /// @notice struct used to modify the allocation of slashable magnitude to an operator set
    /// @param operatorSet the operator set to modify the allocation for
    /// @param strategies the strategies to modify allocations for
    /// @param newMagnitudes the new magnitude to allocate for each strategy to this operator set
    struct AllocateParams {
        OperatorSet operatorSet;
        IStrategy[] strategies;
        uint64[] newMagnitudes;
    }

    /// @notice Parameters used to register for an AVS's operator sets
    /// @param avs the AVS being registered for
    /// @param operatorSetIds the operator sets within the AVS to register for
    /// @param data extra data to be passed to the AVS to complete registration
    struct RegisterParams {
        address avs;
        uint32[] operatorSetIds;
        bytes data;
    }

    /// @notice Parameters used to deregister from an AVS's operator sets
    /// @param operator the operator being deregistered
    /// @param avs the avs being deregistered from
    /// @param operatorSetIds the operator sets within the AVS being deregistered from
    struct DeregisterParams {
        address operator;
        address avs;
        uint32[] operatorSetIds;
    }

    /// @notice Parameters used by an AVS to create new operator sets
    /// @param operatorSetId the id of the operator set to create
    /// @param strategies the strategies to add as slashable to the operator set
    /// @dev This struct and its associated method will be deprecated in Early Q2 2026
    struct CreateSetParams {
        uint32 operatorSetId;
        IStrategy[] strategies;
    }
    /// @notice Parameters used by an AVS to create new operator sets
    /// @param operatorSetId the id of the operator set to create
    /// @param strategies the strategies to add as slashable to the operator set
    /// @param slasher the address that will be the slasher for the operator set

    struct CreateSetParamsV2 {
        uint32 operatorSetId;
        IStrategy[] strategies;
        address slasher;
    }
}

interface IAllocationManagerEvents is IAllocationManagerTypes {
    /// @notice Emitted when operator updates their allocation delay.
    event AllocationDelaySet(address operator, uint32 delay, uint32 effectBlock);

    /// @notice Emitted when an operator set's slasher is updated.
    event SlasherUpdated(OperatorSet operatorSet, address slasher, uint32 effectBlock);

    /// @notice Emitted when an operator set's slasher is migrated.
    event SlasherMigrated(OperatorSet operatorSet, address slasher);

    /// @notice Emitted when an operator's magnitude is updated for a given operatorSet and strategy
    event AllocationUpdated(
        address operator,
        OperatorSet operatorSet,
        IStrategy strategy,
        uint64 magnitude,
        uint32 effectBlock
    );

    /// @notice Emitted when operator's encumbered magnitude is updated for a given strategy
    event EncumberedMagnitudeUpdated(address operator, IStrategy strategy, uint64 encumberedMagnitude);

    /// @notice Emitted when an operator's max magnitude is updated for a given strategy
    event MaxMagnitudeUpdated(address operator, IStrategy strategy, uint64 maxMagnitude);

    /// @notice Emitted when an operator is slashed by an operator set for a strategy
    /// `wadSlashed` is the proportion of the operator's total delegated stake that was slashed
    event OperatorSlashed(
        address operator,
        OperatorSet operatorSet,
        IStrategy[] strategies,
        uint256[] wadSlashed,
        string description
    );

    /// @notice Emitted when an AVS configures the address that will handle registration/deregistration
    event AVSRegistrarSet(address avs, IAVSRegistrar registrar);

    /// @notice Emitted when an AVS updates their metadata URI (Uniform Resource Identifier).
    /// @dev The URI is never stored; it is simply emitted through an event for off-chain indexing.
    event AVSMetadataURIUpdated(address indexed avs, string metadataURI);

    /// @notice Emitted when an operator set is created by an AVS.
    event OperatorSetCreated(OperatorSet operatorSet);

    /// @notice Emitted when an operator is added to an operator set.
    event OperatorAddedToOperatorSet(address indexed operator, OperatorSet operatorSet);

    /// @notice Emitted when an operator is removed from an operator set.
    event OperatorRemovedFromOperatorSet(address indexed operator, OperatorSet operatorSet);

    /// @notice Emitted when a redistributing operator set is created by an AVS.
    event RedistributionAddressSet(OperatorSet operatorSet, address redistributionRecipient);

    /// @notice Emitted when a strategy is added to an operator set.
    event StrategyAddedToOperatorSet(OperatorSet operatorSet, IStrategy strategy);

    /// @notice Emitted when a strategy is removed from an operator set.
    event StrategyRemovedFromOperatorSet(OperatorSet operatorSet, IStrategy strategy);
}

interface IAllocationManagerStorage is IAllocationManagerEvents {
    /// @notice The DelegationManager contract for EigenLayer
    function delegation() external view returns (IDelegationManager);

    /// @notice The Eigen strategy contract
    /// @dev Cannot be added to redistributing operator sets
    function eigenStrategy() external view returns (IStrategy);

    /// @notice Returns the number of blocks between an operator deallocating magnitude and the magnitude becoming
    /// unslashable and then being able to be reallocated to another operator set. Note that unlike the allocation delay
    /// which is configurable by the operator, the DEALLOCATION_DELAY is globally fixed and cannot be changed.
    function DEALLOCATION_DELAY() external view returns (uint32 delay);

    /// @notice Delay before alloaction delay modifications take effect.
    function ALLOCATION_CONFIGURATION_DELAY() external view returns (uint32);

    /// @notice Delay before slasher changes take effect.
    /// @dev Currently set to the same value as ALLOCATION_CONFIGURATION_DELAY.
    function SLASHER_CONFIGURATION_DELAY() external view returns (uint32);
}

interface IAllocationManagerActions is IAllocationManagerErrors, IAllocationManagerEvents, IAllocationManagerStorage {
    /// @dev Initializes the initial owner and paused status.
    function initialize(
        uint256 initialPausedStatus
    ) external;

    /// @notice Called by an AVS to slash an operator in a given operator set. The operator must be registered
    /// and have slashable stake allocated to the operator set.
    ///
    /// @param avs The AVS address initiating the slash.
    /// @param params The slashing parameters, containing:
    ///  - operator: The operator to slash.
    ///  - operatorSetId: The ID of the operator set the operator is being slashed from.
    ///  - strategies: Array of strategies to slash allocations from (must be in ascending order).
    ///  - wadsToSlash: Array of proportions to slash from each strategy (must be between 0 and 1e18).
    ///  - description: Description of why the operator was slashed.
    ///
    /// @return slashId The ID of the slash.
    /// @return shares The amount of shares that were slashed for each strategy.
    ///
    /// @dev For each strategy:
    ///      1. Reduces the operator's current allocation magnitude by wadToSlash proportion.
    ///      2. Reduces the strategy's max and encumbered magnitudes proportionally.
    ///      3. If there is a pending deallocation, reduces it proportionally.
    ///      4. Updates the operator's shares in the DelegationManager.
    ///
    /// @dev Small slashing amounts may not result in actual token burns due to
    ///      rounding, which will result in small amounts of tokens locked in the contract
    ///      rather than fully burning through the burn mechanism.
    function slashOperator(
        address avs,
        SlashingParams calldata params
    ) external returns (uint256 slashId, uint256[] memory shares);

    /// @notice Modifies the proportions of slashable stake allocated to an operator set from a list of strategies
    /// Note that deallocations remain slashable for DEALLOCATION_DELAY blocks therefore when they are cleared they may
    /// free up less allocatable magnitude than initially deallocated.
    /// @param operator the operator to modify allocations for
    /// @param params array of magnitude adjustments for one or more operator sets
    /// @dev Updates encumberedMagnitude for the updated strategies
    function modifyAllocations(
        address operator,
        AllocateParams[] calldata params
    ) external;

    /// @notice This function takes a list of strategies and for each strategy, removes from the deallocationQueue
    /// all clearable deallocations up to max `numToClear` number of deallocations, updating the encumberedMagnitude
    /// of the operator as needed.
    ///
    /// @param operator address to clear deallocations for
    /// @param strategies a list of strategies to clear deallocations for
    /// @param numToClear a list of number of pending deallocations to clear for each strategy
    ///
    /// @dev can be called permissionlessly by anyone
    function clearDeallocationQueue(
        address operator,
        IStrategy[] calldata strategies,
        uint16[] calldata numToClear
    ) external;

    /// @notice Allows an operator to register for one or more operator sets for an AVS. If the operator
    /// has any stake allocated to these operator sets, it immediately becomes slashable.
    /// @dev After registering within the ALM, this method calls the AVS Registrar's `IAVSRegistrar.
    /// registerOperator` method to complete registration. This call MUST succeed in order for
    /// registration to be successful.
    function registerForOperatorSets(
        address operator,
        RegisterParams calldata params
    ) external;

    /// @notice Allows an operator or AVS to deregister the operator from one or more of the AVS's operator sets.
    /// If the operator has any slashable stake allocated to the AVS, it remains slashable until the
    /// DEALLOCATION_DELAY has passed.
    /// @dev After deregistering within the ALM, this method calls the AVS Registrar's `IAVSRegistrar.
    /// deregisterOperator` method to complete deregistration. This call MUST succeed in order for
    /// deregistration to be successful.
    function deregisterFromOperatorSets(
        DeregisterParams calldata params
    ) external;

    /// @notice Called by the delegation manager OR an operator to set an operator's allocation delay.
    /// This is set when the operator first registers, and is the number of blocks between an operator
    /// allocating magnitude to an operator set, and the magnitude becoming slashable.
    /// @param operator The operator to set the delay on behalf of.
    /// @param delay the allocation delay in blocks
    /// @dev When the delay is set for a newly-registered operator (via the `DelegationManager.registerAsOperator` method),
    /// the delay will take effect immediately, allowing for operators to allocate slashable stake immediately.
    /// Else, the delay will take effect after `ALLOCATION_CONFIGURATION_DELAY` blocks.
    function setAllocationDelay(
        address operator,
        uint32 delay
    ) external;

    /// @notice Called by an AVS to configure the address that is called when an operator registers
    /// or is deregistered from the AVS's operator sets. If not set (or set to 0), defaults
    /// to the AVS's address.
    /// @param registrar the new registrar address
    function setAVSRegistrar(
        address avs,
        IAVSRegistrar registrar
    ) external;

    ///  @notice Called by an AVS to emit an `AVSMetadataURIUpdated` event indicating the information has updated.
    ///
    ///  @param metadataURI The URI for metadata associated with an AVS.
    ///
    ///  @dev Note that the `metadataURI` is *never stored* and is only emitted in the `AVSMetadataURIUpdated` event.
    function updateAVSMetadataURI(
        address avs,
        string calldata metadataURI
    ) external;

    /// @notice Allows an AVS to create new operator sets, defining strategies that the operator set uses
    /// @dev Upon creation, the address that can slash the operatorSet is the `avs` address. If you would like to use a different address,
    ///      use the `createOperatorSets` method which takes in `CreateSetParamsV2` instead.
    /// @dev THIS FUNCTION WILL BE DEPRECATED IN EARLY Q2 2026 IN FAVOR OF `createOperatorSets`, WHICH TAKES IN `CreateSetParamsV2`
    /// @dev Reverts for:
    ///      - NonexistentAVSMetadata: The AVS metadata is not registered
    ///      - InvalidOperatorSet: The operatorSet already exists
    ///      - InputAddressZero: The slasher is the zero address
    function createOperatorSets(
        address avs,
        CreateSetParams[] calldata params
    ) external;

    /// @notice Allows an AVS to create new operator sets, defining strategies that the operator set uses
    /// @dev Reverts for:
    ///      - NonexistentAVSMetadata: The AVS metadata is not registered
    ///      - InvalidOperatorSet: The operatorSet already exists
    ///      - InputAddressZero: The slasher is the zero address
    function createOperatorSets(
        address avs,
        CreateSetParamsV2[] calldata params
    ) external;

    /// @notice Allows an AVS to create new Redistribution operator sets.
    /// @param avs The AVS creating the new operator sets.
    /// @param params An array of operator set creation parameters.
    /// @param redistributionRecipients An array of addresses that will receive redistributed funds when operators are slashed.
    /// @dev Same logic as `createOperatorSets`, except `redistributionRecipients` corresponding to each operator set are stored.
    ///      Additionally, emits `RedistributionOperatorSetCreated` event instead of `OperatorSetCreated` for each created operator set.
    /// @dev The address that can slash the operatorSet is the `avs` address. If you would like to use a different address,
    ///      use the `createOperatorSets` method which takes in `CreateSetParamsV2` instead.
    /// @dev THIS FUNCTION WILL BE DEPRECATED IN EARLY Q2 2026 IN FAVOR OF `createRedistributingOperatorSets` WHICH TAKES IN `CreateSetParamsV2`
    /// @dev Reverts for:
    ///      - InputArrayLengthMismatch: The length of the params array does not match the length of the redistributionRecipients array
    ///      - NonexistentAVSMetadata: The AVS metadata is not registered
    ///      - InputAddressZero: The redistribution recipient is the zero address
    ///      - InvalidRedistributionRecipient: The redistribution recipient is the zero address or the default burn address
    ///      - InvalidOperatorSet: The operatorSet already exists
    ///      - InvalidStrategy: The strategy is the BEACONCHAIN_ETH_STRAT or the EIGEN strategy
    ///      - InputAddressZero: The slasher is the zero address
    function createRedistributingOperatorSets(
        address avs,
        CreateSetParams[] calldata params,
        address[] calldata redistributionRecipients
    ) external;

    /// @notice Allows an AVS to create new Redistribution operator sets.
    /// @param avs The AVS creating the new operator sets.
    /// @param params An array of operator set creation parameters.
    /// @param redistributionRecipients An array of addresses that will receive redistributed funds when operators are slashed.
    /// @dev Same logic as `createOperatorSets`, except `redistributionRecipients` corresponding to each operator set are stored.
    ///      Additionally, emits `RedistributionOperatorSetCreated` event instead of `OperatorSetCreated` for each created operator set.
    /// @dev Reverts for:
    ///      - InputArrayLengthMismatch: The length of the params array does not match the length of the redistributionRecipients array
    ///      - NonexistentAVSMetadata: The AVS metadata is not registered
    ///      - InputAddressZero: The redistribution recipient is the zero address
    ///      - InvalidRedistributionRecipient: The redistribution recipient is the zero address or the default burn address
    ///      - InvalidOperatorSet: The operatorSet already exists
    ///      - InvalidStrategy: The strategy is the BEACONCHAIN_ETH_STRAT or the EIGEN strategy
    ///      - InputAddressZero: The slasher is the zero address
    function createRedistributingOperatorSets(
        address avs,
        CreateSetParamsV2[] calldata params,
        address[] calldata redistributionRecipients
    ) external;

    /// @notice Allows an AVS to add strategies to an operator set
    /// @dev Strategies MUST NOT already exist in the operator set
    /// @dev If the operatorSet is redistributing, the `BEACONCHAIN_ETH_STRAT` may not be added, since redistribution is not supported for native eth
    /// @param avs the avs to set strategies for
    /// @param operatorSetId the operator set to add strategies to
    /// @param strategies the strategies to add
    function addStrategiesToOperatorSet(
        address avs,
        uint32 operatorSetId,
        IStrategy[] calldata strategies
    ) external;

    /// @notice Allows an AVS to remove strategies from an operator set
    /// @dev Strategies MUST already exist in the operator set
    /// @param avs the avs to remove strategies for
    /// @param operatorSetId the operator set to remove strategies from
    /// @param strategies the strategies to remove
    function removeStrategiesFromOperatorSet(
        address avs,
        uint32 operatorSetId,
        IStrategy[] calldata strategies
    ) external;

    /// @notice Allows an AVS to update the slasher for an operator set
    /// @param operatorSet the operator set to update the slasher for
    /// @param slasher the new slasher
    /// @dev The new slasher will take effect after `SLASHER_CONFIGURATION_DELAY` blocks.
    /// @dev No-op if the proposed slasher is already pending and hasn't taken effect yet (delay countdown is not restarted).
    /// @dev The slasher can only be updated if it has already been set. The slasher is set either on operatorSet creation or,
    ///      for operatorSets created prior to v1.9.0, via `migrateSlashers`
    /// @dev Reverts for:
    ///      - InvalidCaller: The caller cannot update the slasher for the operator set (set via the `PermissionController`)
    ///      - InvalidOperatorSet: The operator set does not exist
    ///      - SlasherNotSet: The slasher has not been set yet
    ///      - InputAddressZero: The slasher is the zero address
    function updateSlasher(
        OperatorSet memory operatorSet,
        address slasher
    ) external;

    /// @notice Allows any address to migrate the slasher from the permission controller to the ALM
    /// @param operatorSets the list of operator sets to migrate the slasher for
    /// @dev This function is used to migrate the slasher from the permission controller to the ALM for operatorSets created prior to `v1.9.0`
    /// @dev Migrates based on the following rules:
    ///      - If there is no slasher set or the slasher in the `PermissionController`is the 0 address, the AVS address will be set as the slasher
    ///      - If there are multiple slashers set in the `PermissionController`, the first address will be set as the slasher
    /// @dev A migration can only be completed once for a given operatorSet
    /// @dev This function will be deprecated in Early Q2 2026. EigenLabs will migrate the slasher for all operatorSets created prior to `v1.9.0`
    /// @dev This function does not revert to allow for simpler offchain calling. It will no-op if:
    ///      - The operator set does not exist
    ///      - The slasher has already been set, either via migration or creation of the operatorSet
    /// @dev WARNING: Gas cost is O(appointees) per operator set due to `PermissionController.getAppointees()` call.
    ///      May exceed block gas limit for AVSs with large appointee sets. Consider batching operator sets if needed.
    function migrateSlashers(
        OperatorSet[] memory operatorSets
    ) external;
}

interface IAllocationManagerView is IAllocationManagerErrors, IAllocationManagerEvents, IAllocationManagerStorage {
    ///
    ///                         VIEW FUNCTIONS
    ///
    /// @notice Returns the number of operator sets for the AVS
    /// @param avs the AVS to query
    function getOperatorSetCount(
        address avs
    ) external view returns (uint256);

    /// @notice Returns the list of operator sets the operator has current or pending allocations/deallocations in
    /// @param operator the operator to query
    /// @return the list of operator sets the operator has current or pending allocations/deallocations in
    function getAllocatedSets(
        address operator
    ) external view returns (OperatorSet[] memory);

    /// @notice Returns the list of strategies an operator has current or pending allocations/deallocations from
    /// given a specific operator set.
    /// @param operator the operator to query
    /// @param operatorSet the operator set to query
    /// @return the list of strategies
    function getAllocatedStrategies(
        address operator,
        OperatorSet memory operatorSet
    ) external view returns (IStrategy[] memory);

    /// @notice Returns the current/pending stake allocation an operator has from a strategy to an operator set
    /// @param operator the operator to query
    /// @param operatorSet the operator set to query
    /// @param strategy the strategy to query
    /// @return the current/pending stake allocation
    function getAllocation(
        address operator,
        OperatorSet memory operatorSet,
        IStrategy strategy
    ) external view returns (Allocation memory);

    /// @notice Returns the current/pending stake allocations for multiple operators from a strategy to an operator set
    /// @param operators the operators to query
    /// @param operatorSet the operator set to query
    /// @param strategy the strategy to query
    /// @return each operator's allocation
    function getAllocations(
        address[] memory operators,
        OperatorSet memory operatorSet,
        IStrategy strategy
    ) external view returns (Allocation[] memory);

    /// @notice Given a strategy, returns a list of operator sets and corresponding stake allocations.
    /// @dev Note that this returns a list of ALL operator sets the operator has allocations in. This means
    /// some of the returned allocations may be zero.
    /// @param operator the operator to query
    /// @param strategy the strategy to query
    /// @return the list of all operator sets the operator has allocations for
    /// @return the corresponding list of allocations from the specific `strategy`
    function getStrategyAllocations(
        address operator,
        IStrategy strategy
    ) external view returns (OperatorSet[] memory, Allocation[] memory);

    /// @notice For a strategy, get the amount of magnitude that is allocated across one or more operator sets
    /// @param operator the operator to query
    /// @param strategy the strategy to get allocatable magnitude for
    /// @return currently allocated magnitude
    function getEncumberedMagnitude(
        address operator,
        IStrategy strategy
    ) external view returns (uint64);

    /// @notice For a strategy, get the amount of magnitude not currently allocated to any operator set
    /// @param operator the operator to query
    /// @param strategy the strategy to get allocatable magnitude for
    /// @return magnitude available to be allocated to an operator set
    function getAllocatableMagnitude(
        address operator,
        IStrategy strategy
    ) external view returns (uint64);

    /// @notice Returns the maximum magnitude an operator can allocate for the given strategy
    /// @dev The max magnitude of an operator starts at WAD (1e18), and is decreased anytime
    /// the operator is slashed. This value acts as a cap on the max magnitude of the operator.
    /// @param operator the operator to query
    /// @param strategy the strategy to get the max magnitude for
    /// @return the max magnitude for the strategy
    function getMaxMagnitude(
        address operator,
        IStrategy strategy
    ) external view returns (uint64);

    /// @notice Returns the maximum magnitude an operator can allocate for the given strategies
    /// @dev The max magnitude of an operator starts at WAD (1e18), and is decreased anytime
    /// the operator is slashed. This value acts as a cap on the max magnitude of the operator.
    /// @param operator the operator to query
    /// @param strategies the strategies to get the max magnitudes for
    /// @return the max magnitudes for each strategy
    function getMaxMagnitudes(
        address operator,
        IStrategy[] calldata strategies
    ) external view returns (uint64[] memory);

    /// @notice Returns the maximum magnitudes each operator can allocate for the given strategy
    /// @dev The max magnitude of an operator starts at WAD (1e18), and is decreased anytime
    /// the operator is slashed. This value acts as a cap on the max magnitude of the operator.
    /// @param operators the operators to query
    /// @param strategy the strategy to get the max magnitudes for
    /// @return the max magnitudes for each operator
    function getMaxMagnitudes(
        address[] calldata operators,
        IStrategy strategy
    ) external view returns (uint64[] memory);

    /// @notice Returns the maximum magnitude an operator can allocate for the given strategies
    /// at a given block number
    /// @dev The max magnitude of an operator starts at WAD (1e18), and is decreased anytime
    /// the operator is slashed. This value acts as a cap on the max magnitude of the operator.
    /// @param operator the operator to query
    /// @param strategies the strategies to get the max magnitudes for
    /// @param blockNumber the blockNumber at which to check the max magnitudes
    /// @return the max magnitudes for each strategy
    function getMaxMagnitudesAtBlock(
        address operator,
        IStrategy[] calldata strategies,
        uint32 blockNumber
    ) external view returns (uint64[] memory);

    /// @notice Returns the time in blocks between an operator allocating slashable magnitude
    /// and the magnitude becoming slashable. If the delay has not been set, `isSet` will be false.
    /// @dev The operator must have a configured delay before allocating magnitude
    /// @param operator The operator to query
    /// @return isSet Whether the operator has configured a delay
    /// @return delay The time in blocks between allocating magnitude and magnitude becoming slashable
    function getAllocationDelay(
        address operator
    ) external view returns (bool isSet, uint32 delay);

    /// @notice Returns a list of all operator sets the operator is registered for
    /// @param operator The operator address to query.
    function getRegisteredSets(
        address operator
    ) external view returns (OperatorSet[] memory operatorSets);

    /// @notice Returns whether the operator is registered for the operator set
    /// @param operator The operator to query
    /// @param operatorSet The operator set to query
    function isMemberOfOperatorSet(
        address operator,
        OperatorSet memory operatorSet
    ) external view returns (bool);

    /// @notice Returns whether the operator set exists
    function isOperatorSet(
        OperatorSet memory operatorSet
    ) external view returns (bool);

    /// @notice Returns all the operators registered to an operator set
    /// @param operatorSet The operatorSet to query.
    function getMembers(
        OperatorSet memory operatorSet
    ) external view returns (address[] memory operators);

    /// @notice Returns the number of operators registered to an operatorSet.
    /// @param operatorSet The operatorSet to get the member count for
    function getMemberCount(
        OperatorSet memory operatorSet
    ) external view returns (uint256);

    /// @notice Returns the address that handles registration/deregistration for the AVS
    /// If not set, defaults to the input address (`avs`)
    function getAVSRegistrar(
        address avs
    ) external view returns (IAVSRegistrar);

    /// @notice Returns an array of strategies in the operatorSet.
    /// @param operatorSet The operatorSet to query.
    function getStrategiesInOperatorSet(
        OperatorSet memory operatorSet
    ) external view returns (IStrategy[] memory strategies);

    /// @notice Returns the minimum amount of stake that will be slashable as of some future block,
    /// according to each operator's allocation from each strategy to the operator set. Note that this function
    /// will return 0 for the slashable stake if the operator is not slashable at the time of the call.
    /// @dev This method queries actual delegated stakes in the DelegationManager and applies
    /// each operator's allocation to the stake to produce the slashable stake each allocation
    /// represents. This method does not consider slashable stake in the withdrawal queue even though there could be
    /// slashable stake in the queue.
    /// @dev This minimum takes into account `futureBlock`, and will omit any pending magnitude
    /// diffs that will not be in effect as of `futureBlock`. NOTE that in order to get the true
    /// minimum slashable stake as of some future block, `futureBlock` MUST be greater than block.number
    /// @dev NOTE that `futureBlock` should be fewer than `DEALLOCATION_DELAY` blocks in the future,
    /// or the values returned from this method may not be accurate due to deallocations.
    /// @param operatorSet the operator set to query
    /// @param operators the list of operators whose slashable stakes will be returned
    /// @param strategies the strategies that each slashable stake corresponds to
    /// @param futureBlock the block at which to get allocation information. Should be a future block.
    function getMinimumSlashableStake(
        OperatorSet memory operatorSet,
        address[] memory operators,
        IStrategy[] memory strategies,
        uint32 futureBlock
    ) external view returns (uint256[][] memory slashableStake);

    /// @notice Returns the current allocated stake, irrespective of the operator's slashable status for the operatorSet.
    /// @param operatorSet the operator set to query
    /// @param operators the operators to query
    /// @param strategies the strategies to query
    function getAllocatedStake(
        OperatorSet memory operatorSet,
        address[] memory operators,
        IStrategy[] memory strategies
    ) external view returns (uint256[][] memory slashableStake);

    /// @notice Returns whether an operator is slashable by an operator set.
    /// This returns true if the operator is registered or their slashableUntil block has not passed.
    /// This is because even when operators are deregistered, they still remain slashable for a period of time.
    /// @param operator the operator to check slashability for
    /// @param operatorSet the operator set to check slashability for
    function isOperatorSlashable(
        address operator,
        OperatorSet memory operatorSet
    ) external view returns (bool);

    /// @notice Returns the address that can slash a given operator set.
    /// @param operatorSet The operator set to query.
    /// @return The address that can slash the operator set. Returns `address(0)` if the operator set doesn't exist.
    /// @dev If there is a pending slasher that can be applied after the `effectBlock`, the pending slasher will be returned.
    function getSlasher(
        OperatorSet memory operatorSet
    ) external view returns (address);

    /// @notice Returns pending slasher for a given operator set.
    /// @param operatorSet The operator set to query.
    /// @return pendingSlasher The pending slasher for the operator set. Returns `address(0)` if there is no pending slasher or the operator set doesn't exist.
    /// @return effectBlock The block at which the pending slasher will take effect. Returns `0` if there is no pending slasher or the operator set doesn't exist.
    function getPendingSlasher(
        OperatorSet memory operatorSet
    ) external view returns (address pendingSlasher, uint32 effectBlock);

    /// @notice Returns the address where slashed funds will be sent for a given operator set.
    /// @param operatorSet The Operator Set to query.
    /// @return For redistributing Operator Sets, returns the configured redistribution address set during Operator Set creation.
    ///         For non-redistributing operator sets, returns the `DEFAULT_BURN_ADDRESS`.
    function getRedistributionRecipient(
        OperatorSet memory operatorSet
    ) external view returns (address);

    /// @notice Returns whether a given operator set supports redistribution
    /// or not when funds are slashed and burned from EigenLayer.
    /// @param operatorSet The Operator Set to query.
    /// @return For redistributing Operator Sets, returns true.
    ///         For non-redistributing Operator Sets, returns false.
    function isRedistributingOperatorSet(
        OperatorSet memory operatorSet
    ) external view returns (bool);

    /// @notice Returns the number of slashes for a given operator set.
    /// @param operatorSet The operator set to query.
    /// @return The number of slashes for the operator set.
    function getSlashCount(
        OperatorSet memory operatorSet
    ) external view returns (uint256);

    /// @notice Returns whether an operator is slashable by a redistributing operator set.
    /// @param operator The operator to query.
    function isOperatorRedistributable(
        address operator
    ) external view returns (bool);
}

interface IAllocationManager is IAllocationManagerActions, IAllocationManagerView, IPausable {}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin-upgrades/contracts/utils/math/MathUpgradeable.sol";

import "./SlashingLib.sol";

/// @title Library for handling snapshots as part of allocating and slashing.
/// @notice This library is using OpenZeppelin's CheckpointsUpgradeable library (v4.9.0)
/// and removes structs and functions that are unessential.
/// Interfaces and structs are renamed for clarity and usage.
/// Some additional functions have also been added for convenience.
/// @dev This library defines the `DefaultWadHistory` and `DefaultZeroHistory` struct, for snapshotting values as they change at different points in
/// time, and later looking up past values by block number. See {Votes} as an example.
///
/// To create a history of snapshots define a variable type `Snapshots.DefaultWadHistory` or `Snapshots.DefaultZeroHistory` in your contract,
/// and store a new snapshot for the current transaction block using the {push} function. If there is no history yet, the value is either WAD or 0,
/// depending on the type of History struct used. This is implemented because for the AllocationManager we want the
/// the default value to be WAD(1e18) but when used in the DelegationManager we want the default value to be 0.
///
/// _Available since v4.5._
library Snapshots {
    struct DefaultWadHistory {
        Snapshot[] _snapshots;
    }

    struct DefaultZeroHistory {
        Snapshot[] _snapshots;
    }

    struct Snapshot {
        uint32 _key;
        uint224 _value;
    }

    error InvalidSnapshotOrdering();

    /// @dev Pushes a (`key`, `value`) pair into a DefaultWadHistory so that it is stored as the snapshot.
    function push(
        DefaultWadHistory storage self,
        uint32 key,
        uint64 value
    ) internal {
        _insert(self._snapshots, key, value);
    }

    /// @dev Pushes a (`key`, `value`) pair into a DefaultZeroHistory so that it is stored as the snapshot.
    /// `value` is cast to uint224. Responsibility for the safety of this operation falls outside of this library.
    function push(
        DefaultZeroHistory storage self,
        uint32 key,
        uint256 value
    ) internal {
        _insert(self._snapshots, key, uint224(value));
    }

    /// @dev Return default value of WAD if there are no snapshots for DefaultWadHistory.
    /// This is used for looking up maxMagnitudes in the AllocationManager.
    function upperLookup(
        DefaultWadHistory storage self,
        uint32 key
    ) internal view returns (uint64) {
        return uint64(_upperLookup(self._snapshots, key, WAD));
    }

    /// @dev Return default value of 0 if there are no snapshots for DefaultZeroHistory.
    /// This is used for looking up cumulative scaled shares in the DelegationManager.
    function upperLookup(
        DefaultZeroHistory storage self,
        uint32 key
    ) internal view returns (uint256) {
        return _upperLookup(self._snapshots, key, 0);
    }

    /// @dev Returns the value in the most recent snapshot, or WAD if there are no snapshots.
    function latest(
        DefaultWadHistory storage self
    ) internal view returns (uint64) {
        return uint64(_latest(self._snapshots, WAD));
    }

    /// @dev Returns the value in the most recent snapshot, or 0 if there are no snapshots.
    function latest(
        DefaultZeroHistory storage self
    ) internal view returns (uint256) {
        return uint256(_latest(self._snapshots, 0));
    }

    /// @dev Returns the number of snapshots.
    function length(
        DefaultWadHistory storage self
    ) internal view returns (uint256) {
        return self._snapshots.length;
    }

    /// @dev Returns the number of snapshots.
    function length(
        DefaultZeroHistory storage self
    ) internal view returns (uint256) {
        return self._snapshots.length;
    }

    /// @dev Pushes a (`key`, `value`) pair into an ordered list of snapshots, either by inserting a new snapshot,
    /// or by updating the last one.
    function _insert(
        Snapshot[] storage self,
        uint32 key,
        uint224 value
    ) private {
        uint256 pos = self.length;

        if (pos > 0) {
            // Validate that inserted keys are always >= the previous key
            Snapshot memory last = _unsafeAccess(self, pos - 1);
            require(last._key <= key, InvalidSnapshotOrdering());

            // Update existing snapshot if `key` matches
            if (last._key == key) {
                _unsafeAccess(self, pos - 1)._value = value;
                return;
            }
        }

        // `key` was not in the list; push as a new entry
        self.push(Snapshot({_key: key, _value: value}));
    }

    /// @dev Returns the value in the last (most recent) snapshot with key lower or equal than the search key, or `defaultValue` if there is none.
    function _upperLookup(
        Snapshot[] storage snapshots,
        uint32 key,
        uint224 defaultValue
    ) private view returns (uint224) {
        uint256 len = snapshots.length;
        uint256 pos = _upperBinaryLookup(snapshots, key, 0, len);
        return pos == 0 ? defaultValue : _unsafeAccess(snapshots, pos - 1)._value;
    }

    /// @dev Returns the value in the most recent snapshot, or `defaultValue` if there are no snapshots.
    function _latest(
        Snapshot[] storage snapshots,
        uint224 defaultValue
    ) private view returns (uint224) {
        uint256 pos = snapshots.length;
        return pos == 0 ? defaultValue : _unsafeAccess(snapshots, pos - 1)._value;
    }

    /// @dev Return the index of the last (most recent) snapshot with key lower or equal than the search key, or `high` if there is none.
    /// `low` and `high` define a section where to do the search, with inclusive `low` and exclusive `high`.
    ///
    /// WARNING: `high` should not be greater than the array's length.
    function _upperBinaryLookup(
        Snapshot[] storage self,
        uint32 key,
        uint256 low,
        uint256 high
    ) private view returns (uint256) {
        while (low < high) {
            uint256 mid = MathUpgradeable.average(low, high);
            if (_unsafeAccess(self, mid)._key > key) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high;
    }

    /// @dev Access an element of the array without performing bounds check. The position is assumed to be within bounds.
    function _unsafeAccess(
        Snapshot[] storage self,
        uint256 pos
    ) private pure returns (Snapshot storage result) {
        assembly {
            mstore(0, self.slot)
            result.slot := add(keccak256(0, 0x20), pos)
        }
    }
}

File 7 of 19 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCast {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;

using OperatorSetLib for OperatorSet global;

/// @notice An operator set identified by the AVS address and an identifier
/// @param avs The address of the AVS this operator set belongs to
/// @param id The unique identifier for the operator set
struct OperatorSet {
    address avs;
    uint32 id;
}

library OperatorSetLib {
    function key(
        OperatorSet memory os
    ) internal pure returns (bytes32) {
        return bytes32(abi.encodePacked(os.avs, uint96(os.id)));
    }

    function decode(
        bytes32 _key
    ) internal pure returns (OperatorSet memory) {
        /// forgefmt: disable-next-item
        return OperatorSet({
            avs: address(uint160(uint256(_key) >> 96)),
            id: uint32(uint256(_key) & type(uint96).max)
        });
    }
}

File 9 of 19 : IDelegationManager.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

import "./IStrategy.sol";
import "./IPauserRegistry.sol";
import "./ISignatureUtilsMixin.sol";
import "../libraries/SlashingLib.sol";
import "../libraries/OperatorSetLib.sol";

interface IDelegationManagerErrors {
    /// @dev Thrown when caller is neither the StrategyManager or EigenPodManager contract.
    error OnlyStrategyManagerOrEigenPodManager();
    /// @dev Thrown when msg.sender is not the EigenPodManager
    error OnlyEigenPodManager();
    /// @dev Throw when msg.sender is not the AllocationManager
    error OnlyAllocationManager();

    /// Delegation Status

    /// @dev Thrown when an operator attempts to undelegate.
    error OperatorsCannotUndelegate();
    /// @dev Thrown when an account is actively delegated.
    error ActivelyDelegated();
    /// @dev Thrown when an account is not actively delegated.
    error NotActivelyDelegated();
    /// @dev Thrown when `operator` is not a registered operator.
    error OperatorNotRegistered();

    /// Invalid Inputs

    /// @dev Thrown when attempting to execute an action that was not queued.
    error WithdrawalNotQueued();
    /// @dev Thrown when caller cannot undelegate on behalf of a staker.
    error CallerCannotUndelegate();
    /// @dev Thrown when two array parameters have mismatching lengths.
    error InputArrayLengthMismatch();
    /// @dev Thrown when input arrays length is zero.
    error InputArrayLengthZero();

    /// Slashing

    /// @dev Thrown when an operator has been fully slashed(maxMagnitude is 0) for a strategy.
    /// or if the staker has had been natively slashed to the point of their beaconChainScalingFactor equalling 0.
    error FullySlashed();

    /// Signatures

    /// @dev Thrown when attempting to spend a spent eip-712 salt.
    error SaltSpent();

    /// Withdrawal Processing

    /// @dev Thrown when attempting to withdraw before delay has elapsed.
    error WithdrawalDelayNotElapsed();
    /// @dev Thrown when withdrawer is not the current caller.
    error WithdrawerNotCaller();
}

interface IDelegationManagerTypes {
    // @notice Struct used for storing information about a single operator who has registered with EigenLayer
    struct OperatorDetails {
        /// @notice DEPRECATED -- this field is no longer used, payments are handled in RewardsCoordinator.sol
        address __deprecated_earningsReceiver;
        /// @notice Address to verify signatures when a staker wishes to delegate to the operator, as well as controlling "forced undelegations".
        /// @dev Signature verification follows these rules:
        /// 1) If this address is left as address(0), then any staker will be free to delegate to the operator, i.e. no signature verification will be performed.
        /// 2) If this address is an EOA (i.e. it has no code), then we follow standard ECDSA signature verification for delegations to the operator.
        /// 3) If this address is a contract (i.e. it has code) then we forward a call to the contract and verify that it returns the correct EIP-1271 "magic value".
        address delegationApprover;
        /// @notice DEPRECATED -- this field is no longer used. An analogous field is the `allocationDelay` stored in the AllocationManager
        uint32 __deprecated_stakerOptOutWindowBlocks;
    }

    /// @notice Abstract struct used in calculating an EIP712 signature for an operator's delegationApprover to approve that a specific staker delegate to the operator.
    /// @dev Used in computing the `DELEGATION_APPROVAL_TYPEHASH` and as a reference in the computation of the approverDigestHash in the `_delegate` function.
    struct DelegationApproval {
        // the staker who is delegating
        address staker;
        // the operator being delegated to
        address operator;
        // the operator's provided salt
        bytes32 salt;
        // the expiration timestamp (UTC) of the signature
        uint256 expiry;
    }

    /// @dev A struct representing an existing queued withdrawal. After the withdrawal delay has elapsed, this withdrawal can be completed via `completeQueuedWithdrawal`.
    /// A `Withdrawal` is created by the `DelegationManager` when `queueWithdrawals` is called. The `withdrawalRoots` hashes returned by `queueWithdrawals` can be used
    /// to fetch the corresponding `Withdrawal` from storage (via `getQueuedWithdrawal`).
    ///
    /// @param staker The address that queued the withdrawal
    /// @param delegatedTo The address that the staker was delegated to at the time the withdrawal was queued. Used to determine if additional slashing occurred before
    /// this withdrawal became completable.
    /// @param withdrawer The address that will call the contract to complete the withdrawal. Note that this will always equal `staker`; alternate withdrawers are not
    /// supported at this time.
    /// @param nonce The staker's `cumulativeWithdrawalsQueued` at time of queuing. Used to ensure withdrawals have unique hashes.
    /// @param startBlock The block number when the withdrawal was queued.
    /// @param strategies The strategies requested for withdrawal when the withdrawal was queued
    /// @param scaledShares The staker's deposit shares requested for withdrawal, scaled by the staker's `depositScalingFactor`. Upon completion, these will be
    /// scaled by the appropriate slashing factor as of the withdrawal's completable block. The result is what is actually withdrawable.
    struct Withdrawal {
        address staker;
        address delegatedTo;
        address withdrawer;
        uint256 nonce;
        uint32 startBlock;
        IStrategy[] strategies;
        uint256[] scaledShares;
    }

    /// @param strategies The strategies to withdraw from
    /// @param depositShares For each strategy, the number of deposit shares to withdraw. Deposit shares can
    /// be queried via `getDepositedShares`.
    /// NOTE: The number of shares ultimately received when a withdrawal is completed may be lower depositShares
    /// if the staker or their delegated operator has experienced slashing.
    /// @param __deprecated_withdrawer This field is ignored. The only party that may complete a withdrawal
    /// is the staker that originally queued it. Alternate withdrawers are not supported.
    struct QueuedWithdrawalParams {
        IStrategy[] strategies;
        uint256[] depositShares;
        address __deprecated_withdrawer;
    }
}

interface IDelegationManagerEvents is IDelegationManagerTypes {
    // @notice Emitted when a new operator registers in EigenLayer and provides their delegation approver.
    event OperatorRegistered(address indexed operator, address delegationApprover);

    /// @notice Emitted when an operator updates their delegation approver
    event DelegationApproverUpdated(address indexed operator, address newDelegationApprover);

    /// @notice Emitted when @param operator indicates that they are updating their MetadataURI string
    /// @dev Note that these strings are *never stored in storage* and are instead purely emitted in events for off-chain indexing
    event OperatorMetadataURIUpdated(address indexed operator, string metadataURI);

    /// @notice Emitted whenever an operator's shares are increased for a given strategy. Note that shares is the delta in the operator's shares.
    event OperatorSharesIncreased(address indexed operator, address staker, IStrategy strategy, uint256 shares);

    /// @notice Emitted whenever an operator's shares are decreased for a given strategy. Note that shares is the delta in the operator's shares.
    event OperatorSharesDecreased(address indexed operator, address staker, IStrategy strategy, uint256 shares);

    /// @notice Emitted when @param staker delegates to @param operator.
    event StakerDelegated(address indexed staker, address indexed operator);

    /// @notice Emitted when @param staker undelegates from @param operator.
    event StakerUndelegated(address indexed staker, address indexed operator);

    /// @notice Emitted when @param staker is undelegated via a call not originating from the staker themself
    event StakerForceUndelegated(address indexed staker, address indexed operator);

    /// @notice Emitted when a staker's depositScalingFactor is updated
    event DepositScalingFactorUpdated(address staker, IStrategy strategy, uint256 newDepositScalingFactor);

    /// @notice Emitted when a new withdrawal is queued.
    /// @param withdrawalRoot Is the hash of the `withdrawal`.
    /// @param withdrawal Is the withdrawal itself.
    /// @param sharesToWithdraw Is an array of the expected shares that were queued for withdrawal corresponding to the strategies in the `withdrawal`.
    event SlashingWithdrawalQueued(bytes32 withdrawalRoot, Withdrawal withdrawal, uint256[] sharesToWithdraw);

    /// @notice Emitted when a queued withdrawal is completed
    event SlashingWithdrawalCompleted(bytes32 withdrawalRoot);

    /// @notice Emitted whenever an operator's shares are slashed for a given strategy
    event OperatorSharesSlashed(address indexed operator, IStrategy strategy, uint256 totalSlashedShares);
}

/// @title DelegationManager
/// @author Layr Labs, Inc.
/// @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service
/// @notice  This is the contract for delegation in EigenLayer. The main functionalities of this contract are
/// - enabling anyone to register as an operator in EigenLayer
/// - allowing operators to specify parameters related to stakers who delegate to them
/// - enabling any staker to delegate its stake to the operator of its choice (a given staker can only delegate to a single operator at a time)
/// - enabling a staker to undelegate its assets from the operator it is delegated to (performed as part of the withdrawal process, initiated through the StrategyManager)
interface IDelegationManager is ISignatureUtilsMixin, IDelegationManagerErrors, IDelegationManagerEvents {
    /// @dev Initializes the initial owner and paused status.
    function initialize(
        uint256 initialPausedStatus
    ) external;

    /// @notice Registers the caller as an operator in EigenLayer.
    /// @param initDelegationApprover is an address that, if set, must provide a signature when stakers delegate
    /// to an operator.
    /// @param allocationDelay The delay before allocations take effect.
    /// @param metadataURI is a URI for the operator's metadata, i.e. a link providing more details on the operator.
    ///
    /// @dev Once an operator is registered, they cannot 'deregister' as an operator, and they will forever be considered "delegated to themself".
    /// @dev This function will revert if the caller is already delegated to an operator.
    /// @dev Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event
    function registerAsOperator(
        address initDelegationApprover,
        uint32 allocationDelay,
        string calldata metadataURI
    ) external;

    /// @notice Updates an operator's stored `delegationApprover`.
    /// @param operator is the operator to update the delegationApprover for
    /// @param newDelegationApprover is the new delegationApprover for the operator
    ///
    /// @dev The caller must have previously registered as an operator in EigenLayer.
    function modifyOperatorDetails(
        address operator,
        address newDelegationApprover
    ) external;

    /// @notice Called by an operator to emit an `OperatorMetadataURIUpdated` event indicating the information has updated.
    /// @param operator The operator to update metadata for
    /// @param metadataURI The URI for metadata associated with an operator
    /// @dev Note that the `metadataURI` is *never stored * and is only emitted in the `OperatorMetadataURIUpdated` event
    function updateOperatorMetadataURI(
        address operator,
        string calldata metadataURI
    ) external;

    /// @notice Caller delegates their stake to an operator.
    /// @param operator The account (`msg.sender`) is delegating its assets to for use in serving applications built on EigenLayer.
    /// @param approverSignatureAndExpiry (optional) Verifies the operator approves of this delegation
    /// @param approverSalt (optional) A unique single use value tied to an individual signature.
    /// @dev The signature/salt are used ONLY if the operator has configured a delegationApprover.
    /// If they have not, these params can be left empty.
    function delegateTo(
        address operator,
        SignatureWithExpiry memory approverSignatureAndExpiry,
        bytes32 approverSalt
    ) external;

    /// @notice Undelegates the staker from their operator and queues a withdrawal for all of their shares
    /// @param staker The account to be undelegated
    /// @return withdrawalRoots The roots of the newly queued withdrawals, if a withdrawal was queued. Returns
    /// an empty array if none was queued.
    ///
    /// @dev Reverts if the `staker` is also an operator, since operators are not allowed to undelegate from themselves.
    /// @dev Reverts if the caller is not the staker, nor the operator who the staker is delegated to, nor the operator's specified "delegationApprover"
    /// @dev Reverts if the `staker` is not delegated to an operator
    function undelegate(
        address staker
    ) external returns (bytes32[] memory withdrawalRoots);

    /// @notice Undelegates the staker from their current operator, and redelegates to `newOperator`
    /// Queues a withdrawal for all of the staker's withdrawable shares. These shares will only be
    /// delegated to `newOperator` AFTER the withdrawal is completed.
    /// @dev This method acts like a call to `undelegate`, then `delegateTo`
    /// @param newOperator the new operator that will be delegated all assets
    /// @dev NOTE: the following 2 params are ONLY checked if `newOperator` has a `delegationApprover`.
    /// If not, they can be left empty.
    /// @param newOperatorApproverSig A signature from the operator's `delegationApprover`
    /// @param approverSalt A unique single use value tied to the approver's signature
    function redelegate(
        address newOperator,
        SignatureWithExpiry memory newOperatorApproverSig,
        bytes32 approverSalt
    ) external returns (bytes32[] memory withdrawalRoots);

    /// @notice Allows a staker to queue a withdrawal of their deposit shares. The withdrawal can be
    /// completed after the MIN_WITHDRAWAL_DELAY_BLOCKS via either of the completeQueuedWithdrawal methods.
    ///
    /// While in the queue, these shares are removed from the staker's balance, as well as from their operator's
    /// delegated share balance (if applicable). Note that while in the queue, deposit shares are still subject
    /// to slashing. If any slashing has occurred, the shares received may be less than the queued deposit shares.
    ///
    /// @dev To view all the staker's strategies/deposit shares that can be queued for withdrawal, see `getDepositedShares`
    /// @dev To view the current conversion between a staker's deposit shares and withdrawable shares, see `getWithdrawableShares`
    function queueWithdrawals(
        QueuedWithdrawalParams[] calldata params
    ) external returns (bytes32[] memory);

    /// @notice Used to complete a queued withdrawal
    /// @param withdrawal The withdrawal to complete
    /// @param tokens Array in which the i-th entry specifies the `token` input to the 'withdraw' function of the i-th Strategy in the `withdrawal.strategies` array.
    /// @param tokens For each `withdrawal.strategies`, the underlying token of the strategy
    /// NOTE: if `receiveAsTokens` is false, the `tokens` array is unused and can be filled with default values. However, `tokens.length` MUST still be equal to `withdrawal.strategies.length`.
    /// NOTE: For the `beaconChainETHStrategy`, the corresponding `tokens` value is ignored (can be 0).
    /// @param receiveAsTokens If true, withdrawn shares will be converted to tokens and sent to the caller. If false, the caller receives shares that can be delegated to an operator.
    /// NOTE: if the caller receives shares and is currently delegated to an operator, the received shares are
    /// automatically delegated to the caller's current operator.
    function completeQueuedWithdrawal(
        Withdrawal calldata withdrawal,
        IERC20[] calldata tokens,
        bool receiveAsTokens
    ) external;

    /// @notice Used to complete multiple queued withdrawals
    /// @param withdrawals Array of Withdrawals to complete. See `completeQueuedWithdrawal` for the usage of a single Withdrawal.
    /// @param tokens Array of tokens for each Withdrawal. See `completeQueuedWithdrawal` for the usage of a single array.
    /// @param receiveAsTokens Whether or not to complete each withdrawal as tokens. See `completeQueuedWithdrawal` for the usage of a single boolean.
    /// @dev See `completeQueuedWithdrawal` for relevant dev tags
    function completeQueuedWithdrawals(
        Withdrawal[] calldata withdrawals,
        IERC20[][] calldata tokens,
        bool[] calldata receiveAsTokens
    ) external;

    /// @notice Called by a share manager when a staker's deposit share balance in a strategy increases.
    /// This method delegates any new shares to an operator (if applicable), and updates the staker's
    /// deposit scaling factor regardless.
    /// @param staker The address whose deposit shares have increased
    /// @param strategy The strategy in which shares have been deposited
    /// @param prevDepositShares The number of deposit shares the staker had in the strategy prior to the increase
    /// @param addedShares The number of deposit shares added by the staker
    ///
    /// @dev Note that if the either the staker's current operator has been slashed 100% for `strategy`, OR the
    /// staker has been slashed 100% on the beacon chain such that the calculated slashing factor is 0, this
    /// method WILL REVERT.
    function increaseDelegatedShares(
        address staker,
        IStrategy strategy,
        uint256 prevDepositShares,
        uint256 addedShares
    ) external;

    /// @notice If the staker is delegated, decreases its operator's shares in response to
    /// a decrease in balance in the beaconChainETHStrategy
    /// @param staker the staker whose operator's balance will be decreased
    /// @param curDepositShares the current deposit shares held by the staker
    /// @param beaconChainSlashingFactorDecrease the amount that the staker's beaconChainSlashingFactor has decreased by
    /// @dev Note: `beaconChainSlashingFactorDecrease` are assumed to ALWAYS be < 1 WAD.
    /// These invariants are maintained in the EigenPodManager.
    function decreaseDelegatedShares(
        address staker,
        uint256 curDepositShares,
        uint64 beaconChainSlashingFactorDecrease
    ) external;

    /// @notice Decreases the operator's shares in storage after a slash and increases the burnable shares by calling
    /// into either the StrategyManager or EigenPodManager (if the strategy is beaconChainETH).
    /// @param operator The operator to decrease shares for.
    /// @param operatorSet The operator set to decrease shares for.
    /// @param slashId The slash id to decrease shares for.
    /// @param strategy The strategy to decrease shares for.
    /// @param prevMaxMagnitude The previous maxMagnitude of the operator.
    /// @param newMaxMagnitude The new maxMagnitude of the operator.
    /// @dev Callable only by the AllocationManager.
    /// @dev Note: Assumes `prevMaxMagnitude <= newMaxMagnitude`. This invariant is maintained in
    /// the AllocationManager.
    /// @return totalDepositSharesToSlash The total deposit shares to burn or redistribute.
    function slashOperatorShares(
        address operator,
        OperatorSet calldata operatorSet,
        uint256 slashId,
        IStrategy strategy,
        uint64 prevMaxMagnitude,
        uint64 newMaxMagnitude
    ) external returns (uint256 totalDepositSharesToSlash);

    ///
    ///                         VIEW FUNCTIONS
    ///

    /// @notice returns the address of the operator that `staker` is delegated to.
    /// @notice Mapping: staker => operator whom the staker is currently delegated to.
    /// @dev Note that returning address(0) indicates that the staker is not actively delegated to any operator.
    function delegatedTo(
        address staker
    ) external view returns (address);

    /// @notice Mapping: delegationApprover => 32-byte salt => whether or not the salt has already been used by the delegationApprover.
    /// @dev Salts are used in the `delegateTo` function. Note that this function only processes the delegationApprover's
    /// signature + the provided salt if the operator being delegated to has specified a nonzero address as their `delegationApprover`.
    function delegationApproverSaltIsSpent(
        address _delegationApprover,
        bytes32 salt
    ) external view returns (bool);

    /// @notice Mapping: staker => cumulative number of queued withdrawals they have ever initiated.
    /// @dev This only increments (doesn't decrement), and is used to help ensure that otherwise identical withdrawals have unique hashes.
    function cumulativeWithdrawalsQueued(
        address staker
    ) external view returns (uint256);

    /// @notice Returns 'true' if `staker` *is* actively delegated, and 'false' otherwise.
    function isDelegated(
        address staker
    ) external view returns (bool);

    /// @notice Returns true is an operator has previously registered for delegation.
    function isOperator(
        address operator
    ) external view returns (bool);

    /// @notice Returns the delegationApprover account for an operator
    function delegationApprover(
        address operator
    ) external view returns (address);

    /// @notice Returns the shares that an operator has delegated to them in a set of strategies
    /// @param operator the operator to get shares for
    /// @param strategies the strategies to get shares for
    function getOperatorShares(
        address operator,
        IStrategy[] memory strategies
    ) external view returns (uint256[] memory);

    /// @notice Returns the shares that a set of operators have delegated to them in a set of strategies
    /// @param operators the operators to get shares for
    /// @param strategies the strategies to get shares for
    function getOperatorsShares(
        address[] memory operators,
        IStrategy[] memory strategies
    ) external view returns (uint256[][] memory);

    /// @notice Returns amount of withdrawable shares from an operator for a strategy that is still in the queue
    /// and therefore slashable.
    /// @param operator the operator to get shares for
    /// @param strategy the strategy to get shares for
    /// @return the amount of shares that are slashable in the withdrawal queue for an operator and a strategy
    /// @dev If multiple slashes occur to shares in the queue, the function properly accounts for the fewer
    ///      number of shares that are available to be slashed.
    function getSlashableSharesInQueue(
        address operator,
        IStrategy strategy
    ) external view returns (uint256);

    /// @notice Given a staker and a set of strategies, return the shares they can queue for withdrawal and the
    /// corresponding depositShares.
    /// This value depends on which operator the staker is delegated to.
    /// The shares amount returned is the actual amount of Strategy shares the staker would receive (subject
    /// to each strategy's underlying shares to token ratio).
    function getWithdrawableShares(
        address staker,
        IStrategy[] memory strategies
    ) external view returns (uint256[] memory withdrawableShares, uint256[] memory depositShares);

    /// @notice Returns the number of shares in storage for a staker and all their strategies
    function getDepositedShares(
        address staker
    ) external view returns (IStrategy[] memory, uint256[] memory);

    /// @notice Returns the scaling factor applied to a staker's deposits for a given strategy
    function depositScalingFactor(
        address staker,
        IStrategy strategy
    ) external view returns (uint256);

    /// @notice Returns the Withdrawal associated with a `withdrawalRoot`.
    /// @param withdrawalRoot The hash identifying the queued withdrawal.
    /// @return withdrawal The withdrawal details.
    function queuedWithdrawals(
        bytes32 withdrawalRoot
    ) external view returns (Withdrawal memory withdrawal);

    /// @notice Returns the Withdrawal and corresponding shares associated with a `withdrawalRoot`
    /// @param withdrawalRoot The hash identifying the queued withdrawal
    /// @return withdrawal The withdrawal details
    /// @return shares Array of shares corresponding to each strategy in the withdrawal
    /// @dev The shares are what a user would receive from completing a queued withdrawal, assuming all slashings are applied
    /// @dev Withdrawals queued before the slashing release cannot be queried with this method
    function getQueuedWithdrawal(
        bytes32 withdrawalRoot
    ) external view returns (Withdrawal memory withdrawal, uint256[] memory shares);

    /// @notice Returns all queued withdrawals and their corresponding shares for a staker.
    /// @param staker The address of the staker to query withdrawals for.
    /// @return withdrawals Array of Withdrawal structs containing details about each queued withdrawal.
    /// @return shares 2D array of shares, where each inner array corresponds to the strategies in the withdrawal.
    /// @dev The shares are what a user would receive from completing a queued withdrawal, assuming all slashings are applied.
    function getQueuedWithdrawals(
        address staker
    ) external view returns (Withdrawal[] memory withdrawals, uint256[][] memory shares);

    /// @notice Returns a list of queued withdrawal roots for the `staker`.
    /// NOTE that this only returns withdrawals queued AFTER the slashing release.
    function getQueuedWithdrawalRoots(
        address staker
    ) external view returns (bytes32[] memory);

    /// @notice Converts shares for a set of strategies to deposit shares, likely in order to input into `queueWithdrawals`.
    /// This function will revert from a division by 0 error if any of the staker's strategies have a slashing factor of 0.
    /// @param staker the staker to convert shares for
    /// @param strategies the strategies to convert shares for
    /// @param withdrawableShares the shares to convert
    /// @return the deposit shares
    /// @dev will be a few wei off due to rounding errors
    function convertToDepositShares(
        address staker,
        IStrategy[] memory strategies,
        uint256[] memory withdrawableShares
    ) external view returns (uint256[] memory);

    /// @notice Returns the keccak256 hash of `withdrawal`.
    function calculateWithdrawalRoot(
        Withdrawal memory withdrawal
    ) external pure returns (bytes32);

    /// @notice Calculates the digest hash to be signed by the operator's delegationApprove and used in the `delegateTo` function.
    /// @param staker The account delegating their stake
    /// @param operator The account receiving delegated stake
    /// @param _delegationApprover the operator's `delegationApprover` who will be signing the delegationHash (in general)
    /// @param approverSalt A unique and single use value associated with the approver signature.
    /// @param expiry Time after which the approver's signature becomes invalid
    function calculateDelegationApprovalDigestHash(
        address staker,
        address operator,
        address _delegationApprover,
        bytes32 approverSalt,
        uint256 expiry
    ) external view returns (bytes32);

    /// @notice return address of the beaconChainETHStrategy
    function beaconChainETHStrategy() external view returns (IStrategy);

    /// @notice Returns the minimum withdrawal delay in blocks to pass for withdrawals queued to be completable.
    /// Also applies to legacy withdrawals so any withdrawals not completed prior to the slashing upgrade will be subject
    /// to this longer delay.
    /// @dev Backwards-compatible interface to return the internal `MIN_WITHDRAWAL_DELAY_BLOCKS` value
    /// @dev Previous value in storage was deprecated. See `__deprecated_minWithdrawalDelayBlocks`
    function minWithdrawalDelayBlocks() external view returns (uint32);

    /// @notice The EIP-712 typehash for the DelegationApproval struct used by the contract
    function DELEGATION_APPROVAL_TYPEHASH() external view returns (bytes32);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

/// @title Interface for the `PauserRegistry` contract.
/// @author Layr Labs, Inc.
/// @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service
interface IPauserRegistry {
    error OnlyUnpauser();
    error InputAddressZero();

    event PauserStatusChanged(address pauser, bool canPause);

    event UnpauserChanged(address previousUnpauser, address newUnpauser);

    /// @notice Mapping of addresses to whether they hold the pauser role.
    function isPauser(
        address pauser
    ) external view returns (bool);

    /// @notice Unique address that holds the unpauser role. Capable of changing *both* the pauser and unpauser addresses.
    function unpauser() external view returns (address);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

import "../interfaces/IPauserRegistry.sol";

/// @title Adds pausability to a contract, with pausing & unpausing controlled by the `pauser` and `unpauser` of a PauserRegistry contract.
/// @author Layr Labs, Inc.
/// @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service
/// @notice Contracts that inherit from this contract may define their own `pause` and `unpause` (and/or related) functions.
/// These functions should be permissioned as "onlyPauser" which defers to a `PauserRegistry` for determining access control.
/// @dev Pausability is implemented using a uint256, which allows up to 256 different single bit-flags; each bit can potentially pause different functionality.
/// Inspiration for this was taken from the NearBridge design here https://etherscan.io/address/0x3FEFc5A4B1c02f21cBc8D3613643ba0635b9a873#code.
/// For the `pause` and `unpause` functions we've implemented, if you pause, you can only flip (any number of) switches to on/1 (aka "paused"), and if you unpause,
/// you can only flip (any number of) switches to off/0 (aka "paused").
/// If you want a pauseXYZ function that just flips a single bit / "pausing flag", it will:
/// 1) 'bit-wise and' (aka `&`) a flag with the current paused state (as a uint256)
/// 2) update the paused state to this new value
/// @dev We note as well that we have chosen to identify flags by their *bit index* as opposed to their numerical value, so, e.g. defining `DEPOSITS_PAUSED = 3`
/// indicates specifically that if the *third bit* of `_paused` is flipped -- i.e. it is a '1' -- then deposits should be paused
interface IPausable {
    /// @dev Thrown when caller is not pauser.
    error OnlyPauser();
    /// @dev Thrown when caller is not unpauser.
    error OnlyUnpauser();
    /// @dev Thrown when currently paused.
    error CurrentlyPaused();
    /// @dev Thrown when invalid `newPausedStatus` is provided.
    error InvalidNewPausedStatus();
    /// @dev Thrown when a null address input is provided.
    error InputAddressZero();

    /// @notice Emitted when the pause is triggered by `account`, and changed to `newPausedStatus`.
    event Paused(address indexed account, uint256 newPausedStatus);

    /// @notice Emitted when the pause is lifted by `account`, and changed to `newPausedStatus`.
    event Unpaused(address indexed account, uint256 newPausedStatus);

    /// @notice Address of the `PauserRegistry` contract that this contract defers to for determining access control (for pausing).
    function pauserRegistry() external view returns (IPauserRegistry);

    /// @notice This function is used to pause an EigenLayer contract's functionality.
    /// It is permissioned to the `pauser` address, which is expected to be a low threshold multisig.
    /// @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once.
    /// @dev This function can only pause functionality, and thus cannot 'unflip' any bit in `_paused` from 1 to 0.
    function pause(
        uint256 newPausedStatus
    ) external;

    /// @notice Alias for `pause(type(uint256).max)`.
    function pauseAll() external;

    /// @notice This function is used to unpause an EigenLayer contract's functionality.
    /// It is permissioned to the `unpauser` address, which is expected to be a high threshold multisig or governance contract.
    /// @param newPausedStatus represents the new value for `_paused` to take, which means it may flip several bits at once.
    /// @dev This function can only unpause functionality, and thus cannot 'flip' any bit in `_paused` from 0 to 1.
    function unpause(
        uint256 newPausedStatus
    ) external;

    /// @notice Returns the current paused status as a uint256.
    function paused() external view returns (uint256);

    /// @notice Returns 'true' if the `indexed`th bit of `_paused` is 1, and 'false' otherwise
    function paused(
        uint8 index
    ) external view returns (bool);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../libraries/SlashingLib.sol";

interface IStrategyErrors {
    /// @dev Thrown when called by an account that is not strategy manager.
    error OnlyStrategyManager();
    /// @dev Thrown when new shares value is zero.
    error NewSharesZero();
    /// @dev Thrown when total shares exceeds max.
    error TotalSharesExceedsMax();
    /// @dev Thrown when amount shares is greater than total shares.
    error WithdrawalAmountExceedsTotalDeposits();
    /// @dev Thrown when attempting an action with a token that is not accepted.
    error OnlyUnderlyingToken();

    /// StrategyBaseWithTVLLimits

    /// @dev Thrown when `maxPerDeposit` exceeds max.
    error MaxPerDepositExceedsMax();
    /// @dev Thrown when balance exceeds max total deposits.
    error BalanceExceedsMaxTotalDeposits();
}

interface IStrategyEvents {
    /// @notice Used to emit an event for the exchange rate between 1 share and underlying token in a strategy contract
    /// @param rate is the exchange rate in wad 18 decimals
    /// @dev Tokens that do not have 18 decimals must have offchain services scale the exchange rate by the proper magnitude
    event ExchangeRateEmitted(uint256 rate);

    /// Used to emit the underlying token and its decimals on strategy creation
    /// @notice token
    /// @param token is the ERC20 token of the strategy
    /// @param decimals are the decimals of the ERC20 token in the strategy
    event StrategyTokenSet(IERC20 token, uint8 decimals);
}

/// @title Minimal interface for an `Strategy` contract.
/// @author Layr Labs, Inc.
/// @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service
/// @notice Custom `Strategy` implementations may expand extensively on this interface.
interface IStrategy is IStrategyErrors, IStrategyEvents {
    /// @notice Used to deposit tokens into this Strategy
    /// @param token is the ERC20 token being deposited
    /// @param amount is the amount of token being deposited
    /// @dev This function is only callable by the strategyManager contract. It is invoked inside of the strategyManager's
    /// `depositIntoStrategy` function, and individual share balances are recorded in the strategyManager as well.
    /// @return newShares is the number of new shares issued at the current exchange ratio.
    function deposit(
        IERC20 token,
        uint256 amount
    ) external returns (uint256);

    /// @notice Used to withdraw tokens from this Strategy, to the `recipient`'s address
    /// @param recipient is the address to receive the withdrawn funds
    /// @param token is the ERC20 token being transferred out
    /// @param amountShares is the amount of shares being withdrawn
    /// @dev This function is only callable by the strategyManager contract. It is invoked inside of the strategyManager's
    /// other functions, and individual share balances are recorded in the strategyManager as well.
    /// @return amountOut is the amount of tokens being transferred out.
    function withdraw(
        address recipient,
        IERC20 token,
        uint256 amountShares
    ) external returns (uint256);

    /// @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy.
    /// For a staker using this function and trying to calculate the amount of underlying tokens they have in total they
    /// should input into `amountShares` their withdrawable shares read from the `DelegationManager` contract.
    /// @notice In contrast to `sharesToUnderlyingView`, this function **may** make state modifications
    /// @param amountShares is the amount of shares to calculate its conversion into the underlying token
    /// @return The amount of underlying tokens corresponding to the input `amountShares`
    /// @dev Implementation for these functions in particular may vary significantly for different strategies
    function sharesToUnderlying(
        uint256 amountShares
    ) external returns (uint256);

    /// @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy.
    /// @notice In contrast to `underlyingToSharesView`, this function **may** make state modifications
    /// @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares
    /// @return The amount of shares corresponding to the input `amountUnderlying`.  This is used as deposit shares
    /// in the `StrategyManager` contract.
    /// @dev Implementation for these functions in particular may vary significantly for different strategies
    function underlyingToShares(
        uint256 amountUnderlying
    ) external returns (uint256);

    /// @notice convenience function for fetching the current underlying value of all of the `user`'s shares in
    /// this strategy. In contrast to `userUnderlyingView`, this function **may** make state modifications
    function userUnderlying(
        address user
    ) external returns (uint256);

    /// @notice convenience function for fetching the current total shares of `user` in this strategy, by
    /// querying the `strategyManager` contract
    function shares(
        address user
    ) external view returns (uint256);

    /// @notice Used to convert a number of shares to the equivalent amount of underlying tokens for this strategy.
    /// For a staker using this function and trying to calculate the amount of underlying tokens they have in total they
    /// should input into `amountShares` their withdrawable shares read from the `DelegationManager` contract.
    /// @notice In contrast to `sharesToUnderlying`, this function guarantees no state modifications
    /// @param amountShares is the amount of shares to calculate its conversion into the underlying token
    /// @return The amount of underlying tokens corresponding to the input `amountShares`
    /// @dev Implementation for these functions in particular may vary significantly for different strategies
    function sharesToUnderlyingView(
        uint256 amountShares
    ) external view returns (uint256);

    /// @notice Used to convert an amount of underlying tokens to the equivalent amount of shares in this strategy.
    /// @notice In contrast to `underlyingToShares`, this function guarantees no state modifications
    /// @param amountUnderlying is the amount of `underlyingToken` to calculate its conversion into strategy shares
    /// @return The amount of shares corresponding to the input `amountUnderlying`. This is used as deposit shares
    /// in the `StrategyManager` contract.
    /// @dev Implementation for these functions in particular may vary significantly for different strategies
    function underlyingToSharesView(
        uint256 amountUnderlying
    ) external view returns (uint256);

    /// @notice convenience function for fetching the current underlying value of all of the `user`'s shares in
    /// this strategy. In contrast to `userUnderlying`, this function guarantees no state modifications
    function userUnderlyingView(
        address user
    ) external view returns (uint256);

    /// @notice The underlying token for shares in this Strategy
    function underlyingToken() external view returns (IERC20);

    /// @notice The total number of extant shares in this Strategy
    function totalShares() external view returns (uint256);

    /// @notice Returns either a brief string explaining the strategy's goal & purpose, or a link to metadata that explains in more detail.
    function explanation() external view returns (string memory);
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

interface IAVSRegistrar {
    /// @notice Called by the AllocationManager when an operator wants to register
    /// for one or more operator sets. This method should revert if registration
    /// is unsuccessful.
    /// @param operator the registering operator
    /// @param avs the AVS the operator is registering for. This should be the same as IAVSRegistrar.avs()
    /// @param operatorSetIds the list of operator set ids being registered for
    /// @param data arbitrary data the operator can provide as part of registration
    function registerOperator(
        address operator,
        address avs,
        uint32[] calldata operatorSetIds,
        bytes calldata data
    ) external;

    /// @notice Called by the AllocationManager when an operator is deregistered from one or more operator sets
    /// @param operator the deregistering operator
    /// @param avs the AVS the operator is deregistering from. This should be the same as IAVSRegistrar.avs()
    /// @param operatorSetIds the list of operator set ids being deregistered from
    function deregisterOperator(
        address operator,
        address avs,
        uint32[] calldata operatorSetIds
    ) external;

    /// @notice Returns true if the AVS is supported by the registrar
    /// @param avs the AVS to check
    /// @return true if the AVS is supported, false otherwise
    function supportsAVS(
        address avs
    ) external view returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library MathUpgradeable {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;

import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin-upgrades/contracts/utils/math/SafeCastUpgradeable.sol";

/// @dev All scaling factors have `1e18` as an initial/default value. This value is represented
/// by the constant `WAD`, which is used to preserve precision with uint256 math.
///
/// When applying scaling factors, they are typically multiplied/divided by `WAD`, allowing this
/// constant to act as a "1" in mathematical formulae.
uint64 constant WAD = 1e18;

/*
 * There are 2 types of shares:
 *      1. deposit shares
 *          - These can be converted to an amount of tokens given a strategy
 *              - by calling `sharesToUnderlying` on the strategy address (they're already tokens
 *              in the case of EigenPods)
 *          - These live in the storage of the EigenPodManager and individual StrategyManager strategies
 *      2. withdrawable shares
 *          - For a staker, this is the amount of shares that they can withdraw
 *          - For an operator, the shares delegated to them are equal to the sum of their stakers'
 *            withdrawable shares
 *
 * Along with a slashing factor, the DepositScalingFactor is used to convert between the two share types.
 */
struct DepositScalingFactor {
    uint256 _scalingFactor;
}

using SlashingLib for DepositScalingFactor global;

library SlashingLib {
    using Math for uint256;
    using SlashingLib for uint256;
    using SafeCastUpgradeable for uint256;

    /// @dev Thrown if an updated deposit scaling factor is 0 to avoid underflow.
    error InvalidDepositScalingFactor();

    // WAD MATH

    function mulWad(
        uint256 x,
        uint256 y
    ) internal pure returns (uint256) {
        return x.mulDiv(y, WAD);
    }

    function divWad(
        uint256 x,
        uint256 y
    ) internal pure returns (uint256) {
        return x.mulDiv(WAD, y);
    }

    /// @notice Used explicitly for calculating slashed magnitude, we want to ensure even in the
    /// situation where an operator is slashed several times and precision has been lost over time,
    /// an incoming slashing request isn't rounded down to 0 and an operator is able to avoid slashing penalties.
    function mulWadRoundUp(
        uint256 x,
        uint256 y
    ) internal pure returns (uint256) {
        return x.mulDiv(y, WAD, Math.Rounding.Up);
    }

    // GETTERS

    function scalingFactor(
        DepositScalingFactor memory dsf
    ) internal pure returns (uint256) {
        return dsf._scalingFactor == 0 ? WAD : dsf._scalingFactor;
    }

    function scaleForQueueWithdrawal(
        DepositScalingFactor memory dsf,
        uint256 depositSharesToWithdraw
    ) internal pure returns (uint256) {
        return depositSharesToWithdraw.mulWad(dsf.scalingFactor());
    }

    function scaleForCompleteWithdrawal(
        uint256 scaledShares,
        uint256 slashingFactor
    ) internal pure returns (uint256) {
        return scaledShares.mulWad(slashingFactor);
    }

    function update(
        DepositScalingFactor storage dsf,
        uint256 prevDepositShares,
        uint256 addedShares,
        uint256 slashingFactor
    ) internal {
        if (prevDepositShares == 0) {
            // If this is the staker's first deposit or they are delegating to an operator,
            // the slashing factor is inverted and applied to the existing DSF. This has the
            // effect of "forgiving" prior slashing for any subsequent deposits.
            dsf._scalingFactor = dsf.scalingFactor().divWad(slashingFactor);
            return;
        }

        /// Base Equations:
        /// (1) newShares = currentShares + addedShares
        /// (2) newDepositShares = prevDepositShares + addedShares
        /// (3) newShares = newDepositShares * newDepositScalingFactor * slashingFactor
        ///
        /// Plugging (1) into (3):
        /// (4) newDepositShares * newDepositScalingFactor * slashingFactor = currentShares + addedShares
        ///
        /// Solving for newDepositScalingFactor
        /// (5) newDepositScalingFactor = (currentShares + addedShares) / (newDepositShares * slashingFactor)
        ///
        /// Plugging in (2) into (5):
        /// (7) newDepositScalingFactor = (currentShares + addedShares) / ((prevDepositShares + addedShares) * slashingFactor)
        /// Note that magnitudes must be divided by WAD for precision. Thus,
        ///
        /// (8) newDepositScalingFactor = WAD * (currentShares + addedShares) / ((prevDepositShares + addedShares) * slashingFactor / WAD)
        /// (9) newDepositScalingFactor = (currentShares + addedShares) * WAD / (prevDepositShares + addedShares) * WAD / slashingFactor

        // Step 1: Calculate Numerator
        uint256 currentShares = dsf.calcWithdrawable(prevDepositShares, slashingFactor);

        // Step 2: Compute currentShares + addedShares
        uint256 newShares = currentShares + addedShares;

        // Step 3: Calculate newDepositScalingFactor
        /// forgefmt: disable-next-item
        uint256 newDepositScalingFactor = newShares
            .divWad(prevDepositShares + addedShares)
            .divWad(slashingFactor);

        dsf._scalingFactor = newDepositScalingFactor;

        // Avoid potential underflow.
        require(newDepositScalingFactor != 0, InvalidDepositScalingFactor());
    }

    /// @dev Reset the staker's DSF for a strategy by setting it to 0. This is the same
    /// as setting it to WAD (see the `scalingFactor` getter above).
    ///
    /// A DSF is reset when a staker reduces their deposit shares to 0, either by queueing
    /// a withdrawal, or undelegating from their operator. This ensures that subsequent
    /// delegations/deposits do not use a stale DSF (e.g. from a prior operator).
    function reset(
        DepositScalingFactor storage dsf
    ) internal {
        dsf._scalingFactor = 0;
    }

    // CONVERSION

    function calcWithdrawable(
        DepositScalingFactor memory dsf,
        uint256 depositShares,
        uint256 slashingFactor
    ) internal pure returns (uint256) {
        /// forgefmt: disable-next-item
        return depositShares
            .mulWad(dsf.scalingFactor())
            .mulWad(slashingFactor);
    }

    function calcDepositShares(
        DepositScalingFactor memory dsf,
        uint256 withdrawableShares,
        uint256 slashingFactor
    ) internal pure returns (uint256) {
        /// forgefmt: disable-next-item
        return withdrawableShares
            .divWad(dsf.scalingFactor())
            .divWad(slashingFactor);
    }

    /// @notice Calculates the amount of shares that should be slashed given the previous and new magnitudes.
    /// @param operatorShares The amount of shares to slash.
    /// @param prevMaxMagnitude The previous magnitude of the operator.
    /// @param newMaxMagnitude The new magnitude of the operator.
    /// @return The amount of shares that should be slashed.
    /// @dev This function will revert with a divide by zero error if the previous magnitude is 0.
    function calcSlashedAmount(
        uint256 operatorShares,
        uint256 prevMaxMagnitude,
        uint256 newMaxMagnitude
    ) internal pure returns (uint256) {
        // round up mulDiv so we don't overslash
        return operatorShares - operatorShares.mulDiv(newMaxMagnitude, prevMaxMagnitude, Math.Rounding.Up);
    }
}

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.5.0;

interface ISignatureUtilsMixinErrors {
    /// @notice Thrown when a signature is invalid.
    error InvalidSignature();
    /// @notice Thrown when a signature has expired.
    error SignatureExpired();
}

interface ISignatureUtilsMixinTypes {
    /// @notice Struct that bundles together a signature and an expiration time for the signature.
    /// @dev Used primarily for stack management.
    struct SignatureWithExpiry {
        // the signature itself, formatted as a single bytes object
        bytes signature;
        // the expiration timestamp (UTC) of the signature
        uint256 expiry;
    }

    /// @notice Struct that bundles together a signature, a salt for uniqueness, and an expiration time for the signature.
    /// @dev Used primarily for stack management.
    struct SignatureWithSaltAndExpiry {
        // the signature itself, formatted as a single bytes object
        bytes signature;
        // the salt used to generate the signature
        bytes32 salt;
        // the expiration timestamp (UTC) of the signature
        uint256 expiry;
    }
}

/// @title The interface for common signature utilities.
/// @author Layr Labs, Inc.
/// @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service
interface ISignatureUtilsMixin is ISignatureUtilsMixinErrors, ISignatureUtilsMixinTypes {
    /// @notice Computes the EIP-712 domain separator used for signature validation.
    /// @dev The domain separator is computed according to EIP-712 specification, using:
    ///      - The hardcoded name "EigenLayer"
    ///      - The contract's version string
    ///      - The current chain ID
    ///      - This contract's address
    /// @return The 32-byte domain separator hash used in EIP-712 structured data signing.
    /// @dev See https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator.
    function domainSeparator() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

File 19 of 19 : SafeCastUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.0;

/**
 * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
 * all math on `uint256` and `int256` and then downcasting.
 */
library SafeCastUpgradeable {
    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.2._
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v2.5._
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.2._
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v2.5._
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v2.5._
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v2.5._
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v2.5._
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     *
     * _Available since v3.0._
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        require(value >= 0, "SafeCast: value must be positive");
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     *
     * _Available since v4.7._
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     *
     * _Available since v4.7._
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     *
     * _Available since v4.7._
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     *
     * _Available since v4.7._
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     *
     * _Available since v4.7._
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     *
     * _Available since v4.7._
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     *
     * _Available since v4.7._
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     *
     * _Available since v4.7._
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     *
     * _Available since v4.7._
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     *
     * _Available since v4.7._
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     *
     * _Available since v4.7._
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     *
     * _Available since v4.7._
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     *
     * _Available since v4.7._
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     *
     * _Available since v4.7._
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     *
     * _Available since v4.7._
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     *
     * _Available since v3.1._
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     *
     * _Available since v4.7._
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     *
     * _Available since v4.7._
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     *
     * _Available since v4.7._
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     *
     * _Available since v4.7._
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     *
     * _Available since v4.7._
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     *
     * _Available since v4.7._
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     *
     * _Available since v4.7._
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     *
     * _Available since v3.1._
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     *
     * _Available since v4.7._
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     *
     * _Available since v4.7._
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     *
     * _Available since v4.7._
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     *
     * _Available since v3.1._
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     *
     * _Available since v4.7._
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     *
     * _Available since v3.1._
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     *
     * _Available since v3.1._
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     *
     * _Available since v3.0._
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
        return int256(value);
    }
}

Settings
{
  "remappings": [
    "@openzeppelin/=lib/openzeppelin-contracts-v4.9.0/",
    "@openzeppelin-upgrades/=lib/openzeppelin-contracts-upgradeable-v4.9.0/",
    "ds-test/=lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "erc4626-tests/=lib/openzeppelin-contracts-upgradeable-v4.9.0/lib/erc4626-tests/",
    "openzeppelin-contracts-upgradeable-v4.9.0/=lib/openzeppelin-contracts-upgradeable-v4.9.0/",
    "openzeppelin-contracts-v4.9.0/=lib/openzeppelin-contracts-v4.9.0/",
    "openzeppelin/=lib/openzeppelin-contracts-upgradeable-v4.9.0/contracts/",
    "zeus-templates/=lib/zeus-templates/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "prague",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IDelegationManager","name":"_delegation","type":"address"},{"internalType":"contract IStrategy","name":"_eigenStrategy","type":"address"},{"internalType":"uint32","name":"_DEALLOCATION_DELAY","type":"uint32"},{"internalType":"uint32","name":"_ALLOCATION_CONFIGURATION_DELAY","type":"uint32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyMemberOfSet","type":"error"},{"inputs":[],"name":"InputArrayLengthMismatch","type":"error"},{"inputs":[],"name":"InsufficientMagnitude","type":"error"},{"inputs":[],"name":"InvalidAVSRegistrar","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidOperator","type":"error"},{"inputs":[],"name":"InvalidOperatorSet","type":"error"},{"inputs":[],"name":"InvalidRedistributionRecipient","type":"error"},{"inputs":[],"name":"InvalidStrategy","type":"error"},{"inputs":[],"name":"InvalidWadToSlash","type":"error"},{"inputs":[],"name":"ModificationAlreadyPending","type":"error"},{"inputs":[],"name":"NonexistentAVSMetadata","type":"error"},{"inputs":[],"name":"NotMemberOfSet","type":"error"},{"inputs":[],"name":"OperatorNotSlashable","type":"error"},{"inputs":[],"name":"OperatorSetAlreadyMigrated","type":"error"},{"inputs":[],"name":"OutOfBounds","type":"error"},{"inputs":[],"name":"SameMagnitude","type":"error"},{"inputs":[],"name":"SlasherNotSet","type":"error"},{"inputs":[],"name":"StrategiesMustBeInAscendingOrder","type":"error"},{"inputs":[],"name":"StrategyAlreadyInOperatorSet","type":"error"},{"inputs":[],"name":"StrategyNotInOperatorSet","type":"error"},{"inputs":[],"name":"UninitializedAllocationDelay","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"avs","type":"address"},{"indexed":false,"internalType":"string","name":"metadataURI","type":"string"}],"name":"AVSMetadataURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"avs","type":"address"},{"indexed":false,"internalType":"contract IAVSRegistrar","name":"registrar","type":"address"}],"name":"AVSRegistrarSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"uint32","name":"delay","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"effectBlock","type":"uint32"}],"name":"AllocationDelaySet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"indexed":false,"internalType":"contract IStrategy","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint64","name":"magnitude","type":"uint64"},{"indexed":false,"internalType":"uint32","name":"effectBlock","type":"uint32"}],"name":"AllocationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"contract IStrategy","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint64","name":"encumberedMagnitude","type":"uint64"}],"name":"EncumberedMagnitudeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"contract IStrategy","name":"strategy","type":"address"},{"indexed":false,"internalType":"uint64","name":"maxMagnitude","type":"uint64"}],"name":"MaxMagnitudeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"OperatorAddedToOperatorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"OperatorRemovedFromOperatorSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"OperatorSetCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"indexed":false,"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"wadSlashed","type":"uint256[]"},{"indexed":false,"internalType":"string","name":"description","type":"string"}],"name":"OperatorSlashed","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"indexed":false,"internalType":"address","name":"redistributionRecipient","type":"address"}],"name":"RedistributionAddressSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"indexed":false,"internalType":"address","name":"slasher","type":"address"}],"name":"SlasherMigrated","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"indexed":false,"internalType":"address","name":"slasher","type":"address"},{"indexed":false,"internalType":"uint32","name":"effectBlock","type":"uint32"}],"name":"SlasherUpdated","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"indexed":false,"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"StrategyAddedToOperatorSet","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"indexed":false,"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"indexed":false,"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"StrategyRemovedFromOperatorSet","type":"event"},{"inputs":[],"name":"ALLOCATION_CONFIGURATION_DELAY","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEALLOCATION_DELAY","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLASHER_CONFIGURATION_DELAY","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delegation","outputs":[{"internalType":"contract IDelegationManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eigenStrategy","outputs":[{"internalType":"contract IStrategy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"}],"name":"getAVSRegistrar","outputs":[{"internalType":"contract IAVSRegistrar","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"getAllocatableMagnitude","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getAllocatedSets","outputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"internalType":"address[]","name":"operators","type":"address[]"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"name":"getAllocatedStake","outputs":[{"internalType":"uint256[][]","name":"","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"getAllocatedStrategies","outputs":[{"internalType":"contract IStrategy[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"getAllocation","outputs":[{"components":[{"internalType":"uint64","name":"currentMagnitude","type":"uint64"},{"internalType":"int128","name":"pendingDiff","type":"int128"},{"internalType":"uint32","name":"effectBlock","type":"uint32"}],"internalType":"struct IAllocationManagerTypes.Allocation","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getAllocationDelay","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"operators","type":"address[]"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"getAllocations","outputs":[{"components":[{"internalType":"uint64","name":"currentMagnitude","type":"uint64"},{"internalType":"int128","name":"pendingDiff","type":"int128"},{"internalType":"uint32","name":"effectBlock","type":"uint32"}],"internalType":"struct IAllocationManagerTypes.Allocation[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"getEncumberedMagnitude","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"getMaxMagnitude","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"operators","type":"address[]"},{"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"getMaxMagnitudes","outputs":[{"internalType":"uint64[]","name":"","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"name":"getMaxMagnitudes","outputs":[{"internalType":"uint64[]","name":"","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint32","name":"blockNumber","type":"uint32"}],"name":"getMaxMagnitudesAtBlock","outputs":[{"internalType":"uint64[]","name":"","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"getMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"getMembers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"internalType":"address[]","name":"operators","type":"address[]"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint32","name":"futureBlock","type":"uint32"}],"name":"getMinimumSlashableStake","outputs":[{"internalType":"uint256[][]","name":"slashableStake","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"}],"name":"getOperatorSetCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"getPendingSlasher","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"getRedistributionRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"getRegisteredSets","outputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"getSlashCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"getSlasher","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"getStrategiesInOperatorSet","outputs":[{"internalType":"contract IStrategy[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract IStrategy","name":"strategy","type":"address"}],"name":"getStrategyAllocations","outputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet[]","name":"","type":"tuple[]"},{"components":[{"internalType":"uint64","name":"currentMagnitude","type":"uint64"},{"internalType":"int128","name":"pendingDiff","type":"int128"},{"internalType":"uint32","name":"effectBlock","type":"uint32"}],"internalType":"struct IAllocationManagerTypes.Allocation[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"isMemberOfOperatorSet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"}],"name":"isOperatorRedistributable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"isOperatorSet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"isOperatorSlashable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"}],"name":"isRedistributingOperatorSet","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]

610120604052348015610010575f5ffd5b5060405161277a38038061277a83398101604081905261002f9161008d565b6001600160a01b039384166080529290911660a05263ffffffff90811660c0521660e0819052610100526100e3565b6001600160a01b0381168114610072575f5ffd5b50565b805163ffffffff81168114610088575f5ffd5b919050565b5f5f5f5f608085870312156100a0575f5ffd5b84516100ab8161005e565b60208601519094506100bc8161005e565b92506100ca60408601610075565b91506100d860608601610075565b905092959194509250565b60805160a05160c05160e051610100516126536101275f395f6103d601525f61044e01525f6102ac01525f61056d01525f81816105a701526113e201526126535ff3fe608060405234801561000f575f5ffd5b50600436106101fd575f3560e01c80636e875dba11610114578063ba1a84e5116100a9578063db4df76111610079578063db4df76114610568578063dc2af6921461058f578063df5cf723146105a2578063f231bd08146105c9578063f605ce08146105dc575f5ffd5b8063ba1a84e5146104f8578063c221d8ae1461050b578063d4a3fcce1461051e578063d779485714610531575f5ffd5b806394d7d00c116100e457806394d7d00c14610490578063a9333ec8146104a3578063b2447af7146104b6578063b9fbaed1146104c9575f5ffd5b80636e875dba1461042357806379ae50cd146104365780637bc1ef61146104495780638ce6485414610470575f5ffd5b8063304c10cd116101955780634cfd2939116101655780634cfd29391461038a578063547afb87146103ab578063670d3ba2146103be57806367aeaa53146103d15780636cfb4481146103f8575f5ffd5b8063304c10cd1461031657806340120dab146103295780634177a87c1461034a5780634a10ffe51461036a575f5ffd5b8063260dc758116101d0578063260dc758146102945780632981eb77146102a75780632b453a9a146102e35780632bab2c4a14610303575f5ffd5b80630f3df50e1461020157806310e1b9b8146102315780631352c3e61461025157806315fe502814610274575b5f5ffd5b61021461020f366004611dd8565b6105ef565b6040516001600160a01b0390911681526020015b60405180910390f35b61024461023f366004611df2565b610630565b6040516102289190611e39565b61026461025f366004611e6c565b610669565b6040519015158152602001610228565b610287610282366004611ea0565b6106e4565b6040516102289190611f10565b6102646102a2366004611dd8565b6107fb565b6102ce7f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff9091168152602001610228565b6102f66102f1366004611fb7565b61082c565b604051610228919061202a565b6102f66103113660046120b6565b610842565b610214610324366004611ea0565b6108e1565b61033c61033736600461213a565b610910565b6040516102289291906121d2565b61035d610358366004611dd8565b610a89565b604051610228919061222f565b61037d610378366004612241565b610aad565b6040516102289190612284565b61039d610398366004611dd8565b610b55565b604051908152602001610228565b61037d6103b93660046122cf565b610b77565b6102646103cc366004611e6c565b610c1f565b6102ce7f000000000000000000000000000000000000000000000000000000000000000081565b61040b61040636600461213a565b610c4b565b6040516001600160401b039091168152602001610228565b61035d610431366004611dd8565b610c60565b610287610444366004611ea0565b610c71565b6102ce7f000000000000000000000000000000000000000000000000000000000000000081565b61048361047e366004612311565b610d4b565b6040516102289190612354565b61037d61049e366004612366565b610e07565b61040b6104b136600461213a565b610ef3565b61039d6104c4366004611dd8565b610f22565b6104dc6104d7366004611ea0565b610f44565b60408051921515835263ffffffff909116602083015201610228565b61039d610506366004611ea0565b610fe5565b61035d610519366004611e6c565b611005565b61021461052c366004611dd8565b61102e565b61054461053f366004611dd8565b6110b5565b604080516001600160a01b03909316835263ffffffff909116602083015201610228565b6102147f000000000000000000000000000000000000000000000000000000000000000081565b61026461059d366004611ea0565b611136565b6102147f000000000000000000000000000000000000000000000000000000000000000081565b6102646105d7366004611dd8565b611169565b61040b6105ea36600461213a565b611188565b5f5f60a65f6105fd85611194565b815260208101919091526040015f20546001600160a01b0316905080156106245780610629565b620e16e45b9392505050565b604080516060810182525f808252602082018190529181018290529061065f8561065986611194565b856111f7565b9695505050505050565b6001600160a01b0382165f908152609e6020526040812081908161068c85611194565b815260208082019290925260409081015f2081518083019092525460ff8116151580835261010090910463ffffffff16928201929092529150806106da5750806020015163ffffffff164311155b9150505b92915050565b6001600160a01b0381165f908152609d602052604081206060919061070890611363565b90505f816001600160401b0381111561072357610723611d0d565b60405190808252806020026020018201604052801561076757816020015b604080518082019091525f80825260208201528152602001906001900390816107415790505b5090505f5b828110156107f3576001600160a01b0385165f908152609d602052604090206107ce90610799908361136c565b604080518082019091525f80825260208201525060408051808201909152606082901c815263ffffffff909116602082015290565b8282815181106107e0576107e06123c1565b602090810291909101015260010161076c565b509392505050565b60208082015182516001600160a01b03165f9081526098909252604082206106de9163ffffffff9081169061137716565b606061083a8484844361138e565b949350505050565b60606108508585858561138e565b90505f5b84518110156108d857610880858281518110610872576108726123c1565b602002602001015187610669565b6108d0575f5b84518110156108ce575f8383815181106108a2576108a26123c1565b602002602001015182815181106108bb576108bb6123c1565b6020908102919091010152600101610886565b505b600101610854565b50949350505050565b6001600160a01b038082165f9081526097602052604081205490911680156109095780610629565b5090919050565b6001600160a01b0382165f908152609d60205260408120606091829161093590611363565b90505f816001600160401b0381111561095057610950611d0d565b60405190808252806020026020018201604052801561099457816020015b604080518082019091525f808252602082015281526020019060019003908161096e5790505b5090505f826001600160401b038111156109b0576109b0611d0d565b6040519080825280602002602001820160405280156109f957816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816109ce5790505b5090505f5b83811015610a7c576001600160a01b0388165f908152609d60205260408120610a2b90610799908461136c565b905080848381518110610a4057610a406123c1565b6020026020010181905250610a5689828a610630565b838381518110610a6857610a686123c1565b6020908102919091010152506001016109fe565b5090969095509350505050565b60605f61062960995f610a9b86611194565b81526020019081526020015f2061167b565b60605f83516001600160401b03811115610ac957610ac9611d0d565b604051908082528060200260200182016040528015610af2578160200160208202803683370190505b5090505f5b84518110156107f357610b23858281518110610b1557610b156123c1565b602002602001015185610ef3565b828281518110610b3557610b356123c1565b6001600160401b0390921660209283029190910190910152600101610af7565b5f60a55f610b6284611194565b81526020019081526020015f20549050919050565b60605f82516001600160401b03811115610b9357610b93611d0d565b604051908082528060200260200182016040528015610bbc578160200160208202803683370190505b5090505f5b83518110156107f357610bed85858381518110610be057610be06123c1565b6020026020010151610ef3565b828281518110610bff57610bff6123c1565b6001600160401b0390921660209283029190910190910152600101610bc1565b5f61062983609a5f610c3086611194565b81526020019081526020015f2061168790919063ffffffff16565b5f5f610c5784846116a8565b95945050505050565b60606106de609a5f610a9b85611194565b6001600160a01b0381165f908152609c6020526040812060609190610c9590611363565b90505f816001600160401b03811115610cb057610cb0611d0d565b604051908082528060200260200182016040528015610cf457816020015b604080518082019091525f8082526020820152815260200190600190039081610cce5790505b5090505f5b828110156107f3576001600160a01b0385165f908152609c60205260409020610d2690610799908361136c565b828281518110610d3857610d386123c1565b6020908102919091010152600101610cf9565b60605f84516001600160401b03811115610d6757610d67611d0d565b604051908082528060200260200182016040528015610db057816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610d855790505b5090505f5b85518110156108d857610de2868281518110610dd357610dd36123c1565b60200260200101518686610630565b828281518110610df457610df46123c1565b6020908102919091010152600101610db5565b60605f83516001600160401b03811115610e2357610e23611d0d565b604051908082528060200260200182016040528015610e4c578160200160208202803683370190505b5090505f5b84518110156108d8576001600160a01b0386165f90815260a1602052604081208651610ec192879291899086908110610e8c57610e8c6123c1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f2061181790919063ffffffff16565b828281518110610ed357610ed36123c1565b6001600160401b0390921660209283029190910190910152600101610e51565b6001600160a01b038083165f90815260a16020908152604080832093851683529290529081206106299061182b565b5f6106de609a5f610f3285611194565b81526020019081526020015f20611363565b6001600160a01b0381165f908152609b602090815260408083208151608081018352905463ffffffff80821680845260ff64010000000084041615159584018690526501000000000083048216948401949094526901000000000000000000909104166060820181905284939192919015801590610fcc5750826060015163ffffffff164310155b15610fdb575050604081015160015b9590945092505050565b6001600160a01b0381165f9081526098602052604081206106de90611363565b6001600160a01b0382165f908152609f60205260408120606091906106da9082610a9b86611194565b5f5f60a75f61103c85611194565b815260208082019290925260409081015f20815160608101835281546001600160a01b0390811680835260019093015490811694820194909452600160a01b90930463ffffffff16918301829052919250158015906110a55750816040015163ffffffff164310155b1561062957506020015192915050565b5f5f5f5f5f60a75f6110c688611194565b815260208082019290925260409081015f20815160608101835281546001600160a01b03908116825260019092015491821693810193909352600160a01b900463ffffffff1690820181905290915043101561112b5780602001519250806040015191505b509094909350915050565b5f5f61114183610c71565b90505f61114d846106e4565b9050611159848361183e565b8061083a575061083a848261183e565b5f620e16e4611177836105ef565b6001600160a01b0316141592915050565b5f5f6108d884846116a8565b5f815f0151826020015163ffffffff166040516020016111df92919060609290921b6bffffffffffffffffffffffff1916825260a01b6001600160a01b031916601482015260200190565b6040516020818303038152906040526106de906123d5565b6040805180820182525f80825260208083018290528351606081018552828152808201839052808501839052845180860186526001600160a01b03898116855260a18452868520908816855290925293822092939281906112579061182b565b6001600160401b0390811682526001600160a01b038981165f81815260a260209081526040808320948c168084529482528083205486169682019690965291815260a082528481208b8252825284812092815291815290839020835160608101855290549283168152600160401b8304600f0b91810191909152600160c01b90910463ffffffff169181018290529192504310156112f957909250905061135b565b61130a815f015182602001516118b6565b6001600160401b0316815260208101515f600f9190910b121561134857611339826020015182602001516118b6565b6001600160401b031660208301525b5f60408201819052602082015290925090505b935093915050565b5f6106de825490565b5f61062983836118d5565b5f8181526001830160205260408120541515610629565b606083516001600160401b038111156113a9576113a9611d0d565b6040519080825280602002602001820160405280156113dc57816020015b60608152602001906001900390816113c75790505b5090505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f0e0e67686866040518363ffffffff1660e01b815260040161142e9291906123fb565b5f60405180830381865afa158015611448573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261146f919081019061241f565b90505f5b8551811015611671575f86828151811061148f5761148f6123c1565b6020026020010151905085516001600160401b038111156114b2576114b2611d0d565b6040519080825280602002602001820160405280156114db578160200160208202803683370190505b508483815181106114ee576114ee6123c1565b60209081029190910101525f5b8651811015611667575f878281518110611517576115176123c1565b6020908102919091018101516001600160a01b038086165f90815260a18452604080822092841682529190935282209092506115529061182b565b9050806001600160401b03165f0361156b57505061165f565b5f611577858d85610630565b90508863ffffffff16816040015163ffffffff161115801561159f57505f8160200151600f0b125b156115c1576115b5815f015182602001516118b6565b6001600160401b031681525b80515f906115dc906001600160401b039081169085166118fb565b9050611623818989815181106115f4576115f46123c1565b6020026020010151878151811061160d5761160d6123c1565b602002602001015161190f90919063ffffffff16565b898881518110611635576116356123c1565b6020026020010151868151811061164e5761164e6123c1565b602002602001018181525050505050505b6001016114fb565b5050600101611473565b5050949350505050565b60605f61062983611923565b6001600160a01b0381165f9081526001830160205260408120541515610629565b6001600160a01b038281165f81815260a2602090815260408083209486168084529482528083205493835260a38252808320948352939052918220546001600160401b039091169190600f81810b600160801b909204900b03815b818110156117d3576001600160a01b038087165f90815260a360209081526040808320938916835292905290812061173b908361197c565b6001600160a01b038881165f90815260a0602090815260408083208584528252808320938b16835292815290829020825160608101845290546001600160401b0381168252600160401b8104600f0b92820192909252600160c01b90910463ffffffff169181018290529192504310156117b65750506117d3565b6117c48682602001516118b6565b95505050806001019050611703565b506001600160a01b038086165f90815260a16020908152604080832093881683529290522083906118039061182b565b61180d919061253f565b9150509250929050565b5f6106298383670de0b6b3a76400006119eb565b5f6106de82670de0b6b3a7640000611a41565b5f805b82518110156118ad5761186d84848381518110611860576118606123c1565b6020026020010151610669565b80156118965750611896838281518110611889576118896123c1565b6020026020010151611169565b156118a55760019150506106de565b600101611841565b505f9392505050565b5f6106296118cd836001600160401b03861661255e565b600f0b611a79565b5f825f0182815481106118ea576118ea6123c1565b905f5260205f200154905092915050565b5f61062983670de0b6b3a764000084611ae9565b5f6106298383670de0b6b3a7640000611ae9565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561197057602002820191905f5260205f20905b81548152602001906001019080831161195c575b50505050509050919050565b5f5f61199e61198a84611bce565b85546119999190600f0b61259d565b611c37565b8454909150600160801b9004600f90810b9082900b126119d157604051632d0483c560e21b815260040160405180910390fd5b600f0b5f9081526001939093016020525050604090205490565b82545f90816119fc86868385611ca0565b90508015611a3757611a2086611a136001846125c4565b5f91825260209091200190565b5464010000000090046001600160e01b031661065f565b5091949350505050565b81545f908015611a7157611a5a84611a136001846125c4565b5464010000000090046001600160e01b03166106da565b509092915050565b5f6001600160401b03821115611ae55760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084015b60405180910390fd5b5090565b5f80805f19858709858702925082811083820303915050805f03611b2057838281611b1657611b166125d7565b0492505050610629565b808411611b675760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b6044820152606401611adc565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f6001600160ff1b03821115611ae55760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401611adc565b80600f81900b8114611c9b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401611adc565b919050565b5f5b818310156107f3575f611cb58484611cf3565b5f8781526020902090915063ffffffff86169082015463ffffffff161115611cdf57809250611ced565b611cea8160016125eb565b93505b50611ca2565b5f611d0160028484186125fe565b610629908484166125eb565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715611d4957611d49611d0d565b604052919050565b6001600160a01b0381168114611d65575f5ffd5b50565b803563ffffffff81168114611c9b575f5ffd5b5f60408284031215611d8b575f5ffd5b604080519081016001600160401b0381118282101715611dad57611dad611d0d565b6040529050808235611dbe81611d51565b8152611dcc60208401611d68565b60208201525092915050565b5f60408284031215611de8575f5ffd5b6106298383611d7b565b5f5f5f60808486031215611e04575f5ffd5b8335611e0f81611d51565b9250611e1e8560208601611d7b565b91506060840135611e2e81611d51565b809150509250925092565b81516001600160401b03168152602080830151600f0b9082015260408083015163ffffffff1690820152606081016106de565b5f5f60608385031215611e7d575f5ffd5b8235611e8881611d51565b9150611e978460208501611d7b565b90509250929050565b5f60208284031215611eb0575f5ffd5b813561062981611d51565b5f8151808452602084019350602083015f5b82811015611f0657815180516001600160a01b0316875260209081015163ffffffff168188015260409096019590910190600101611ecd565b5093949350505050565b602081525f6106296020830184611ebb565b5f6001600160401b03821115611f3a57611f3a611d0d565b5060051b60200190565b5f82601f830112611f53575f5ffd5b8135611f66611f6182611f22565b611d21565b8082825260208201915060208360051b860101925085831115611f87575f5ffd5b602085015b83811015611fad578035611f9f81611d51565b835260209283019201611f8c565b5095945050505050565b5f5f5f60808486031215611fc9575f5ffd5b611fd38585611d7b565b925060408401356001600160401b03811115611fed575f5ffd5b611ff986828701611f44565b92505060608401356001600160401b03811115612014575f5ffd5b61202086828701611f44565b9150509250925092565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156120aa57868503603f19018452815180518087526020918201918701905f5b81811015612091578351835260209384019390920191600101612073565b5090965050506020938401939190910190600101612050565b50929695505050505050565b5f5f5f5f60a085870312156120c9575f5ffd5b6120d38686611d7b565b935060408501356001600160401b038111156120ed575f5ffd5b6120f987828801611f44565b93505060608501356001600160401b03811115612114575f5ffd5b61212087828801611f44565b92505061212f60808601611d68565b905092959194509250565b5f5f6040838503121561214b575f5ffd5b823561215681611d51565b9150602083013561216681611d51565b809150509250929050565b5f8151808452602084019350602083015f5b82811015611f06576121bc86835180516001600160401b03168252602080820151600f0b9083015260409081015163ffffffff16910152565b6060959095019460209190910190600101612183565b604081525f6121e46040830185611ebb565b8281036020840152610c578185612171565b5f8151808452602084019350602083015f5b82811015611f065781516001600160a01b0316865260209586019590910190600101612208565b602081525f61062960208301846121f6565b5f5f60408385031215612252575f5ffd5b82356001600160401b03811115612267575f5ffd5b61227385828601611f44565b925050602083013561216681611d51565b602080825282518282018190525f918401906040840190835b818110156122c45783516001600160401b031683526020938401939092019160010161229d565b509095945050505050565b5f5f604083850312156122e0575f5ffd5b82356122eb81611d51565b915060208301356001600160401b03811115612305575f5ffd5b61180d85828601611f44565b5f5f5f60808486031215612323575f5ffd5b83356001600160401b03811115612338575f5ffd5b61234486828701611f44565b935050611e1e8560208601611d7b565b602081525f6106296020830184612171565b5f5f5f60608486031215612378575f5ffd5b833561238381611d51565b925060208401356001600160401b0381111561239d575f5ffd5b6123a986828701611f44565b9250506123b860408501611d68565b90509250925092565b634e487b7160e01b5f52603260045260245ffd5b805160208083015191908110156123f5575f198160200360031b1b821691505b50919050565b604081525f61240d60408301856121f6565b8281036020840152610c5781856121f6565b5f6020828403121561242f575f5ffd5b81516001600160401b03811115612444575f5ffd5b8201601f81018413612454575f5ffd5b8051612462611f6182611f22565b8082825260208201915060208360051b850101925086831115612483575f5ffd5b602084015b838110156125205780516001600160401b038111156124a5575f5ffd5b8501603f810189136124b5575f5ffd5b60208101516124c6611f6182611f22565b808282526020820191506020808460051b8601010192508b8311156124e9575f5ffd5b6040840193505b8284101561250b5783518252602093840193909101906124f0565b86525050602093840193919091019050612488565b509695505050505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0382811682821603908111156106de576106de61252b565b600f81810b9083900b016f7fffffffffffffffffffffffffffffff81136f7fffffffffffffffffffffffffffffff19821217156106de576106de61252b565b8082018281125f8312801582168215821617156125bc576125bc61252b565b505092915050565b818103818111156106de576106de61252b565b634e487b7160e01b5f52601260045260245ffd5b808201808211156106de576106de61252b565b5f8261261857634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220800066159b94ad8279c77e9ea5168403873dfa0fd7176376207ccdac08ea7a9664736f6c634300081e003300000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f700000000000000000000000000000000000000000000000000000000000189c0000000000000000000000000000000000000000000000000000000000001ec30

Deployed Bytecode

0x608060405234801561000f575f5ffd5b50600436106101fd575f3560e01c80636e875dba11610114578063ba1a84e5116100a9578063db4df76111610079578063db4df76114610568578063dc2af6921461058f578063df5cf723146105a2578063f231bd08146105c9578063f605ce08146105dc575f5ffd5b8063ba1a84e5146104f8578063c221d8ae1461050b578063d4a3fcce1461051e578063d779485714610531575f5ffd5b806394d7d00c116100e457806394d7d00c14610490578063a9333ec8146104a3578063b2447af7146104b6578063b9fbaed1146104c9575f5ffd5b80636e875dba1461042357806379ae50cd146104365780637bc1ef61146104495780638ce6485414610470575f5ffd5b8063304c10cd116101955780634cfd2939116101655780634cfd29391461038a578063547afb87146103ab578063670d3ba2146103be57806367aeaa53146103d15780636cfb4481146103f8575f5ffd5b8063304c10cd1461031657806340120dab146103295780634177a87c1461034a5780634a10ffe51461036a575f5ffd5b8063260dc758116101d0578063260dc758146102945780632981eb77146102a75780632b453a9a146102e35780632bab2c4a14610303575f5ffd5b80630f3df50e1461020157806310e1b9b8146102315780631352c3e61461025157806315fe502814610274575b5f5ffd5b61021461020f366004611dd8565b6105ef565b6040516001600160a01b0390911681526020015b60405180910390f35b61024461023f366004611df2565b610630565b6040516102289190611e39565b61026461025f366004611e6c565b610669565b6040519015158152602001610228565b610287610282366004611ea0565b6106e4565b6040516102289190611f10565b6102646102a2366004611dd8565b6107fb565b6102ce7f00000000000000000000000000000000000000000000000000000000000189c081565b60405163ffffffff9091168152602001610228565b6102f66102f1366004611fb7565b61082c565b604051610228919061202a565b6102f66103113660046120b6565b610842565b610214610324366004611ea0565b6108e1565b61033c61033736600461213a565b610910565b6040516102289291906121d2565b61035d610358366004611dd8565b610a89565b604051610228919061222f565b61037d610378366004612241565b610aad565b6040516102289190612284565b61039d610398366004611dd8565b610b55565b604051908152602001610228565b61037d6103b93660046122cf565b610b77565b6102646103cc366004611e6c565b610c1f565b6102ce7f000000000000000000000000000000000000000000000000000000000001ec3081565b61040b61040636600461213a565b610c4b565b6040516001600160401b039091168152602001610228565b61035d610431366004611dd8565b610c60565b610287610444366004611ea0565b610c71565b6102ce7f000000000000000000000000000000000000000000000000000000000001ec3081565b61048361047e366004612311565b610d4b565b6040516102289190612354565b61037d61049e366004612366565b610e07565b61040b6104b136600461213a565b610ef3565b61039d6104c4366004611dd8565b610f22565b6104dc6104d7366004611ea0565b610f44565b60408051921515835263ffffffff909116602083015201610228565b61039d610506366004611ea0565b610fe5565b61035d610519366004611e6c565b611005565b61021461052c366004611dd8565b61102e565b61054461053f366004611dd8565b6110b5565b604080516001600160a01b03909316835263ffffffff909116602083015201610228565b6102147f000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f781565b61026461059d366004611ea0565b611136565b6102147f00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a81565b6102646105d7366004611dd8565b611169565b61040b6105ea36600461213a565b611188565b5f5f60a65f6105fd85611194565b815260208101919091526040015f20546001600160a01b0316905080156106245780610629565b620e16e45b9392505050565b604080516060810182525f808252602082018190529181018290529061065f8561065986611194565b856111f7565b9695505050505050565b6001600160a01b0382165f908152609e6020526040812081908161068c85611194565b815260208082019290925260409081015f2081518083019092525460ff8116151580835261010090910463ffffffff16928201929092529150806106da5750806020015163ffffffff164311155b9150505b92915050565b6001600160a01b0381165f908152609d602052604081206060919061070890611363565b90505f816001600160401b0381111561072357610723611d0d565b60405190808252806020026020018201604052801561076757816020015b604080518082019091525f80825260208201528152602001906001900390816107415790505b5090505f5b828110156107f3576001600160a01b0385165f908152609d602052604090206107ce90610799908361136c565b604080518082019091525f80825260208201525060408051808201909152606082901c815263ffffffff909116602082015290565b8282815181106107e0576107e06123c1565b602090810291909101015260010161076c565b509392505050565b60208082015182516001600160a01b03165f9081526098909252604082206106de9163ffffffff9081169061137716565b606061083a8484844361138e565b949350505050565b60606108508585858561138e565b90505f5b84518110156108d857610880858281518110610872576108726123c1565b602002602001015187610669565b6108d0575f5b84518110156108ce575f8383815181106108a2576108a26123c1565b602002602001015182815181106108bb576108bb6123c1565b6020908102919091010152600101610886565b505b600101610854565b50949350505050565b6001600160a01b038082165f9081526097602052604081205490911680156109095780610629565b5090919050565b6001600160a01b0382165f908152609d60205260408120606091829161093590611363565b90505f816001600160401b0381111561095057610950611d0d565b60405190808252806020026020018201604052801561099457816020015b604080518082019091525f808252602082015281526020019060019003908161096e5790505b5090505f826001600160401b038111156109b0576109b0611d0d565b6040519080825280602002602001820160405280156109f957816020015b604080516060810182525f80825260208083018290529282015282525f199092019101816109ce5790505b5090505f5b83811015610a7c576001600160a01b0388165f908152609d60205260408120610a2b90610799908461136c565b905080848381518110610a4057610a406123c1565b6020026020010181905250610a5689828a610630565b838381518110610a6857610a686123c1565b6020908102919091010152506001016109fe565b5090969095509350505050565b60605f61062960995f610a9b86611194565b81526020019081526020015f2061167b565b60605f83516001600160401b03811115610ac957610ac9611d0d565b604051908082528060200260200182016040528015610af2578160200160208202803683370190505b5090505f5b84518110156107f357610b23858281518110610b1557610b156123c1565b602002602001015185610ef3565b828281518110610b3557610b356123c1565b6001600160401b0390921660209283029190910190910152600101610af7565b5f60a55f610b6284611194565b81526020019081526020015f20549050919050565b60605f82516001600160401b03811115610b9357610b93611d0d565b604051908082528060200260200182016040528015610bbc578160200160208202803683370190505b5090505f5b83518110156107f357610bed85858381518110610be057610be06123c1565b6020026020010151610ef3565b828281518110610bff57610bff6123c1565b6001600160401b0390921660209283029190910190910152600101610bc1565b5f61062983609a5f610c3086611194565b81526020019081526020015f2061168790919063ffffffff16565b5f5f610c5784846116a8565b95945050505050565b60606106de609a5f610a9b85611194565b6001600160a01b0381165f908152609c6020526040812060609190610c9590611363565b90505f816001600160401b03811115610cb057610cb0611d0d565b604051908082528060200260200182016040528015610cf457816020015b604080518082019091525f8082526020820152815260200190600190039081610cce5790505b5090505f5b828110156107f3576001600160a01b0385165f908152609c60205260409020610d2690610799908361136c565b828281518110610d3857610d386123c1565b6020908102919091010152600101610cf9565b60605f84516001600160401b03811115610d6757610d67611d0d565b604051908082528060200260200182016040528015610db057816020015b604080516060810182525f80825260208083018290529282015282525f19909201910181610d855790505b5090505f5b85518110156108d857610de2868281518110610dd357610dd36123c1565b60200260200101518686610630565b828281518110610df457610df46123c1565b6020908102919091010152600101610db5565b60605f83516001600160401b03811115610e2357610e23611d0d565b604051908082528060200260200182016040528015610e4c578160200160208202803683370190505b5090505f5b84518110156108d8576001600160a01b0386165f90815260a1602052604081208651610ec192879291899086908110610e8c57610e8c6123c1565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f2061181790919063ffffffff16565b828281518110610ed357610ed36123c1565b6001600160401b0390921660209283029190910190910152600101610e51565b6001600160a01b038083165f90815260a16020908152604080832093851683529290529081206106299061182b565b5f6106de609a5f610f3285611194565b81526020019081526020015f20611363565b6001600160a01b0381165f908152609b602090815260408083208151608081018352905463ffffffff80821680845260ff64010000000084041615159584018690526501000000000083048216948401949094526901000000000000000000909104166060820181905284939192919015801590610fcc5750826060015163ffffffff164310155b15610fdb575050604081015160015b9590945092505050565b6001600160a01b0381165f9081526098602052604081206106de90611363565b6001600160a01b0382165f908152609f60205260408120606091906106da9082610a9b86611194565b5f5f60a75f61103c85611194565b815260208082019290925260409081015f20815160608101835281546001600160a01b0390811680835260019093015490811694820194909452600160a01b90930463ffffffff16918301829052919250158015906110a55750816040015163ffffffff164310155b1561062957506020015192915050565b5f5f5f5f5f60a75f6110c688611194565b815260208082019290925260409081015f20815160608101835281546001600160a01b03908116825260019092015491821693810193909352600160a01b900463ffffffff1690820181905290915043101561112b5780602001519250806040015191505b509094909350915050565b5f5f61114183610c71565b90505f61114d846106e4565b9050611159848361183e565b8061083a575061083a848261183e565b5f620e16e4611177836105ef565b6001600160a01b0316141592915050565b5f5f6108d884846116a8565b5f815f0151826020015163ffffffff166040516020016111df92919060609290921b6bffffffffffffffffffffffff1916825260a01b6001600160a01b031916601482015260200190565b6040516020818303038152906040526106de906123d5565b6040805180820182525f80825260208083018290528351606081018552828152808201839052808501839052845180860186526001600160a01b03898116855260a18452868520908816855290925293822092939281906112579061182b565b6001600160401b0390811682526001600160a01b038981165f81815260a260209081526040808320948c168084529482528083205486169682019690965291815260a082528481208b8252825284812092815291815290839020835160608101855290549283168152600160401b8304600f0b91810191909152600160c01b90910463ffffffff169181018290529192504310156112f957909250905061135b565b61130a815f015182602001516118b6565b6001600160401b0316815260208101515f600f9190910b121561134857611339826020015182602001516118b6565b6001600160401b031660208301525b5f60408201819052602082015290925090505b935093915050565b5f6106de825490565b5f61062983836118d5565b5f8181526001830160205260408120541515610629565b606083516001600160401b038111156113a9576113a9611d0d565b6040519080825280602002602001820160405280156113dc57816020015b60608152602001906001900390816113c75790505b5090505f7f00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a6001600160a01b031663f0e0e67686866040518363ffffffff1660e01b815260040161142e9291906123fb565b5f60405180830381865afa158015611448573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261146f919081019061241f565b90505f5b8551811015611671575f86828151811061148f5761148f6123c1565b6020026020010151905085516001600160401b038111156114b2576114b2611d0d565b6040519080825280602002602001820160405280156114db578160200160208202803683370190505b508483815181106114ee576114ee6123c1565b60209081029190910101525f5b8651811015611667575f878281518110611517576115176123c1565b6020908102919091018101516001600160a01b038086165f90815260a18452604080822092841682529190935282209092506115529061182b565b9050806001600160401b03165f0361156b57505061165f565b5f611577858d85610630565b90508863ffffffff16816040015163ffffffff161115801561159f57505f8160200151600f0b125b156115c1576115b5815f015182602001516118b6565b6001600160401b031681525b80515f906115dc906001600160401b039081169085166118fb565b9050611623818989815181106115f4576115f46123c1565b6020026020010151878151811061160d5761160d6123c1565b602002602001015161190f90919063ffffffff16565b898881518110611635576116356123c1565b6020026020010151868151811061164e5761164e6123c1565b602002602001018181525050505050505b6001016114fb565b5050600101611473565b5050949350505050565b60605f61062983611923565b6001600160a01b0381165f9081526001830160205260408120541515610629565b6001600160a01b038281165f81815260a2602090815260408083209486168084529482528083205493835260a38252808320948352939052918220546001600160401b039091169190600f81810b600160801b909204900b03815b818110156117d3576001600160a01b038087165f90815260a360209081526040808320938916835292905290812061173b908361197c565b6001600160a01b038881165f90815260a0602090815260408083208584528252808320938b16835292815290829020825160608101845290546001600160401b0381168252600160401b8104600f0b92820192909252600160c01b90910463ffffffff169181018290529192504310156117b65750506117d3565b6117c48682602001516118b6565b95505050806001019050611703565b506001600160a01b038086165f90815260a16020908152604080832093881683529290522083906118039061182b565b61180d919061253f565b9150509250929050565b5f6106298383670de0b6b3a76400006119eb565b5f6106de82670de0b6b3a7640000611a41565b5f805b82518110156118ad5761186d84848381518110611860576118606123c1565b6020026020010151610669565b80156118965750611896838281518110611889576118896123c1565b6020026020010151611169565b156118a55760019150506106de565b600101611841565b505f9392505050565b5f6106296118cd836001600160401b03861661255e565b600f0b611a79565b5f825f0182815481106118ea576118ea6123c1565b905f5260205f200154905092915050565b5f61062983670de0b6b3a764000084611ae9565b5f6106298383670de0b6b3a7640000611ae9565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561197057602002820191905f5260205f20905b81548152602001906001019080831161195c575b50505050509050919050565b5f5f61199e61198a84611bce565b85546119999190600f0b61259d565b611c37565b8454909150600160801b9004600f90810b9082900b126119d157604051632d0483c560e21b815260040160405180910390fd5b600f0b5f9081526001939093016020525050604090205490565b82545f90816119fc86868385611ca0565b90508015611a3757611a2086611a136001846125c4565b5f91825260209091200190565b5464010000000090046001600160e01b031661065f565b5091949350505050565b81545f908015611a7157611a5a84611a136001846125c4565b5464010000000090046001600160e01b03166106da565b509092915050565b5f6001600160401b03821115611ae55760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b60648201526084015b60405180910390fd5b5090565b5f80805f19858709858702925082811083820303915050805f03611b2057838281611b1657611b166125d7565b0492505050610629565b808411611b675760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b6044820152606401611adc565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b5f6001600160ff1b03821115611ae55760405162461bcd60e51b815260206004820152602860248201527f53616665436173743a2076616c756520646f65736e27742066697420696e2061604482015267371034b73a191a9b60c11b6064820152608401611adc565b80600f81900b8114611c9b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20316044820152663238206269747360c81b6064820152608401611adc565b919050565b5f5b818310156107f3575f611cb58484611cf3565b5f8781526020902090915063ffffffff86169082015463ffffffff161115611cdf57809250611ced565b611cea8160016125eb565b93505b50611ca2565b5f611d0160028484186125fe565b610629908484166125eb565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b0381118282101715611d4957611d49611d0d565b604052919050565b6001600160a01b0381168114611d65575f5ffd5b50565b803563ffffffff81168114611c9b575f5ffd5b5f60408284031215611d8b575f5ffd5b604080519081016001600160401b0381118282101715611dad57611dad611d0d565b6040529050808235611dbe81611d51565b8152611dcc60208401611d68565b60208201525092915050565b5f60408284031215611de8575f5ffd5b6106298383611d7b565b5f5f5f60808486031215611e04575f5ffd5b8335611e0f81611d51565b9250611e1e8560208601611d7b565b91506060840135611e2e81611d51565b809150509250925092565b81516001600160401b03168152602080830151600f0b9082015260408083015163ffffffff1690820152606081016106de565b5f5f60608385031215611e7d575f5ffd5b8235611e8881611d51565b9150611e978460208501611d7b565b90509250929050565b5f60208284031215611eb0575f5ffd5b813561062981611d51565b5f8151808452602084019350602083015f5b82811015611f0657815180516001600160a01b0316875260209081015163ffffffff168188015260409096019590910190600101611ecd565b5093949350505050565b602081525f6106296020830184611ebb565b5f6001600160401b03821115611f3a57611f3a611d0d565b5060051b60200190565b5f82601f830112611f53575f5ffd5b8135611f66611f6182611f22565b611d21565b8082825260208201915060208360051b860101925085831115611f87575f5ffd5b602085015b83811015611fad578035611f9f81611d51565b835260209283019201611f8c565b5095945050505050565b5f5f5f60808486031215611fc9575f5ffd5b611fd38585611d7b565b925060408401356001600160401b03811115611fed575f5ffd5b611ff986828701611f44565b92505060608401356001600160401b03811115612014575f5ffd5b61202086828701611f44565b9150509250925092565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156120aa57868503603f19018452815180518087526020918201918701905f5b81811015612091578351835260209384019390920191600101612073565b5090965050506020938401939190910190600101612050565b50929695505050505050565b5f5f5f5f60a085870312156120c9575f5ffd5b6120d38686611d7b565b935060408501356001600160401b038111156120ed575f5ffd5b6120f987828801611f44565b93505060608501356001600160401b03811115612114575f5ffd5b61212087828801611f44565b92505061212f60808601611d68565b905092959194509250565b5f5f6040838503121561214b575f5ffd5b823561215681611d51565b9150602083013561216681611d51565b809150509250929050565b5f8151808452602084019350602083015f5b82811015611f06576121bc86835180516001600160401b03168252602080820151600f0b9083015260409081015163ffffffff16910152565b6060959095019460209190910190600101612183565b604081525f6121e46040830185611ebb565b8281036020840152610c578185612171565b5f8151808452602084019350602083015f5b82811015611f065781516001600160a01b0316865260209586019590910190600101612208565b602081525f61062960208301846121f6565b5f5f60408385031215612252575f5ffd5b82356001600160401b03811115612267575f5ffd5b61227385828601611f44565b925050602083013561216681611d51565b602080825282518282018190525f918401906040840190835b818110156122c45783516001600160401b031683526020938401939092019160010161229d565b509095945050505050565b5f5f604083850312156122e0575f5ffd5b82356122eb81611d51565b915060208301356001600160401b03811115612305575f5ffd5b61180d85828601611f44565b5f5f5f60808486031215612323575f5ffd5b83356001600160401b03811115612338575f5ffd5b61234486828701611f44565b935050611e1e8560208601611d7b565b602081525f6106296020830184612171565b5f5f5f60608486031215612378575f5ffd5b833561238381611d51565b925060208401356001600160401b0381111561239d575f5ffd5b6123a986828701611f44565b9250506123b860408501611d68565b90509250925092565b634e487b7160e01b5f52603260045260245ffd5b805160208083015191908110156123f5575f198160200360031b1b821691505b50919050565b604081525f61240d60408301856121f6565b8281036020840152610c5781856121f6565b5f6020828403121561242f575f5ffd5b81516001600160401b03811115612444575f5ffd5b8201601f81018413612454575f5ffd5b8051612462611f6182611f22565b8082825260208201915060208360051b850101925086831115612483575f5ffd5b602084015b838110156125205780516001600160401b038111156124a5575f5ffd5b8501603f810189136124b5575f5ffd5b60208101516124c6611f6182611f22565b808282526020820191506020808460051b8601010192508b8311156124e9575f5ffd5b6040840193505b8284101561250b5783518252602093840193909101906124f0565b86525050602093840193919091019050612488565b509695505050505050565b634e487b7160e01b5f52601160045260245ffd5b6001600160401b0382811682821603908111156106de576106de61252b565b600f81810b9083900b016f7fffffffffffffffffffffffffffffff81136f7fffffffffffffffffffffffffffffff19821217156106de576106de61252b565b8082018281125f8312801582168215821617156125bc576125bc61252b565b505092915050565b818103818111156106de576106de61252b565b634e487b7160e01b5f52601260045260245ffd5b808201808211156106de576106de61252b565b5f8261261857634e487b7160e01b5f52601260045260245ffd5b50049056fea2646970667358221220800066159b94ad8279c77e9ea5168403873dfa0fd7176376207ccdac08ea7a9664736f6c634300081e0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f700000000000000000000000000000000000000000000000000000000000189c0000000000000000000000000000000000000000000000000000000000001ec30

-----Decoded View---------------
Arg [0] : _delegation (address): 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A
Arg [1] : _eigenStrategy (address): 0xaCB55C530Acdb2849e6d4f36992Cd8c9D50ED8F7
Arg [2] : _DEALLOCATION_DELAY (uint32): 100800
Arg [3] : _ALLOCATION_CONFIGURATION_DELAY (uint32): 126000

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a
Arg [1] : 000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f7
Arg [2] : 00000000000000000000000000000000000000000000000000000000000189c0
Arg [3] : 000000000000000000000000000000000000000000000000000000000001ec30


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.