Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AllocationManagerView
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 200 runs
Other Settings:
prague EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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;
}
}// 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;
}
}// 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)
}
}
}// 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)
});
}
}// 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);
}
}
}// 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);
}
}{
"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
- No Contract Security Audit Submitted- Submit Audit Here
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"}]Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.