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
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
AllocationManager
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.27;
import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin-upgrades/contracts/security/ReentrancyGuardUpgradeable.sol";
import "../mixins/Deprecated_OwnableUpgradeable.sol";
import "../mixins/SplitContractMixin.sol";
import "../mixins/PermissionControllerMixin.sol";
import "../permissions/Pausable.sol";
import "../libraries/SlashingLib.sol";
import "../libraries/OperatorSetLib.sol";
import "./storage/AllocationManagerStorage.sol";
contract AllocationManager is
Initializable,
Deprecated_OwnableUpgradeable,
Pausable,
AllocationManagerStorage,
ReentrancyGuardUpgradeable,
PermissionControllerMixin,
SplitContractMixin,
IAllocationManager
{
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(
IAllocationManagerView _allocationManagerView,
IDelegationManager _delegation,
IStrategy _eigenStrategy,
IPauserRegistry _pauserRegistry,
IPermissionController _permissionController,
uint32 _DEALLOCATION_DELAY,
uint32 _ALLOCATION_CONFIGURATION_DELAY
)
AllocationManagerStorage(_delegation, _eigenStrategy, _DEALLOCATION_DELAY, _ALLOCATION_CONFIGURATION_DELAY)
Pausable(_pauserRegistry)
SplitContractMixin(address(_allocationManagerView))
PermissionControllerMixin(_permissionController)
{
_disableInitializers();
}
/// @inheritdoc IAllocationManagerActions
function initialize(
uint256 initialPausedStatus
) external initializer {
_setPausedStatus(initialPausedStatus);
}
/// @inheritdoc IAllocationManagerActions
function slashOperator(
address avs,
SlashingParams calldata params
) external onlyWhenNotPaused(PAUSED_OPERATOR_SLASHING) returns (uint256, uint256[] memory) {
// Check that the operator set exists and the operator is registered to it
OperatorSet memory operatorSet = OperatorSet(avs, params.operatorSetId);
require(params.strategies.length == params.wadsToSlash.length, InputArrayLengthMismatch());
require(_operatorSets[operatorSet.avs].contains(operatorSet.id), InvalidOperatorSet());
require(isOperatorSlashable(params.operator, operatorSet), OperatorNotSlashable());
// Assert that the caller is the slasher for the operator set
require(msg.sender == getSlasher(operatorSet), InvalidCaller());
return _slashOperator(params, operatorSet);
}
/// @inheritdoc IAllocationManagerActions
function modifyAllocations(
address operator,
AllocateParams[] memory params
) external onlyWhenNotPaused(PAUSED_MODIFY_ALLOCATIONS) {
// Check that the caller is allowed to modify allocations on behalf of the operator
// We do not use a modifier to avoid `stack too deep` errors
_checkCanCall(operator);
// Check that the operator exists and has configured an allocation delay
uint32 operatorAllocationDelay;
{
(bool isSet, uint32 delay) = getAllocationDelay(operator);
require(isSet, UninitializedAllocationDelay());
operatorAllocationDelay = delay;
}
for (uint256 i = 0; i < params.length; i++) {
require(params[i].strategies.length == params[i].newMagnitudes.length, InputArrayLengthMismatch());
// Check that the operator set exists and get the operator's registration status
// Operators do not need to be registered for an operator set in order to allocate
// slashable magnitude to the set. In fact, it is expected that operators will
// allocate magnitude before registering, as AVS's will likely only accept
// registrations from operators that are already slashable.
OperatorSet memory operatorSet = params[i].operatorSet;
require(_operatorSets[operatorSet.avs].contains(operatorSet.id), InvalidOperatorSet());
bool _isOperatorSlashable = isOperatorSlashable(operator, operatorSet);
for (uint256 j = 0; j < params[i].strategies.length; j++) {
IStrategy strategy = params[i].strategies[j];
// 1. If the operator has any pending deallocations for this strategy, clear them
// to free up magnitude for allocation. Fetch the operator's up to date allocation
// info and ensure there is no remaining pending modification.
_clearDeallocationQueue(operator, strategy, type(uint16).max);
(StrategyInfo memory info, Allocation memory allocation) =
_getUpdatedAllocation(operator, operatorSet.key(), strategy);
require(allocation.effectBlock == 0, ModificationAlreadyPending());
// 2. Check whether the operator's allocation is slashable. If not, we allow instant
// deallocation.
bool isSlashable = _isAllocationSlashable(operatorSet, strategy, allocation, _isOperatorSlashable);
// 3. Calculate the change in magnitude
allocation.pendingDiff = _calcDelta(allocation.currentMagnitude, params[i].newMagnitudes[j]);
require(allocation.pendingDiff != 0, SameMagnitude());
// 4. Handle deallocation/allocation
if (allocation.pendingDiff < 0) {
if (isSlashable) {
// If the operator is slashable, deallocated magnitude will be freed after
// the deallocation delay. This magnitude remains slashable until then.
deallocationQueue[operator][strategy].pushBack(operatorSet.key());
// deallocations are slashable in the window [block.number, block.number + deallocationDelay]
// therefore, the effectBlock is set to the block right after the slashable window
allocation.effectBlock = uint32(block.number) + DEALLOCATION_DELAY + 1;
} else {
// Deallocation immediately updates/frees magnitude if the operator is not slashable
info.encumberedMagnitude = _addInt128(info.encumberedMagnitude, allocation.pendingDiff);
allocation.currentMagnitude = params[i].newMagnitudes[j];
allocation.pendingDiff = 0;
allocation.effectBlock = uint32(block.number);
}
} else if (allocation.pendingDiff > 0) {
// Allocation immediately consumes available magnitude, but the additional
// magnitude does not become slashable until after the allocation delay
info.encumberedMagnitude = _addInt128(info.encumberedMagnitude, allocation.pendingDiff);
require(info.encumberedMagnitude <= info.maxMagnitude, InsufficientMagnitude());
allocation.effectBlock = uint32(block.number) + operatorAllocationDelay;
}
// 5. Update state
_updateAllocationInfo(operator, operatorSet.key(), strategy, info, allocation);
// 6. Emit an event for the updated allocation
emit AllocationUpdated(
operator,
operatorSet,
strategy,
_addInt128(allocation.currentMagnitude, allocation.pendingDiff),
allocation.effectBlock
);
}
}
}
/// @inheritdoc IAllocationManagerActions
function clearDeallocationQueue(
address operator,
IStrategy[] calldata strategies,
uint16[] calldata numToClear
) external onlyWhenNotPaused(PAUSED_MODIFY_ALLOCATIONS) {
require(strategies.length == numToClear.length, InputArrayLengthMismatch());
for (uint256 i = 0; i < strategies.length; ++i) {
_clearDeallocationQueue({operator: operator, strategy: strategies[i], numToClear: numToClear[i]});
}
}
/// @inheritdoc IAllocationManagerActions
function registerForOperatorSets(
address operator,
RegisterParams calldata params
) external onlyWhenNotPaused(PAUSED_OPERATOR_SET_REGISTRATION_AND_DEREGISTRATION) checkCanCall(operator) {
// Check if the operator has registered.
require(delegation.isOperator(operator), InvalidOperator());
for (uint256 i = 0; i < params.operatorSetIds.length; i++) {
// Check the operator set exists and the operator is not currently registered to it
OperatorSet memory operatorSet = OperatorSet(params.avs, params.operatorSetIds[i]);
require(_operatorSets[operatorSet.avs].contains(operatorSet.id), InvalidOperatorSet());
require(!isOperatorSlashable(operator, operatorSet), AlreadyMemberOfSet());
// Add operator to operator set
registeredSets[operator].add(operatorSet.key());
_operatorSetMembers[operatorSet.key()].add(operator);
emit OperatorAddedToOperatorSet(operator, operatorSet);
// Mark the operator registered
registrationStatus[operator][operatorSet.key()].registered = true;
}
// Call the AVS to complete registration. If the AVS reverts, registration will fail.
getAVSRegistrar(params.avs).registerOperator(operator, params.avs, params.operatorSetIds, params.data);
}
/// @inheritdoc IAllocationManagerActions
function deregisterFromOperatorSets(
DeregisterParams calldata params
) external onlyWhenNotPaused(PAUSED_OPERATOR_SET_REGISTRATION_AND_DEREGISTRATION) {
// Check that the caller is either authorized on behalf of the operator or AVS
require(_canCall(params.operator) || _canCall(params.avs), InvalidCaller());
for (uint256 i = 0; i < params.operatorSetIds.length; i++) {
// Check the operator set exists and the operator is registered to it
OperatorSet memory operatorSet = OperatorSet(params.avs, params.operatorSetIds[i]);
require(_operatorSets[params.avs].contains(operatorSet.id), InvalidOperatorSet());
require(registrationStatus[params.operator][operatorSet.key()].registered, NotMemberOfSet());
// Remove operator from operator set
registeredSets[params.operator].remove(operatorSet.key());
_operatorSetMembers[operatorSet.key()].remove(params.operator);
emit OperatorRemovedFromOperatorSet(params.operator, operatorSet);
// Mark operator deregistered until the DEALLOCATION_DELAY passes
// forgefmt: disable-next-item
registrationStatus[params.operator][operatorSet.key()] = RegistrationStatus({
registered: false,
slashableUntil: uint32(block.number) + DEALLOCATION_DELAY
});
}
// Call the AVS to complete deregistration
getAVSRegistrar(params.avs).deregisterOperator(params.operator, params.avs, params.operatorSetIds);
}
/// @inheritdoc IAllocationManagerActions
function setAllocationDelay(
address operator,
uint32 delay
) external {
/// If the caller is the delegationManager, the operator is newly registered
/// This results in *newly-registered* operators in the core protocol to have their allocation delay effective immediately
bool newlyRegistered = (msg.sender == address(delegation));
// If we're not newly registered, check that the caller (not the delegationManager) is authorized to set the allocation delay for the operator
if (!newlyRegistered) {
_checkCanCall(operator);
require(delegation.isOperator(operator), InvalidOperator());
}
_setAllocationDelay(operator, delay, newlyRegistered);
}
/// @inheritdoc IAllocationManagerActions
function setAVSRegistrar(
address avs,
IAVSRegistrar registrar
) external checkCanCall(avs) {
// Check that the registrar is correctly configured to prevent an AVSRegistrar contract
// from being used with the wrong AVS
require(registrar.supportsAVS(avs), InvalidAVSRegistrar());
_avsRegistrar[avs] = registrar;
emit AVSRegistrarSet(avs, getAVSRegistrar(avs));
}
/// @inheritdoc IAllocationManagerActions
function updateAVSMetadataURI(
address avs,
string calldata metadataURI
) external checkCanCall(avs) {
if (!_avsRegisteredMetadata[avs]) _avsRegisteredMetadata[avs] = true;
emit AVSMetadataURIUpdated(avs, metadataURI);
}
/// @inheritdoc IAllocationManagerActions
/// @notice This function will be deprecated in Early Q2 2026 in favor of `createOperatorSets` which takes in `CreateSetParamsV2`
function createOperatorSets(
address avs,
CreateSetParams[] calldata params
) external checkCanCall(avs) {
createOperatorSets(avs, _convertCreateSetParams(params, avs));
}
/// @inheritdoc IAllocationManagerActions
function createOperatorSets(
address avs,
CreateSetParamsV2[] memory params
) public checkCanCall(avs) {
require(_avsRegisteredMetadata[avs], NonexistentAVSMetadata());
for (uint256 i = 0; i < params.length; i++) {
_createOperatorSet(avs, params[i], DEFAULT_BURN_ADDRESS);
}
}
/// @inheritdoc IAllocationManagerActions
/// @notice This function will be deprecated in Early Q2 2026 in favor of `createRedistributingOperatorSets` which takes in `CreateSetParamsV2`
function createRedistributingOperatorSets(
address avs,
CreateSetParams[] calldata params,
address[] calldata redistributionRecipients
) external checkCanCall(avs) {
createRedistributingOperatorSets(avs, _convertCreateSetParams(params, avs), redistributionRecipients);
}
/// @inheritdoc IAllocationManagerActions
function createRedistributingOperatorSets(
address avs,
CreateSetParamsV2[] memory params,
address[] calldata redistributionRecipients
) public checkCanCall(avs) {
require(params.length == redistributionRecipients.length, InputArrayLengthMismatch());
require(_avsRegisteredMetadata[avs], NonexistentAVSMetadata());
for (uint256 i = 0; i < params.length; i++) {
address recipient = redistributionRecipients[i];
require(recipient != address(0), InputAddressZero());
require(recipient != DEFAULT_BURN_ADDRESS, InvalidRedistributionRecipient());
_createOperatorSet(avs, params[i], recipient);
}
}
/// @inheritdoc IAllocationManagerActions
function addStrategiesToOperatorSet(
address avs,
uint32 operatorSetId,
IStrategy[] calldata strategies
) external checkCanCall(avs) {
OperatorSet memory operatorSet = OperatorSet(avs, operatorSetId);
require(_operatorSets[avs].contains(operatorSet.id), InvalidOperatorSet());
for (uint256 i = 0; i < strategies.length; i++) {
_addStrategyToOperatorSet(
operatorSet, strategies[i], isRedistributingOperatorSet(OperatorSet(avs, operatorSetId))
);
}
}
/// @inheritdoc IAllocationManagerActions
function removeStrategiesFromOperatorSet(
address avs,
uint32 operatorSetId,
IStrategy[] calldata strategies
) external checkCanCall(avs) {
OperatorSet memory operatorSet = OperatorSet(avs, operatorSetId);
require(_operatorSets[avs].contains(operatorSet.id), InvalidOperatorSet());
bytes32 operatorSetKey = operatorSet.key();
for (uint256 i = 0; i < strategies.length; i++) {
require(_operatorSetStrategies[operatorSetKey].remove(address(strategies[i])), StrategyNotInOperatorSet());
emit StrategyRemovedFromOperatorSet(operatorSet, strategies[i]);
}
}
/// @inheritdoc IAllocationManagerActions
function updateSlasher(
OperatorSet memory operatorSet,
address slasher
) external checkCanCall(operatorSet.avs) {
require(_operatorSets[operatorSet.avs].contains(operatorSet.id), InvalidOperatorSet());
// Prevent updating a slasher if one is not already set
// A slasher is set either on operatorSet creation or, for operatorSets created prior to v1.9.0, via `migrateSlashers`
require(getSlasher(operatorSet) != address(0), SlasherNotSet());
_updateSlasher({operatorSet: operatorSet, slasher: slasher, instantEffectBlock: false});
}
/// @inheritdoc IAllocationManagerActions
/// @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 {
for (uint256 i = 0; i < operatorSets.length; i++) {
// If the operatorSet does not exist, continue
if (!_operatorSets[operatorSets[i].avs].contains(operatorSets[i].id)) {
continue;
}
// If the slasher is already set, continue
if (getSlasher(operatorSets[i]) != address(0)) {
continue;
}
// Get the slasher from the permission controller.
address[] memory slashers =
permissionController.getAppointees(operatorSets[i].avs, address(this), this.slashOperator.selector);
address slasher;
// If there are no slashers or the first slasher is the 0 address, set the slasher to the AVS
if (slashers.length == 0 || slashers[0] == address(0)) {
slasher = operatorSets[i].avs;
// Else, set the slasher to the first slasher
} else {
slasher = slashers[0];
}
_updateSlasher({operatorSet: operatorSets[i], slasher: slasher, instantEffectBlock: true});
emit SlasherMigrated(operatorSets[i], slasher);
}
}
///
/// INTERNAL FUNCTIONS
///
/// @dev Slashes an operator.
/// @param params The slashing parameters. See IAllocationManager.sol#slashOperator for specifics.
/// @param operatorSet The operator set from which the operator is being slashed.
/// @return slashId The operator set's unique identifier for the slash.
/// @return shares The number of shares to be burned or redistributed for each strategy that was slashed.
function _slashOperator(
SlashingParams calldata params,
OperatorSet memory operatorSet
) internal returns (uint256 slashId, uint256[] memory shares) {
uint256[] memory wadSlashed = new uint256[](params.strategies.length);
shares = new uint256[](params.strategies.length);
// Increment the slash count for the operator set.
slashId = ++_slashIds[operatorSet.key()];
// For each strategy in the operator set, slash any existing allocation
for (uint256 i = 0; i < params.strategies.length; i++) {
// Check that `strategies` is in ascending order.
require(
i == 0 || uint160(address(params.strategies[i])) > uint160(address(params.strategies[i - 1])),
StrategiesMustBeInAscendingOrder()
);
// Check that `wadToSlash` is within acceptable bounds.
require(0 < params.wadsToSlash[i] && params.wadsToSlash[i] <= WAD, InvalidWadToSlash());
// Check that the operator set contains the strategy.
require(
_operatorSetStrategies[operatorSet.key()].contains(address(params.strategies[i])),
StrategyNotInOperatorSet()
);
// 1. Get the operator's allocation info for the strategy and operator set
(StrategyInfo memory info, Allocation memory allocation) =
_getUpdatedAllocation(params.operator, operatorSet.key(), params.strategies[i]);
// 2. Skip if the operator does not have a slashable allocation
// NOTE: this "if" is equivalent to: `if (!_isAllocationSlashable)`, because the other
// conditions in this method are already true (isOperatorSlashable + operatorSetStrategies.contains)
if (allocation.currentMagnitude == 0) {
continue;
}
// 3. Calculate the amount of magnitude being slashed, and subtract from
// the operator's currently-allocated magnitude, as well as the strategy's
// max and encumbered magnitudes
uint64 slashedMagnitude = uint64(uint256(allocation.currentMagnitude).mulWadRoundUp(params.wadsToSlash[i]));
uint64 prevMaxMagnitude = info.maxMagnitude;
wadSlashed[i] = uint256(slashedMagnitude).divWad(info.maxMagnitude);
allocation.currentMagnitude -= slashedMagnitude;
info.maxMagnitude -= slashedMagnitude;
info.encumberedMagnitude -= slashedMagnitude;
// 4. If there is a pending deallocation, reduce the pending deallocation proportionally.
// This ensures that when the deallocation is completed, less magnitude is freed.
if (allocation.pendingDiff < 0) {
uint64 slashedPending =
uint64(uint256(uint128(-allocation.pendingDiff)).mulWadRoundUp(params.wadsToSlash[i]));
allocation.pendingDiff += int128(uint128(slashedPending));
emit AllocationUpdated(
params.operator,
operatorSet,
params.strategies[i],
_addInt128(allocation.currentMagnitude, allocation.pendingDiff),
allocation.effectBlock
);
}
// 5. Update state
_updateAllocationInfo(params.operator, operatorSet.key(), params.strategies[i], info, allocation);
// Emit an event for the updated allocation
emit AllocationUpdated(
params.operator,
operatorSet,
params.strategies[i],
allocation.currentMagnitude,
uint32(block.number)
);
_updateMaxMagnitude(params.operator, params.strategies[i], info.maxMagnitude);
// 6. Slash operators shares in the DelegationManager
shares[i] = delegation.slashOperatorShares({
operator: params.operator,
operatorSet: operatorSet,
slashId: slashId,
strategy: params.strategies[i],
prevMaxMagnitude: prevMaxMagnitude,
newMaxMagnitude: info.maxMagnitude
});
}
emit OperatorSlashed(params.operator, operatorSet, params.strategies, wadSlashed, params.description);
}
/// @dev Adds a strategy to an operator set.
/// @param operatorSet The operator set to add the strategy to.
/// @param strategy The strategy to add to the operator set.
/// @param isRedistributing Whether the operator set is redistributing.
function _addStrategyToOperatorSet(
OperatorSet memory operatorSet,
IStrategy strategy,
bool isRedistributing
) internal {
// We do not currently support redistributing beaconchain ETH or EIGEN.
if (isRedistributing) {
require(strategy != BEACONCHAIN_ETH_STRAT && strategy != eigenStrategy, InvalidStrategy());
}
require(_operatorSetStrategies[operatorSet.key()].add(address(strategy)), StrategyAlreadyInOperatorSet());
emit StrategyAddedToOperatorSet(operatorSet, strategy);
}
/// @notice Creates a new operator set for an AVS.
/// @param avs The AVS address that owns the operator set.
/// @param params The parameters for creating the operator set.
/// @param redistributionRecipient Address to receive redistributed funds when operators are slashed.
/// @dev If `redistributionRecipient` is address(0), the operator set is considered non-redistributing
/// and slashed funds are sent to the `DEFAULT_BURN_ADDRESS`.
/// @dev Providing `BEACONCHAIN_ETH_STRAT` as a strategy will revert since it's not currently supported.
/// @dev The address that can slash the operatorSet is the `avs` address.
function _createOperatorSet(
address avs,
CreateSetParamsV2 memory params,
address redistributionRecipient
) internal {
OperatorSet memory operatorSet = OperatorSet(avs, params.operatorSetId);
// Create the operator set, ensuring it does not already exist.
require(_operatorSets[avs].add(operatorSet.id), InvalidOperatorSet());
emit OperatorSetCreated(operatorSet);
bool isRedistributing = redistributionRecipient != DEFAULT_BURN_ADDRESS;
if (isRedistributing) {
_redistributionRecipients[operatorSet.key()] = redistributionRecipient;
emit RedistributionAddressSet(operatorSet, redistributionRecipient);
}
for (uint256 j = 0; j < params.strategies.length; j++) {
_addStrategyToOperatorSet(operatorSet, params.strategies[j], isRedistributing);
}
// Update the slasher for the operator set
_updateSlasher({operatorSet: operatorSet, slasher: params.slasher, instantEffectBlock: true});
}
/// @dev Clear one or more pending deallocations to a strategy's allocated magnitude
/// @param operator the operator whose pending deallocations will be cleared
/// @param strategy the strategy to update
/// @param numToClear the number of pending deallocations to clear
function _clearDeallocationQueue(
address operator,
IStrategy strategy,
uint16 numToClear
) internal {
uint256 numCleared;
uint256 length = deallocationQueue[operator][strategy].length();
while (length > 0 && numCleared < numToClear) {
bytes32 operatorSetKey = deallocationQueue[operator][strategy].front();
(StrategyInfo memory info, Allocation memory allocation) =
_getUpdatedAllocation(operator, operatorSetKey, strategy);
// If we've reached a pending deallocation that isn't completable yet,
// we can stop. Any subsequent deallocation will also be uncompletable.
if (block.number < allocation.effectBlock) {
break;
}
// Update state. This completes the deallocation, because `_getUpdatedAllocation`
// gave us strategy/allocation info as if the deallocation was already completed.
_updateAllocationInfo(operator, operatorSetKey, strategy, info, allocation);
// Remove the deallocation from the queue
deallocationQueue[operator][strategy].popFront();
++numCleared;
--length;
}
}
/// @dev Sets the operator's allocation delay. This 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.
/// @param newlyRegistered Whether the operator is newly registered in the core protocol.
function _setAllocationDelay(
address operator,
uint32 delay,
bool newlyRegistered
) internal {
AllocationDelayInfo memory info = _allocationDelayInfo[operator];
// If there is a pending delay that can be applied now, set it
if (info.effectBlock != 0 && block.number >= info.effectBlock) {
info.delay = info.pendingDelay;
info.isSet = true;
}
info.pendingDelay = delay;
/// If the caller is the delegationManager, the operator is newly registered
/// This results in *newly-registered* operators in the core protocol to have their allocation delay effective immediately
if (newlyRegistered) {
// Update delay and isSet immediately for storage consistency
info.delay = delay;
info.isSet = true;
info.effectBlock = uint32(block.number);
} else {
// Wait the entire configuration delay before the delay takes effect
info.effectBlock = uint32(block.number) + ALLOCATION_CONFIGURATION_DELAY + 1;
}
_allocationDelayInfo[operator] = info;
emit AllocationDelaySet(operator, delay, info.effectBlock);
}
/// @notice returns whether the operator's allocation is slashable in the given operator set
function _isAllocationSlashable(
OperatorSet memory operatorSet,
IStrategy strategy,
Allocation memory allocation,
bool _isOperatorSlashable
) internal view returns (bool) {
/// forgefmt: disable-next-item
return
// If the operator set does not use this strategy, any allocation from it is not slashable
_operatorSetStrategies[operatorSet.key()].contains(address(strategy)) &&
// If the operator is not slashable by the operatorSet, any allocation is not slashable
_isOperatorSlashable &&
// If there is nothing allocated, the allocation is not slashable
allocation.currentMagnitude != 0;
}
/// @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);
}
function _updateAllocationInfo(
address operator,
bytes32 operatorSetKey,
IStrategy strategy,
StrategyInfo memory info,
Allocation memory allocation
) internal {
// Update encumbered magnitude if it has changed
// The mapping should NOT be updated when there is a deallocation on a delay
if (encumberedMagnitude[operator][strategy] != info.encumberedMagnitude) {
encumberedMagnitude[operator][strategy] = info.encumberedMagnitude;
emit EncumberedMagnitudeUpdated(operator, strategy, info.encumberedMagnitude);
}
// Update allocation for this operator set from the strategy
// We emit an `AllocationUpdated` from the `modifyAllocations` and `slashOperator` functions.
// `clearDeallocationQueue` does not emit an `AllocationUpdated` event since it was
// emitted when the deallocation was queued
allocations[operator][operatorSetKey][strategy] = allocation;
// Note: these no-op if the sets already contain the added values (or do not contain removed ones)
if (allocation.pendingDiff != 0) {
// If we have a pending modification, ensure the allocation is in the operator's
// list of enumerable strategies/sets.
allocatedStrategies[operator][operatorSetKey].add(address(strategy));
allocatedSets[operator].add(operatorSetKey);
} else if (allocation.currentMagnitude == 0) {
// If we do NOT have a pending modification, and no existing magnitude, remove the
// allocation from the operator's lists.
allocatedStrategies[operator][operatorSetKey].remove(address(strategy));
if (allocatedStrategies[operator][operatorSetKey].length() == 0) {
allocatedSets[operator].remove(operatorSetKey);
}
}
}
function _updateMaxMagnitude(
address operator,
IStrategy strategy,
uint64 newMaxMagnitude
) internal {
_maxMagnitudeHistory[operator][strategy].push({key: uint32(block.number), value: newMaxMagnitude});
emit MaxMagnitudeUpdated(operator, strategy, newMaxMagnitude);
}
function _calcDelta(
uint64 currentMagnitude,
uint64 newMagnitude
) internal pure returns (int128) {
return int128(uint128(newMagnitude)) - int128(uint128(currentMagnitude));
}
/// @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();
}
/// @dev Helper function to update the slasher for an operator set
/// @param operatorSet the operator set to update the slasher for
/// @param slasher the new slasher
/// @param instantEffectBlock Whether the new slasher will take effect immediately. Instant if on operatorSet creation or migration function.
/// The new slasher will take `ALLOCATION_CONFIGURATION_DELAY` blocks to take effect if called by the `updateSlasher` function.
function _updateSlasher(
OperatorSet memory operatorSet,
address slasher,
bool instantEffectBlock
) internal {
// Ensure that the slasher address is not the 0 address, which is used to denote if the slasher is not set
require(slasher != address(0), InputAddressZero());
SlasherParams memory params = _slashers[operatorSet.key()];
// If there is a pending slasher that can be applied, apply it
if (params.effectBlock != 0 && block.number >= params.effectBlock) {
params.slasher = params.pendingSlasher;
}
// No-op if proposing the same pending slasher that hasn't taken effect yet
if (slasher == params.pendingSlasher && block.number < params.effectBlock) {
return;
}
// Set the pending parameters
params.pendingSlasher = slasher;
if (instantEffectBlock) {
// Update slasher field immediately for storage consistency
params.slasher = slasher;
params.effectBlock = uint32(block.number);
} else {
params.effectBlock = uint32(block.number) + SLASHER_CONFIGURATION_DELAY + 1;
}
_slashers[operatorSet.key()] = params;
emit SlasherUpdated(operatorSet, slasher, params.effectBlock);
}
/// @notice Helper function to convert CreateSetParams to CreateSetParamsV2
/// @param params The parameters to convert
/// @param avs The AVS address that owns the operator sets, which will be the slasher
/// @return The converted parameters, into CreateSetParamsV2 format
/// @dev The slasher will be set to the AVS address
function _convertCreateSetParams(
CreateSetParams[] calldata params,
address avs
) internal pure returns (CreateSetParamsV2[] memory) {
CreateSetParamsV2[] memory createSetParams = new CreateSetParamsV2[](params.length);
for (uint256 i = 0; i < params.length; i++) {
createSetParams[i] = CreateSetParamsV2(params[i].operatorSetId, params[i].strategies, avs);
}
return createSetParams;
}
///
/// VIEW FUNCTIONS
///
/// Public View Functions
/// @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 isRedistributingOperatorSet(
OperatorSet memory operatorSet
) public view returns (bool) {
return getRedistributionRecipient(operatorSet) != DEFAULT_BURN_ADDRESS;
}
/// @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 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 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;
}
/// External View Functions
/// These functions are delegated to the view implementation
/// @inheritdoc IAllocationManagerView
function getOperatorSetCount(
address
) external view returns (uint256 count) {
_delegateView(viewImplementation);
count;
}
/// @inheritdoc IAllocationManagerView
function getAllocatedSets(
address
) external view returns (OperatorSet[] memory operatorSets) {
_delegateView(viewImplementation);
operatorSets;
}
/// @inheritdoc IAllocationManagerView
function getAllocatedStrategies(
address,
OperatorSet memory
) external view returns (IStrategy[] memory strategies) {
_delegateView(viewImplementation);
strategies;
}
/// @inheritdoc IAllocationManagerView
function getAllocation(
address,
OperatorSet memory,
IStrategy
) external view returns (Allocation memory allocation) {
_delegateView(viewImplementation);
allocation;
}
/// @inheritdoc IAllocationManagerView
function getAllocations(
address[] memory,
OperatorSet memory,
IStrategy
) external view returns (Allocation[] memory allocations) {
_delegateView(viewImplementation);
allocations;
}
/// @inheritdoc IAllocationManagerView
function getStrategyAllocations(
address,
IStrategy
) external view returns (OperatorSet[] memory operatorSets, Allocation[] memory allocations) {
_delegateView(viewImplementation);
operatorSets;
allocations;
}
/// @inheritdoc IAllocationManagerView
function getEncumberedMagnitude(
address,
IStrategy
) external view returns (uint64 encumberedMagnitude) {
_delegateView(viewImplementation);
encumberedMagnitude;
}
/// @inheritdoc IAllocationManagerView
function getAllocatableMagnitude(
address,
IStrategy
) external view returns (uint64 allocatableMagnitude) {
_delegateView(viewImplementation);
allocatableMagnitude;
}
/// @inheritdoc IAllocationManagerView
function getMaxMagnitude(
address,
IStrategy
) external view returns (uint64 maxMagnitude) {
_delegateView(viewImplementation);
maxMagnitude;
}
/// @inheritdoc IAllocationManagerView
function getMaxMagnitudes(
address,
IStrategy[] calldata
) external view returns (uint64[] memory maxMagnitudes) {
_delegateView(viewImplementation);
maxMagnitudes;
}
/// @inheritdoc IAllocationManagerView
function getMaxMagnitudes(
address[] calldata,
IStrategy
) external view returns (uint64[] memory maxMagnitudes) {
_delegateView(viewImplementation);
maxMagnitudes;
}
/// @inheritdoc IAllocationManagerView
function getMaxMagnitudesAtBlock(
address,
IStrategy[] calldata,
uint32
) external view returns (uint64[] memory maxMagnitudes) {
_delegateView(viewImplementation);
maxMagnitudes;
}
/// @inheritdoc IAllocationManagerView
function getRegisteredSets(
address
) external view returns (OperatorSet[] memory operatorSets) {
_delegateView(viewImplementation);
operatorSets;
}
/// @inheritdoc IAllocationManagerView
function isMemberOfOperatorSet(
address,
OperatorSet memory
) external view returns (bool result) {
_delegateView(viewImplementation);
result;
}
/// @inheritdoc IAllocationManagerView
function isOperatorSet(
OperatorSet memory
) external view returns (bool result) {
_delegateView(viewImplementation);
result;
}
/// @inheritdoc IAllocationManagerView
function getMembers(
OperatorSet memory
) external view returns (address[] memory operators) {
_delegateView(viewImplementation);
operators;
}
/// @inheritdoc IAllocationManagerView
function getMemberCount(
OperatorSet memory
) external view returns (uint256 memberCount) {
_delegateView(viewImplementation);
memberCount;
}
/// @inheritdoc IAllocationManagerView
function getStrategiesInOperatorSet(
OperatorSet memory
) external view returns (IStrategy[] memory strategies) {
_delegateView(viewImplementation);
strategies;
}
/// @inheritdoc IAllocationManagerView
function getMinimumSlashableStake(
OperatorSet memory,
address[] memory,
IStrategy[] memory,
uint32
) external view returns (uint256[][] memory slashableStake) {
_delegateView(viewImplementation);
slashableStake;
}
/// @inheritdoc IAllocationManagerView
function getAllocatedStake(
OperatorSet memory,
address[] memory,
IStrategy[] memory
) external view returns (uint256[][] memory slashableStake) {
_delegateView(viewImplementation);
slashableStake;
}
/// @inheritdoc IAllocationManagerView
function getPendingSlasher(
OperatorSet memory
) external view returns (address pendingSlasher, uint32 effectBlock) {
_delegateView(viewImplementation);
pendingSlasher;
effectBlock;
}
/// @inheritdoc IAllocationManagerView
function getSlashCount(
OperatorSet memory
) external view returns (uint256 slashCount) {
_delegateView(viewImplementation);
slashCount;
}
/// @inheritdoc IAllocationManagerView
function isOperatorRedistributable(
address
) external view returns (bool result) {
_delegateView(viewImplementation);
result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuardUpgradeable is Initializable {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
function __ReentrancyGuard_init() internal onlyInitializing {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal onlyInitializing {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
/**
* @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[49] private __gap;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "@openzeppelin-upgrades/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin-upgrades/contracts/utils/ContextUpgradeable.sol";
/// @title Deprecated_OwnableUpgradeable
/// @dev This contract can be inherited in place of OpenZeppelin's OwnableUpgradeable
/// to maintain the same storage layout while effectively removing the Ownable functionality.
///
/// This is useful in cases where a contract previously used OwnableUpgradeable but no longer
/// needs ownership functionality, yet must maintain the same storage slots to ensure
/// compatibility with existing deployed proxies.
///
/// The contract preserves the same storage layout as OwnableUpgradeable:
/// - It keeps the `_owner` storage variable in the same slot
/// - It maintains the same storage gap for future upgrades
abstract contract Deprecated_OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
/// @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[49] private __gap;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
abstract contract SplitContractMixin {
/// @notice The address of the second half of the contract.
address public immutable viewImplementation;
constructor(
address _viewImplementation
) {
viewImplementation = _viewImplementation;
}
/// @dev Delegates the current call to `implementation`.
///
/// This function does not return to its internal call site, it will return directly to the external caller.
///
/// Copied from OpenZeppelin Contracts v4.9.0 (proxy/Proxy.sol).
function _delegate(
address implementation
) internal virtual {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
/// @dev Performs a delegate call to `implementation` in the context of a view function.
///
/// This function typecasts the non-view `_delegate` function to a view function in order to
/// allow its invocation from a view context. This is required because the EVM itself does not
/// enforce view/pure mutability, and using inline assembly, it is possible to cast a function
/// pointer to a view (read-only) signature. This pattern is sometimes used for readonly proxies,
/// but it should be used cautiously since any state-modifying logic in the underlying delegate
/// violates the spirit of a view call.
///
/// @param implementation The address to which the call should be delegated.
function _delegateView(
address implementation
) internal view virtual {
function(address) fn = _delegate;
function(address) view fnView;
/// @solidity memory-safe-assembly
assembly {
fnView := fn
}
fnView(implementation);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.0;
import "../interfaces/IPermissionController.sol";
abstract contract PermissionControllerMixin {
/// @dev Thrown when the caller is not allowed to call a function on behalf of an account.
error InvalidPermissions();
/// @notice Pointer to the permission controller contract.
IPermissionController public immutable permissionController;
constructor(
IPermissionController _permissionController
) {
permissionController = _permissionController;
}
/// @notice Modifier that checks if the caller can call on behalf of an account, reverts if not permitted.
/// @param account The account on whose behalf the function is being called.
/// @dev Use this modifier when the entire function requires authorization.
/// @dev This is the most common pattern - prefer this over `_checkCanCall` when possible.
modifier checkCanCall(
address account
) {
_checkCanCall(account);
_;
}
/// @notice Checks if the caller is permitted to call the current function on behalf of the given account.
/// @param account The account on whose behalf the function is being called.
/// @dev Reverts with `InvalidPermissions()` if the caller is not permitted.
/// @dev Use this function instead of the modifier when:
/// - You need to avoid "stack too deep" errors (e.g., when combining multiple modifiers)
/// - You need more control over when the check occurs in your function logic
function _checkCanCall(
address account
) internal view {
require(_canCall(account), InvalidPermissions());
}
/// @notice Checks if the caller is permitted to call the current function on behalf of the given account.
/// @param account The account on whose behalf the function is being called.
/// @return allowed True if the caller is permitted, false otherwise.
/// @dev Unlike `_checkCanCall`, this function returns a boolean instead of reverting.
/// @dev Use this function when you need conditional logic based on permissions, such as:
/// - OR conditions: `require(_canCall(operator) || _canCall(avs), InvalidCaller());`
/// - If-else branches: `if (_canCall(account)) { ... } else { ... }`
/// - Multiple authorization paths in the same function
/// @dev This function queries the permissionController to determine if msg.sender is authorized
/// to call the current function (identified by msg.sig) on behalf of `account`.
function _canCall(
address account
) internal view returns (bool allowed) {
return permissionController.canCall(account, msg.sender, address(this), msg.sig);
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import "../interfaces/IPausable.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
abstract contract Pausable is IPausable {
/// Constants
uint256 internal constant _UNPAUSE_ALL = 0;
uint256 internal constant _PAUSE_ALL = type(uint256).max;
/// @notice Address of the `PauserRegistry` contract that this contract defers to for determining access control (for pausing).
IPauserRegistry public immutable pauserRegistry;
/// Storage
/// @dev Do not remove, deprecated storage.
IPauserRegistry private __deprecated_pauserRegistry;
/// @dev Returns a bitmap representing the paused status of the contract.
uint256 private _paused;
/// Modifiers
/// @dev Thrown if the caller is not a valid pauser according to the pauser registry.
modifier onlyPauser() {
_checkOnlyPauser();
_;
}
/// @dev Thrown if the caller is not a valid unpauser according to the pauser registry.
modifier onlyUnpauser() {
_checkOnlyUnpauser();
_;
}
/// @dev Thrown if the contract is paused, i.e. if any of the bits in `_paused` is flipped to 1.
modifier whenNotPaused() {
_checkOnlyWhenNotPaused();
_;
}
/// @dev Thrown if the `indexed`th bit of `_paused` is 1, i.e. if the `index`th pause switch is flipped.
modifier onlyWhenNotPaused(
uint8 index
) {
_checkOnlyWhenNotPaused(index);
_;
}
function _checkOnlyPauser() internal view {
require(pauserRegistry.isPauser(msg.sender), OnlyPauser());
}
function _checkOnlyUnpauser() internal view {
require(msg.sender == pauserRegistry.unpauser(), OnlyUnpauser());
}
function _checkOnlyWhenNotPaused() internal view {
require(_paused == 0, CurrentlyPaused());
}
function _checkOnlyWhenNotPaused(
uint8 index
) internal view {
require(!paused(index), CurrentlyPaused());
}
/// Construction
constructor(
IPauserRegistry _pauserRegistry
) {
require(address(_pauserRegistry) != address(0), InputAddressZero());
pauserRegistry = _pauserRegistry;
}
/// @inheritdoc IPausable
function pause(
uint256 newPausedStatus
) external onlyPauser {
uint256 currentPausedStatus = _paused;
// verify that the `newPausedStatus` does not *unflip* any bits (i.e. doesn't unpause anything, all 1 bits remain)
require((currentPausedStatus & newPausedStatus) == currentPausedStatus, InvalidNewPausedStatus());
_setPausedStatus(newPausedStatus);
}
/// @inheritdoc IPausable
function pauseAll() external onlyPauser {
_setPausedStatus(_PAUSE_ALL);
}
/// @inheritdoc IPausable
function unpause(
uint256 newPausedStatus
) external onlyUnpauser {
uint256 currentPausedStatus = _paused;
// verify that the `newPausedStatus` does not *flip* any bits (i.e. doesn't pause anything, all 0 bits remain)
require(((~currentPausedStatus) & (~newPausedStatus)) == (~currentPausedStatus), InvalidNewPausedStatus());
_paused = newPausedStatus;
emit Unpaused(msg.sender, newPausedStatus);
}
/// @inheritdoc IPausable
function paused() public view virtual returns (uint256) {
return _paused;
}
/// @inheritdoc IPausable
function paused(
uint8 index
) public view virtual returns (bool) {
uint256 mask = 1 << index;
return ((_paused & mask) == mask);
}
/// @dev Internal helper for setting the paused status, and emitting the corresponding event.
function _setPausedStatus(
uint256 pausedStatus
) internal {
_paused = pausedStatus;
emit Paused(msg.sender, pausedStatus);
}
/// @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[48] private __gap;
}// 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.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.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/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @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[50] private __gap;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
interface IPermissionControllerErrors {
/// @notice Thrown when a non-admin caller attempts to perform an admin-only action.
error NotAdmin();
/// @notice Thrown when attempting to remove an admin that does not exist.
error AdminNotSet();
/// @notice Thrown when attempting to set an appointee for a function that already has one.
error AppointeeAlreadySet();
/// @notice Thrown when attempting to interact with a non-existent appointee.
error AppointeeNotSet();
/// @notice Thrown when attempting to remove the last remaining admin.
error CannotHaveZeroAdmins();
/// @notice Thrown when attempting to set an admin that is already registered.
error AdminAlreadySet();
/// @notice Thrown when attempting to interact with an admin that is not in pending status.
error AdminNotPending();
/// @notice Thrown when attempting to add an admin that is already pending.
error AdminAlreadyPending();
}
interface IPermissionControllerEvents {
/// @notice Emitted when an appointee is set for an account to handle specific function calls.
event AppointeeSet(address indexed account, address indexed appointee, address target, bytes4 selector);
/// @notice Emitted when an appointee's permission to handle function calls for an account is revoked.
event AppointeeRemoved(address indexed account, address indexed appointee, address target, bytes4 selector);
/// @notice Emitted when an address is set as a pending admin for an account, requiring acceptance.
event PendingAdminAdded(address indexed account, address admin);
/// @notice Emitted when a pending admin status is removed for an account before acceptance.
event PendingAdminRemoved(address indexed account, address admin);
/// @notice Emitted when an address accepts and becomes an active admin for an account.
event AdminSet(address indexed account, address admin);
/// @notice Emitted when an admin's permissions are removed from an account.
event AdminRemoved(address indexed account, address admin);
}
interface IPermissionController is IPermissionControllerErrors, IPermissionControllerEvents {
/// @notice Sets a pending admin for an account.
/// @param account The account to set the pending admin for.
/// @param admin The address to set as pending admin.
/// @dev The pending admin must accept the role before becoming an active admin.
/// @dev Multiple admins can be set for a single account.
function addPendingAdmin(
address account,
address admin
) external;
/// @notice Removes a pending admin from an account before they have accepted the role.
/// @param account The account to remove the pending admin from.
/// @param admin The pending admin address to remove.
/// @dev Only an existing admin of the account can remove a pending admin.
function removePendingAdmin(
address account,
address admin
) external;
/// @notice Allows a pending admin to accept their admin role for an account.
/// @param account The account to accept the admin role for.
/// @dev Only addresses that were previously set as pending admins can accept the role.
function acceptAdmin(
address account
) external;
/// @notice Removes an active admin from an account.
/// @param account The account to remove the admin from.
/// @param admin The admin address to remove.
/// @dev Only an existing admin of the account can remove another admin.
/// @dev Will revert if removing this admin would leave the account with zero admins.
function removeAdmin(
address account,
address admin
) external;
/// @notice Sets an appointee who can call specific functions on behalf of an account.
/// @param account The account to set the appointee for.
/// @param appointee The address to be given permission.
/// @param target The contract address the appointee can interact with.
/// @param selector The function selector the appointee can call.
/// @dev Only an admin of the account can set appointees.
function setAppointee(
address account,
address appointee,
address target,
bytes4 selector
) external;
/// @notice Removes an appointee's permission to call a specific function.
/// @param account The account to remove the appointee from.
/// @param appointee The appointee address to remove.
/// @param target The contract address to remove permissions for.
/// @param selector The function selector to remove permissions for.
/// @dev Only an admin of the account can remove appointees.
function removeAppointee(
address account,
address appointee,
address target,
bytes4 selector
) external;
/// @notice Checks if a given address is an admin of an account.
/// @param account The account to check admin status for.
/// @param caller The address to check.
/// @dev If the account has no admins, returns true only if the caller is the account itself.
/// @return Returns true if the caller is an admin, false otherwise.
function isAdmin(
address account,
address caller
) external view returns (bool);
/// @notice Checks if an address is currently a pending admin for an account.
/// @param account The account to check pending admin status for.
/// @param pendingAdmin The address to check.
/// @return Returns true if the address is a pending admin, false otherwise.
function isPendingAdmin(
address account,
address pendingAdmin
) external view returns (bool);
/// @notice Retrieves all active admins for an account.
/// @param account The account to get the admins for.
/// @dev If the account has no admins, returns an array containing only the account address.
/// @return An array of admin addresses.
function getAdmins(
address account
) external view returns (address[] memory);
/// @notice Retrieves all pending admins for an account.
/// @param account The account to get the pending admins for.
/// @return An array of pending admin addresses.
function getPendingAdmins(
address account
) external view returns (address[] memory);
/// @notice Checks if a caller has permission to call a specific function.
/// @param account The account to check permissions for.
/// @param caller The address attempting to make the call.
/// @param target The contract address being called.
/// @param selector The function selector being called.
/// @dev Returns true if the caller is either an admin or an appointed caller.
/// @dev Be mindful that upgrades to the contract may invalidate the appointee's permissions.
/// This is only possible if a function's selector changes (e.g. if a function's parameters are modified).
/// @return Returns true if the caller has permission, false otherwise.
function canCall(
address account,
address caller,
address target,
bytes4 selector
) external view returns (bool);
/// @notice Retrieves all permissions granted to an appointee for a given account.
/// @param account The account to check appointee permissions for.
/// @param appointee The appointee address to check.
/// @return Two arrays: target contract addresses and their corresponding function selectors.
function getAppointeePermissions(
address account,
address appointee
) external view returns (address[] memory, bytes4[] memory);
/// @notice Retrieves all appointees that can call a specific function for an account.
/// @param account The account to get appointees for.
/// @param target The contract address to check.
/// @param selector The function selector to check.
/// @dev Does not include admins in the returned list, even though they have calling permission.
/// @return An array of appointee addresses.
function getAppointees(
address account,
address target,
bytes4 selector
) external view returns (address[] memory);
}// 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: 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);
}
}// 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: 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: 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.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;
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.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);
}{
"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 IAllocationManagerView","name":"_allocationManagerView","type":"address"},{"internalType":"contract IDelegationManager","name":"_delegation","type":"address"},{"internalType":"contract IStrategy","name":"_eigenStrategy","type":"address"},{"internalType":"contract IPauserRegistry","name":"_pauserRegistry","type":"address"},{"internalType":"contract IPermissionController","name":"_permissionController","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":"CurrentlyPaused","type":"error"},{"inputs":[],"name":"Empty","type":"error"},{"inputs":[],"name":"InputAddressZero","type":"error"},{"inputs":[],"name":"InputArrayLengthMismatch","type":"error"},{"inputs":[],"name":"InsufficientMagnitude","type":"error"},{"inputs":[],"name":"InvalidAVSRegistrar","type":"error"},{"inputs":[],"name":"InvalidCaller","type":"error"},{"inputs":[],"name":"InvalidNewPausedStatus","type":"error"},{"inputs":[],"name":"InvalidOperator","type":"error"},{"inputs":[],"name":"InvalidOperatorSet","type":"error"},{"inputs":[],"name":"InvalidPermissions","type":"error"},{"inputs":[],"name":"InvalidRedistributionRecipient","type":"error"},{"inputs":[],"name":"InvalidSnapshotOrdering","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":"OnlyPauser","type":"error"},{"inputs":[],"name":"OnlyUnpauser","type":"error"},{"inputs":[],"name":"OperatorNotSlashable","type":"error"},{"inputs":[],"name":"OperatorSetAlreadyMigrated","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":"uint8","name":"version","type":"uint8"}],"name":"Initialized","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":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"name":"Paused","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"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"name":"Unpaused","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":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"operatorSetId","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"name":"addStrategiesToOperatorSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint16[]","name":"numToClear","type":"uint16[]"}],"name":"clearDeallocationQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"},{"components":[{"internalType":"uint32","name":"operatorSetId","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"internalType":"struct IAllocationManagerTypes.CreateSetParams[]","name":"params","type":"tuple[]"}],"name":"createOperatorSets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"},{"components":[{"internalType":"uint32","name":"operatorSetId","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"address","name":"slasher","type":"address"}],"internalType":"struct IAllocationManagerTypes.CreateSetParamsV2[]","name":"params","type":"tuple[]"}],"name":"createOperatorSets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"},{"components":[{"internalType":"uint32","name":"operatorSetId","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"internalType":"struct IAllocationManagerTypes.CreateSetParams[]","name":"params","type":"tuple[]"},{"internalType":"address[]","name":"redistributionRecipients","type":"address[]"}],"name":"createRedistributingOperatorSets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"},{"components":[{"internalType":"uint32","name":"operatorSetId","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"address","name":"slasher","type":"address"}],"internalType":"struct IAllocationManagerTypes.CreateSetParamsV2[]","name":"params","type":"tuple[]"},{"internalType":"address[]","name":"redistributionRecipients","type":"address[]"}],"name":"createRedistributingOperatorSets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"delegation","outputs":[{"internalType":"contract IDelegationManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32[]","name":"operatorSetIds","type":"uint32[]"}],"internalType":"struct IAllocationManagerTypes.DeregisterParams","name":"params","type":"tuple"}],"name":"deregisterFromOperatorSets","outputs":[],"stateMutability":"nonpayable","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":"","type":"address"},{"internalType":"contract IStrategy","name":"","type":"address"}],"name":"getAllocatableMagnitude","outputs":[{"internalType":"uint64","name":"allocatableMagnitude","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getAllocatedSets","outputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet[]","name":"operatorSets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"contract IStrategy[]","name":"","type":"address[]"}],"name":"getAllocatedStake","outputs":[{"internalType":"uint256[][]","name":"slashableStake","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"}],"name":"getAllocatedStrategies","outputs":[{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"},{"internalType":"contract IStrategy","name":"","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":"allocation","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":"","type":"address[]"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"},{"internalType":"contract IStrategy","name":"","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":"allocations","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract IStrategy","name":"","type":"address"}],"name":"getEncumberedMagnitude","outputs":[{"internalType":"uint64","name":"encumberedMagnitude","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract IStrategy","name":"","type":"address"}],"name":"getMaxMagnitude","outputs":[{"internalType":"uint64","name":"maxMagnitude","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"contract IStrategy","name":"","type":"address"}],"name":"getMaxMagnitudes","outputs":[{"internalType":"uint64[]","name":"maxMagnitudes","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract IStrategy[]","name":"","type":"address[]"}],"name":"getMaxMagnitudes","outputs":[{"internalType":"uint64[]","name":"maxMagnitudes","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract IStrategy[]","name":"","type":"address[]"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"getMaxMagnitudesAtBlock","outputs":[{"internalType":"uint64[]","name":"maxMagnitudes","type":"uint64[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"}],"name":"getMemberCount","outputs":[{"internalType":"uint256","name":"memberCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"}],"name":"getMembers","outputs":[{"internalType":"address[]","name":"operators","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"contract IStrategy[]","name":"","type":"address[]"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"getMinimumSlashableStake","outputs":[{"internalType":"uint256[][]","name":"slashableStake","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"getOperatorSetCount","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"}],"name":"getPendingSlasher","outputs":[{"internalType":"address","name":"pendingSlasher","type":"address"},{"internalType":"uint32","name":"effectBlock","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":"","type":"address"}],"name":"getRegisteredSets","outputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet[]","name":"operatorSets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"}],"name":"getSlashCount","outputs":[{"internalType":"uint256","name":"slashCount","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":"","type":"tuple"}],"name":"getStrategiesInOperatorSet","outputs":[{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"contract IStrategy","name":"","type":"address"}],"name":"getStrategyAllocations","outputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet[]","name":"operatorSets","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":"allocations","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"initialPausedStatus","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"}],"name":"isMemberOfOperatorSet","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isOperatorRedistributable","outputs":[{"internalType":"bool","name":"result","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"","type":"tuple"}],"name":"isOperatorSet","outputs":[{"internalType":"bool","name":"result","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"},{"inputs":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet[]","name":"operatorSets","type":"tuple[]"}],"name":"migrateSlashers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"components":[{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"id","type":"uint32"}],"internalType":"struct OperatorSet","name":"operatorSet","type":"tuple"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint64[]","name":"newMagnitudes","type":"uint64[]"}],"internalType":"struct IAllocationManagerTypes.AllocateParams[]","name":"params","type":"tuple[]"}],"name":"modifyAllocations","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"index","type":"uint8"}],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauserRegistry","outputs":[{"internalType":"contract IPauserRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"permissionController","outputs":[{"internalType":"contract IPermissionController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"components":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32[]","name":"operatorSetIds","type":"uint32[]"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IAllocationManagerTypes.RegisterParams","name":"params","type":"tuple"}],"name":"registerForOperatorSets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"uint32","name":"operatorSetId","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"}],"name":"removeStrategiesFromOperatorSet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"contract IAVSRegistrar","name":"registrar","type":"address"}],"name":"setAVSRegistrar","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint32","name":"delay","type":"uint32"}],"name":"setAllocationDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"},{"components":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint32","name":"operatorSetId","type":"uint32"},{"internalType":"contract IStrategy[]","name":"strategies","type":"address[]"},{"internalType":"uint256[]","name":"wadsToSlash","type":"uint256[]"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct IAllocationManagerTypes.SlashingParams","name":"params","type":"tuple"}],"name":"slashOperator","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newPausedStatus","type":"uint256"}],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"avs","type":"address"},{"internalType":"string","name":"metadataURI","type":"string"}],"name":"updateAVSMetadataURI","outputs":[],"stateMutability":"nonpayable","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":"slasher","type":"address"}],"name":"updateSlasher","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"viewImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
610180604052348015610010575f5ffd5b50604051615a31380380615a3183398101604081905261002f91610198565b868387878585896001600160a01b03811661005d576040516339b190bb60e11b815260040160405180910390fd5b6001600160a01b0390811660805293841660a05291831660c05263ffffffff90811660e05216610100819052610120529081166101405216610160526100a16100ad565b50505050505050610227565b5f54610100900460ff16156101185760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff90811614610167575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b6001600160a01b038116811461017d575f5ffd5b50565b805163ffffffff81168114610193575f5ffd5b919050565b5f5f5f5f5f5f5f60e0888a0312156101ae575f5ffd5b87516101b981610169565b60208901519097506101ca81610169565b60408901519096506101db81610169565b60608901519095506101ec81610169565b60808901519094506101fd81610169565b925061020b60a08901610180565b915061021960c08901610180565b905092959891949750929550565b60805160a05160c05160e0516101005161012051610140516101605161571561031c5f395f81816103910152818161097101528181610a5101528181610a8001528181610aca01528181610af501528181610d5101528181610ff501528181612125015261240001525f818161058b015281816119bc01526137c801525f818161067601526136aa01525f81816106e9015261347701525f818161048601528181611325015261174601525f818161087f01526132fd01525f81816108b401528181610ef701528181610f4501528181611c4f0152612eed01525f81816107100152818161264f0152613c8501526157155ff3fe608060405234801561000f575f5ffd5b5060043610610388575f3560e01c80636c9d7c58116101df578063b66bd98911610109578063d7794857116100a9578063f231bd0811610079578063f231bd08146108d6578063f605ce08146106ab578063fabc1cbc146108e9578063fe4b84df146108fc575f5ffd5b8063d779485714610843578063db4df7611461087a578063dc2af692146108a1578063df5cf723146108af575f5ffd5b8063c221d8ae116100e4578063c221d8ae146107f7578063d1a83f541461080a578063d3d96ff41461081d578063d4a3fcce14610830575f5ffd5b8063b66bd989146107a7578063b9fbaed1146107ba578063ba1a84e5146107e9575f5ffd5b80638ce648541161017f578063a9333ec81161014f578063a9333ec8146106ab578063a982182114610781578063adc2e3d914610794578063b2447af7146105db575f5ffd5b80638ce648541461073257806394d7d00c1461074d578063952899ee1461075b578063957dc50b1461076e575f5ffd5b80636e875dba116101ba5780636e875dba1461056b57806379ae50cd1461043b5780637bc1ef61146106e4578063886f11951461070b575f5ffd5b80636c9d7c58146106985780636cfb4481146106ab5780636e3492b5146106d1575f5ffd5b80633dff8e7d116102c057806350feea20116102605780635ac86ab7116102305780635ac86ab7146106335780635c975abb14610656578063670d3ba21461065e57806367aeaa5314610671575f5ffd5b806350feea20146105f7578063547afb871461060a57806356c483e614610618578063595c6a671461062b575f5ffd5b80634657e26a1161029b5780634657e26a146105865780634a10ffe5146105ad5780634b5046ef146105c85780634cfd2939146105db575f5ffd5b80633dff8e7d1461053757806340120dab1461054a5780634177a87c1461056b575f5ffd5b8063261f84e01161032b5780632bab2c4a116103065780632bab2c4a146104dd578063304c10cd146104f057806332a879e4146105035780633635205714610516575f5ffd5b8063261f84e01461046e5780632981eb77146104815780632b453a9a146104bd575f5ffd5b80631352c3e6116103665780631352c3e614610403578063136439dd1461042657806315fe50281461043b578063260dc7581461045b575f5ffd5b80630b156bb61461038c5780630f3df50e146103d057806310e1b9b8146103e3575b5f5ffd5b6103b37f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6103b36103de36600461442d565b61090f565b6103f66103f1366004614447565b610950565b6040516103c7919061448e565b6104166104113660046144c1565b610995565b60405190151581526020016103c7565b6104396104343660046144f5565b610a10565b005b61044e61044936600461450c565b610a4a565b6040516103c7919061458a565b61041661046936600461442d565b610a7a565b61043961047c3660046145dc565b610aa4565b6104a87f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff90911681526020016103c7565b6104d06104cb3660046146c1565b610ac3565b6040516103c79190614764565b6104d06104eb3660046147c7565b610aee565b6103b36104fe36600461450c565b610b21565b61043961051136600461484b565b610b50565b6105296105243660046148cb565b610b78565b6040516103c792919061491d565b610439610545366004614a13565b610ccd565b61055d610558366004614a5f565b610d49565b6040516103c7929190614aec565b61057961044936600461442d565b6040516103c79190614b10565b6103b37f000000000000000000000000000000000000000000000000000000000000000081565b6105bb6104cb366004614b5b565b6040516103c79190614ba2565b6104396105d636600461484b565b610d7c565b6105e961046936600461442d565b6040519081526020016103c7565b610439610605366004614be2565b610e18565b6105bb6104cb3660046145dc565b610439610626366004614c40565b610eec565b610439610fdb565b610416610641366004614c6a565b606654600160ff9092169190911b9081161490565b6066546105e9565b61041661066c3660046144c1565b610fef565b6104a87f000000000000000000000000000000000000000000000000000000000000000081565b6104396106a6366004614c8a565b611019565b6106b961066c366004614a5f565b6040516001600160401b0390911681526020016103c7565b6104396106df366004614ccb565b6110af565b6104a87f000000000000000000000000000000000000000000000000000000000000000081565b6103b37f000000000000000000000000000000000000000000000000000000000000000081565b6107406104cb366004614cfc565b6040516103c79190614d3f565b6105bb6104eb366004614d51565b610439610769366004614da8565b61146a565b61043961077c366004614f51565b6118fb565b61043961078f366004614fe1565b611b86565b6104396107a236600461505f565b611c1b565b6104396107b5366004614be2565b611f47565b6107cd6107c836600461450c565b612084565b60408051921515835263ffffffff9091166020830152016103c7565b6105e961046936600461450c565b6105796108053660046144c1565b61211e565b6104396108183660046150a1565b612149565b61043961082b366004614a5f565b612262565b6103b361083e36600461442d565b612372565b61085661085136600461442d565b6123f9565b604080516001600160a01b03909316835263ffffffff9091166020830152016103c7565b6103b37f000000000000000000000000000000000000000000000000000000000000000081565b61041661046936600461450c565b6103b37f000000000000000000000000000000000000000000000000000000000000000081565b6104166108e436600461442d565b612429565b6104396108f73660046144f5565b612448565b61043961090a3660046144f5565b6124b5565b5f5f60a65f61091d856125c6565b815260208101919091526040015f20546001600160a01b0316905080156109445780610949565b620e16e45b9392505050565b604080516060810182525f80825260208201819052918101919091526109497f0000000000000000000000000000000000000000000000000000000000000000612629565b6001600160a01b0382165f908152609e602052604081208190816109b8856125c6565b815260208082019290925260409081015f2081518083019092525460ff8116151580835261010090910463ffffffff1692820192909252915080610a065750806020015163ffffffff164311155b9150505b92915050565b610a1861263a565b6066548181168114610a3d5760405163c61dca5d60e01b815260040160405180910390fd5b610a46826126dd565b5050565b6060610a757f0000000000000000000000000000000000000000000000000000000000000000612629565b919050565b5f610a757f0000000000000000000000000000000000000000000000000000000000000000612629565b82610aae8161271a565b610abd84610545858588612743565b50505050565b60606109497f0000000000000000000000000000000000000000000000000000000000000000612629565b6060610b197f0000000000000000000000000000000000000000000000000000000000000000612629565b949350505050565b6001600160a01b038082165f908152609760205260408120549091168015610b495780610949565b5090919050565b84610b5a8161271a565b610b7086610b6987878a612743565b8585612149565b505050505050565b5f60606001610b86816128ba565b5f6040518060400160405280876001600160a01b03168152602001866020016020810190610bb49190615100565b63ffffffff1690529050610bcb6060860186615119565b9050610bda6040870187615119565b905014610bfa576040516343714afd60e01b815260040160405180910390fd5b60208082015182516001600160a01b03165f90815260989092526040909120610c2c9163ffffffff908116906128e516565b610c4957604051631fb1705560e21b815260040160405180910390fd5b610c5f610c59602087018761450c565b82610995565b610c7c5760405163ebbff49760e01b815260040160405180910390fd5b610c8581612372565b6001600160a01b0316336001600160a01b031614610cb6576040516348f5c3ed60e01b815260040160405180910390fd5b610cc085826128fc565b9350935050509250929050565b81610cd78161271a565b6001600160a01b0383165f90815260a4602052604090205460ff16610d0f576040516348f7dbb960e01b815260040160405180910390fd5b5f5b8251811015610abd57610d4184848381518110610d3057610d3061515e565b6020026020010151620e16e4613057565b600101610d11565b606080610d757f0000000000000000000000000000000000000000000000000000000000000000612629565b9250929050565b5f610d86816128ba565b838214610da6576040516343714afd60e01b815260040160405180910390fd5b5f5b84811015610e0f57610e0787878784818110610dc657610dc661515e565b9050602002016020810190610ddb919061450c565b868685818110610ded57610ded61515e565b9050602002016020810190610e029190615172565b6131c9565b600101610da8565b50505050505050565b83610e228161271a565b6040805180820182526001600160a01b03871680825263ffffffff80881660208085018290525f93845260989052939091209192610e6192916128e516565b610e7e57604051631fb1705560e21b815260040160405180910390fd5b5f5b83811015610e0f57610ee482868684818110610e9e57610e9e61515e565b9050602002016020810190610eb3919061450c565b610edf60405180604001604052808c6001600160a01b031681526020018b63ffffffff16815250612429565b6132cd565b600101610e80565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610fcb57610f268361271a565b6040516336b87bd760e11b81526001600160a01b0384811660048301527f00000000000000000000000000000000000000000000000000000000000000001690636d70f7ae90602401602060405180830381865afa158015610f8a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fae9190615193565b610fcb5760405163ccea9e6f60e01b815260040160405180910390fd5b610fd68383836133ad565b505050565b610fe361263a565b610fed5f196126dd565b565b5f610a0a7f0000000000000000000000000000000000000000000000000000000000000000612629565b81516110248161271a565b60208084015184516001600160a01b03165f908152609890925260409091206110569163ffffffff908116906128e516565b61107357604051631fb1705560e21b815260040160405180910390fd5b5f61107d84612372565b6001600160a01b0316036110a45760405163255b0f4160e01b815260040160405180910390fd5b610fd683835f613589565b60026110ba816128ba565b6110cf6110ca602084018461450c565b61378a565b806110e857506110e86110ca604084016020850161450c565b611105576040516348f5c3ed60e01b815260040160405180910390fd5b5f5b6111146040840184615119565b90508110156113d6575f604051806040016040528085602001602081019061113c919061450c565b6001600160a01b031681526020016111576040870187615119565b858181106111675761116761515e565b905060200201602081019061117c9190615100565b63ffffffff1681525090506111c9816020015163ffffffff1660985f8760200160208101906111ab919061450c565b6001600160a01b0316815260208101919091526040015f20906128e5565b6111e657604051631fb1705560e21b815260040160405180910390fd5b609e5f6111f6602087018761450c565b6001600160a01b03166001600160a01b031681526020019081526020015f205f61121f836125c6565b815260208101919091526040015f205460ff1661124f576040516325131d4f60e01b815260040160405180910390fd5b61128961125b826125c6565b609c5f61126b602089018961450c565b6001600160a01b0316815260208101919091526040015f2090613833565b506112c161129a602086018661450c565b609a5f6112a6856125c6565b81526020019081526020015f2061383e90919063ffffffff16565b506112cf602085018561450c565b6001600160a01b03167fad34c3070be1dffbcaa499d000ba2b8d9848aefcac3059df245dd95c4ece14fe8260405161130791906151b2565b60405180910390a2604080518082019091525f81526020810161134a7f0000000000000000000000000000000000000000000000000000000000000000436151d4565b63ffffffff169052609e5f611362602088018861450c565b6001600160a01b03166001600160a01b031681526020019081526020015f205f61138b846125c6565b81526020808201929092526040015f2082518154939092015163ffffffff166101000264ffffffff00199215159290921664ffffffffff199093169290921717905550600101611107565b506113ea6104fe604084016020850161450c565b6001600160a01b031663303ca956611405602085018561450c565b611415604086016020870161450c565b6114226040870187615119565b6040518563ffffffff1660e01b81526004016114419493929190615229565b5f604051808303815f87803b158015611458575f5ffd5b505af1158015610b70573d5f5f3e3d5ffd5b5f611474816128ba565b61147d8361271a565b5f5f5f61148986612084565b91509150816114ab5760405163fa55fc8160e01b815260040160405180910390fd5b91505f90505b83518110156118f4578381815181106114cc576114cc61515e565b602002602001015160400151518482815181106114eb576114eb61515e565b6020026020010151602001515114611516576040516343714afd60e01b815260040160405180910390fd5b5f8482815181106115295761152961515e565b602090810291909101810151518082015181516001600160a01b03165f908152609890935260409092209092506115699163ffffffff908116906128e516565b61158657604051631fb1705560e21b815260040160405180910390fd5b5f6115918783610995565b90505f5b8684815181106115a7576115a761515e565b602002602001015160200151518110156118e9575f8785815181106115ce576115ce61515e565b60200260200101516020015182815181106115eb576115eb61515e565b60200260200101519050611602898261ffff6131c9565b5f5f6116178b611611886125c6565b85613852565b91509150806040015163ffffffff165f1461164557604051630d8fcbe360e41b815260040160405180910390fd5b5f611652878584896139be565b9050611697825f01518c8a8151811061166d5761166d61515e565b602002602001015160400151878151811061168a5761168a61515e565b60200260200101516139f6565b600f0b602083018190525f036116c057604051634606179360e11b815260040160405180910390fd5b5f8260200151600f0b1215611804578015611786576117416116e1886125c6565b6001600160a01b03808f165f90815260a360209081526040808320938a16835292905220908154600160801b90819004600f0b5f818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b61176b7f0000000000000000000000000000000000000000000000000000000000000000436151d4565b6117769060016151d4565b63ffffffff166040830152611871565b61179883602001518360200151613a0d565b6001600160401b031660208401528a518b90899081106117ba576117ba61515e565b60200260200101516040015185815181106117d7576117d761515e565b6020908102919091018101516001600160401b031683525f9083015263ffffffff43166040830152611871565b5f8260200151600f0b13156118715761182583602001518360200151613a0d565b6001600160401b03908116602085018190528451909116101561185b57604051636c9be0bf60e01b815260040160405180910390fd5b61186589436151d4565b63ffffffff1660408301525b6118868c61187e896125c6565b868686613a2c565b7f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd8c88866118bb865f01518760200151613a0d565b86604001516040516118d1959493929190615255565b60405180910390a15050600190920191506115959050565b5050506001016114b1565b5050505050565b5f5b8151811015610a465761197a82828151811061191b5761191b61515e565b60200260200101516020015163ffffffff1660985f8585815181106119425761194261515e565b60200260200101515f01516001600160a01b03166001600160a01b031681526020019081526020015f206128e590919063ffffffff16565b15611b7e575f6001600160a01b03166119ab83838151811061199e5761199e61515e565b6020026020010151612372565b6001600160a01b031603611b7e575f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663fddbdefd8484815181106119fb576119fb61515e565b6020908102919091010151516040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152633635205760e01b60448201526064015f60405180830381865afa158015611a5b573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611a8291908101906152a6565b90505f81515f1480611abe57505f6001600160a01b0316825f81518110611aab57611aab61515e565b60200260200101516001600160a01b0316145b15611ae757838381518110611ad557611ad561515e565b60200260200101515f01519050611b04565b815f81518110611af957611af961515e565b602002602001015190505b611b29848481518110611b1957611b1961515e565b6020026020010151826001613589565b7ff0c8fc7d71f647bd3a88ac369112517f6a4b8038e71913f2d20f71f877dfc725848481518110611b5c57611b5c61515e565b602002602001015182604051611b73929190615335565b60405180910390a150505b6001016118fd565b82611b908161271a565b6001600160a01b0384165f90815260a4602052604090205460ff16611bd2576001600160a01b0384165f90815260a460205260409020805460ff191660011790555b836001600160a01b03167fa89c1dc243d8908a96dd84944bcc97d6bc6ac00dd78e20621576be6a3c9437138484604051611c0d929190615383565b60405180910390a250505050565b6002611c26816128ba565b82611c308161271a565b6040516336b87bd760e11b81526001600160a01b0385811660048301527f00000000000000000000000000000000000000000000000000000000000000001690636d70f7ae90602401602060405180830381865afa158015611c94573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cb89190615193565b611cd55760405163ccea9e6f60e01b815260040160405180910390fd5b5f5b611ce46020850185615119565b9050811015611eac57604080518082019091525f9080611d07602088018861450c565b6001600160a01b03168152602001868060200190611d259190615119565b85818110611d3557611d3561515e565b9050602002016020810190611d4a9190615100565b63ffffffff90811690915260208083015183516001600160a01b03165f90815260989092526040909120929350611d869291908116906128e516565b611da357604051631fb1705560e21b815260040160405180910390fd5b611dad8682610995565b15611dcb57604051636c6c6e2760e11b815260040160405180910390fd5b611df4611dd7826125c6565b6001600160a01b0388165f908152609c6020526040902090613c64565b50611e2086609a5f611e05856125c6565b81526020019081526020015f20613c6f90919063ffffffff16565b50856001600160a01b03167f43232edf9071753d2321e5fa7e018363ee248e5f2142e6c08edd3265bfb4895e82604051611e5a91906151b2565b60405180910390a26001600160a01b0386165f908152609e60205260408120600191611e85846125c6565b815260208101919091526040015f20805460ff191691151591909117905550600101611cd7565b50611ebd6104fe602085018561450c565b6001600160a01b031663c63fd50285611ed9602087018761450c565b611ee66020880188615119565b611ef360408a018a615396565b6040518763ffffffff1660e01b8152600401611f14969594939291906153d8565b5f604051808303815f87803b158015611f2b575f5ffd5b505af1158015611f3d573d5f5f3e3d5ffd5b5050505050505050565b83611f518161271a565b6040805180820182526001600160a01b03871680825263ffffffff80881660208085018290525f93845260989052939091209192611f9092916128e516565b611fad57604051631fb1705560e21b815260040160405180910390fd5b5f611fb7826125c6565b90505f5b84811015611f3d57612000868683818110611fd857611fd861515e565b9050602002016020810190611fed919061450c565b5f8481526099602052604090209061383e565b61201d576040516331bc342760e11b815260040160405180910390fd5b7f7b4b073d80dcac55a11177d8459ad9f664ceeb91f71f27167bb14f8152a7eeee838787848181106120515761205161515e565b9050602002016020810190612066919061450c565b604051612074929190615335565b60405180910390a1600101611fbb565b6001600160a01b0381165f908152609b602090815260408083208151608081018352905463ffffffff80821680845260ff600160201b8404161515958401869052650100000000008304821694840194909452600160481b9091041660608201819052849391929190158015906121055750826060015163ffffffff164310155b15612114575050604081015160015b9590945092505050565b6060610a0a7f0000000000000000000000000000000000000000000000000000000000000000612629565b836121538161271a565b83518214612174576040516343714afd60e01b815260040160405180910390fd5b6001600160a01b0385165f90815260a4602052604090205460ff166121ac576040516348f7dbb960e01b815260040160405180910390fd5b5f5b8451811015610b70575f8484838181106121ca576121ca61515e565b90506020020160208101906121df919061450c565b90506001600160a01b038116612208576040516339b190bb60e11b815260040160405180910390fd5b620e16e3196001600160a01b03821601612235576040516364be1a3f60e11b815260040160405180910390fd5b6122598787848151811061224b5761224b61515e565b602002602001015183613057565b506001016121ae565b8161226c8161271a565b60405163b526578760e01b81526001600160a01b03848116600483015283169063b526578790602401602060405180830381865afa1580156122b0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d49190615193565b6122f157604051631d0b13c160e31b815260040160405180910390fd5b6001600160a01b038381165f90815260976020526040902080546001600160a01b0319169184169190911790557f2ae945c40c44dc0ec263f95609c3fdc6952e0aefa22d6374e44f2c997acedf858361234981610b21565b604080516001600160a01b039384168152929091166020830152015b60405180910390a1505050565b5f5f60a75f612380856125c6565b815260208082019290925260409081015f20815160608101835281546001600160a01b0390811680835260019093015490811694820194909452600160a01b90930463ffffffff16918301829052919250158015906123e95750816040015163ffffffff164310155b1561094957506020015192915050565b5f5f6124247f0000000000000000000000000000000000000000000000000000000000000000612629565b915091565b5f620e16e46124378361090f565b6001600160a01b0316141592915050565b612450613c83565b606654801982198116146124775760405163c61dca5d60e01b815260040160405180910390fd5b606682905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200160405180910390a25050565b5f54610100900460ff16158080156124d357505f54600160ff909116105b806124ec5750303b1580156124ec57505f5460ff166001145b6125545760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015612575575f805461ff0019166101001790555b61257e826126dd565b8015610a46575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b5f815f0151826020015163ffffffff1660405160200161261192919060609290921b6bffffffffffffffffffffffff1916825260a01b6001600160a01b031916601482015260200190565b604051602081830303815290604052610a0a90615424565b613d3480610fd68363ffffffff8316565b60405163237dfb4760e11b81523360048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906346fbf68e90602401602060405180830381865afa15801561269c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c09190615193565b610fed57604051631d77d47760e21b815260040160405180910390fd5b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b6127238161378a565b6127405760405163932d94f760e01b815260040160405180910390fd5b50565b60605f836001600160401b0381111561275e5761275e61433d565b6040519080825280602002602001820160405280156127c057816020015b6127ad60405180606001604052805f63ffffffff168152602001606081526020015f6001600160a01b031681525090565b81526020019060019003908161277c5790505b5090505f5b848110156128b15760405180606001604052808787848181106127ea576127ea61515e565b90506020028101906127fc9190615447565b61280a906020810190615100565b63ffffffff1681526020018787848181106128275761282761515e565b90506020028101906128399190615447565b612847906020810190615119565b808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152505050908252506001600160a01b038616602090910152825183908390811061289e5761289e61515e565b60209081029190910101526001016127c5565b50949350505050565b606654600160ff83161b908116036127405760405163840a48d560e01b815260040160405180910390fd5b5f8181526001830160205260408120541515610949565b5f60608161290d6040860186615119565b90506001600160401b038111156129265761292661433d565b60405190808252806020026020018201604052801561294f578160200160208202803683370190505b50905061295f6040860186615119565b90506001600160401b038111156129785761297861433d565b6040519080825280602002602001820160405280156129a1578160200160208202803683370190505b50915060a55f6129b0866125c6565b81526020019081526020015f205f81546129c990615465565b918290555092505f5b6129df6040870187615119565b9050811015612fe957801580612a7257506129fd6040870187615119565b612a0860018461547d565b818110612a1757612a1761515e565b9050602002016020810190612a2c919061450c565b6001600160a01b0316612a426040880188615119565b83818110612a5257612a5261515e565b9050602002016020810190612a67919061450c565b6001600160a01b0316115b612a8f57604051639f1c805360e01b815260040160405180910390fd5b612a9c6060870187615119565b82818110612aac57612aac61515e565b905060200201355f108015612aec5750670de0b6b3a7640000612ad26060880188615119565b83818110612ae257612ae261515e565b9050602002013511155b612b0957604051631353603160e01b815260040160405180910390fd5b612b65612b196040880188615119565b83818110612b2957612b2961515e565b9050602002016020810190612b3e919061450c565b60995f612b4a896125c6565b81526020019081526020015f20613d5290919063ffffffff16565b612b82576040516331bc342760e11b815260040160405180910390fd5b5f80612bd4612b9460208a018a61450c565b612b9d896125c6565b612baa60408c018c615119565b87818110612bba57612bba61515e565b9050602002016020810190612bcf919061450c565b613852565b805191935091506001600160401b03165f03612bf1575050612fe1565b5f612c2c612c0260608b018b615119565b86818110612c1257612c1261515e565b85516001600160401b031692602090910201359050613d73565b8351909150612c476001600160401b03808416908316613d89565b868681518110612c5957612c5961515e565b60200260200101818152505081835f01818151612c769190615490565b6001600160401b0316905250835182908590612c93908390615490565b6001600160401b0316905250602084018051839190612cb3908390615490565b6001600160401b031690525060208301515f600f9190910b1215612dcb575f612d16612ce260608d018d615119565b88818110612cf257612cf261515e565b905060200201358560200151612d07906154af565b6001600160801b031690613d73565b9050806001600160401b031684602001818151612d3391906154d3565b600f0b9052507f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd612d6760208d018d61450c565b8b612d7560408f018f615119565b8a818110612d8557612d8561515e565b9050602002016020810190612d9a919061450c565b612dab885f01518960200151613a0d565b8860400151604051612dc1959493929190615255565b60405180910390a1505b612e1d612ddb60208c018c61450c565b612de48b6125c6565b612df160408e018e615119565b89818110612e0157612e0161515e565b9050602002016020810190612e16919061450c565b8787613a2c565b7f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd612e4b60208c018c61450c565b8a612e5960408e018e615119565b89818110612e6957612e6961515e565b9050602002016020810190612e7e919061450c565b8651604051612e9294939291904390615255565b60405180910390a1612ee3612eaa60208c018c61450c565b612eb760408d018d615119565b88818110612ec757612ec761515e565b9050602002016020810190612edc919061450c565b8651613d9d565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016635ae679a7612f1f60208d018d61450c565b8b8b8e8060400190612f319190615119565b8b818110612f4157612f4161515e565b9050602002016020810190612f56919061450c565b89516040516001600160e01b031960e088901b168152612f7e95949392918991600401615500565b6020604051808303815f875af1158015612f9a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fbe9190615553565b878681518110612fd057612fd061515e565b602002602001018181525050505050505b6001016129d2565b507f80969ad29428d6797ee7aad084f9e4a42a82fc506dcd2ca3b6fb431f85ccebe5613018602087018761450c565b856130266040890189615119565b8561303460808c018c615396565b604051613047979695949392919061556a565b60405180910390a1509250929050565b6040805180820182526001600160a01b038516808252845163ffffffff90811660208085018290525f938452609890529390912091926130989291613c6416565b6130b557604051631fb1705560e21b815260040160405180910390fd5b7f31629285ead2335ae0933f86ed2ae63321f7af77b4e6eaabc42c057880977e6c816040516130e491906151b2565b60405180910390a16001600160a01b038216620e16e414801590613179578260a65f61310f856125c6565b81526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055507f90a6fa2a9b79b910872ebca540cf3bd8be827f586e6420c30d8836e30012907e8284604051613170929190615335565b60405180910390a15b5f5b8460200151518110156131b8576131b083866020015183815181106131a2576131a261515e565b6020026020010151846132cd565b60010161317b565b506118f48285604001516001613589565b6001600160a01b038381165f90815260a360209081526040808320938616835292905290812054600f81810b600160801b909204900b035b5f8111801561321357508261ffff1682105b156118f4576001600160a01b038086165f90815260a360209081526040808320938816835292905290812061324790613e1f565b90505f5f613256888489613852565b91509150806040015163ffffffff16431015613274575050506118f4565b6132818884898585613a2c565b6001600160a01b038089165f90815260a360209081526040808320938b168352929052206132ae90613e71565b506132b885615465565b94506132c384615600565b9350505050613201565b801561334f576001600160a01b03821673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac01480159061333257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614155b61334f57604051632711b74d60e11b815260040160405180910390fd5b61335f8260995f611e05876125c6565b61337c5760405163585cfb2f60e01b815260040160405180910390fd5b7f7ab260fe0af193db5f4986770d831bda4ea46099dc817e8b6716dcae8af8e88b8383604051612365929190615335565b6001600160a01b0383165f908152609b60209081526040918290208251608081018452905463ffffffff808216835260ff600160201b830416151593830193909352650100000000008104831693820193909352600160481b9092041660608201819052158015906134295750806060015163ffffffff164310155b1561344357604081015163ffffffff168152600160208201525b63ffffffff8316604082015281156134725763ffffffff808416825260016020830152431660608201526134b3565b61349c7f0000000000000000000000000000000000000000000000000000000000000000436151d4565b6134a79060016151d4565b63ffffffff1660608201525b6001600160a01b0384165f818152609b60209081526040918290208451815486840151878601516060808a015163ffffffff95861664ffffffffff1990951694909417600160201b93151593909302929092176cffffffffffffffff0000000000191665010000000000918516919091026cffffffff000000000000000000191617600160481b92841692830217909355845195865290881692850192909252918301527f4e85751d6331506c6c62335f207eb31f12a61e570f34f5c17640308785c6d4db91015b60405180910390a150505050565b6001600160a01b0382166135b0576040516339b190bb60e11b815260040160405180910390fd5b5f60a75f6135bd866125c6565b815260208082019290925260409081015f20815160608101835281546001600160a01b03908116825260019092015491821693810193909352600160a01b900463ffffffff16908201819052909150158015906136245750806040015163ffffffff164310155b1561363a5760208101516001600160a01b031681525b80602001516001600160a01b0316836001600160a01b03161480156136685750806040015163ffffffff1643105b156136735750505050565b6001600160a01b038316602082015281156136a5576001600160a01b038316815263ffffffff431660408201526136e6565b6136cf7f0000000000000000000000000000000000000000000000000000000000000000436151d4565b6136da9060016151d4565b63ffffffff1660408201525b8060a75f6136f3876125c6565b815260208082019290925260409081015f20835181546001600160a01b039182166001600160a01b031990911617825592840151600190910180549483015163ffffffff16600160a01b026001600160c01b031990951691909316179290921790558181015190517f3873f29d7a65a4d75f5ba28909172f486216a1420e77c3c2720815951a6b4f579161357b9187918791615615565b604051631beb2b9760e31b81526001600160a01b0382811660048301523360248301523060448301525f80356001600160e01b0319166064840152917f00000000000000000000000000000000000000000000000000000000000000009091169063df595cb890608401602060405180830381865afa15801561380f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0a9190615193565b5f6109498383613eee565b5f610949836001600160a01b038416613eee565b6040805180820182525f80825260208083018290528351606081018552828152808201839052808501839052845180860186526001600160a01b03898116855260a18452868520908816855290925293822092939281906138b290613fd1565b6001600160401b0390811682526001600160a01b038981165f81815260a260209081526040808320948c168084529482528083205486169682019690965291815260a082528481208b8252825284812092815291815290839020835160608101855290549283168152600160401b8304600f0b91810191909152600160c01b90910463ffffffff169181018290529192504310156139545790925090506139b6565b613965815f01518260200151613a0d565b6001600160401b0316815260208101515f600f9190910b12156139a35761399482602001518260200151613a0d565b6001600160401b031660208301525b5f60408201819052602082015290925090505b935093915050565b5f6139cf8460995f612b4a896125c6565b80156139d85750815b80156139ed575082516001600160401b031615155b95945050505050565b5f6109496001600160401b03808516908416615648565b5f610949613a24836001600160401b0386166154d3565b600f0b613fe4565b6020808301516001600160a01b038088165f90815260a284526040808220928816825291909352909120546001600160401b03908116911614613af257602082810180516001600160a01b038881165f81815260a286526040808220938a1680835293875290819020805467ffffffffffffffff19166001600160401b0395861617905593518451918252948101919091529216908201527facf9095feb3a370c9cf692421c69ef320d4db5c66e6a7d29c7694eb02364fc559060600160405180910390a15b6001600160a01b038086165f90815260a060209081526040808320888452825280832093871683529281529082902083518154928501519385015163ffffffff16600160c01b0263ffffffff60c01b196001600160801b038616600160401b026001600160c01b03199095166001600160401b03909316929092179390931716919091179055600f0b15613bd4576001600160a01b0385165f908152609f602090815260408083208784529091529020613bac9084613c6f565b506001600160a01b0385165f908152609d60205260409020613bce9085613c64565b506118f4565b80516001600160401b03165f036118f4576001600160a01b0385165f908152609f602090815260408083208784529091529020613c11908461383e565b506001600160a01b0385165f908152609f602090815260408083208784529091529020613c3d9061404f565b5f036118f4576001600160a01b0385165f908152609d60205260409020610b709085613833565b5f6109498383614058565b5f610949836001600160a01b038416614058565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613cdf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613d039190615675565b6001600160a01b0316336001600160a01b031614610fed5760405163794821ff60e01b815260040160405180910390fd5b365f5f375f5f365f845af43d5f5f3e808015613d4e573d5ff35b3d5ffd5b6001600160a01b0381165f9081526001830160205260408120541515610949565b5f6109498383670de0b6b3a764000060016140a4565b5f61094983670de0b6b3a7640000846140fd565b6001600160a01b038084165f90815260a160209081526040808320938616835292905220613dcc9043836141e2565b604080516001600160a01b038086168252841660208201526001600160401b038316918101919091527f1c6458079a41077d003c11faf9bf097e693bd67979e4e6500bac7b29db779b5c90606001612365565b5f613e398254600f81810b600160801b909204900b131590565b15613e5757604051631ed9509560e11b815260040160405180910390fd5b508054600f0b5f9081526001909101602052604090205490565b5f613e8b8254600f81810b600160801b909204900b131590565b15613ea957604051631ed9509560e11b815260040160405180910390fd5b508054600f0b5f818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b5f8181526001830160205260408120548015613fc8575f613f1060018361547d565b85549091505f90613f239060019061547d565b9050818114613f82575f865f018281548110613f4157613f4161515e565b905f5260205f200154905080875f018481548110613f6157613f6161515e565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613f9357613f93615690565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610a0a565b5f915050610a0a565b5f610a0a82670de0b6b3a76400006141f6565b5f6001600160401b0382111561404b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b606482015260840161254b565b5090565b5f610a0a825490565b5f81815260018301602052604081205461409d57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610a0a565b505f610a0a565b5f5f6140b18686866140fd565b905060018360028111156140c7576140c76156a4565b1480156140e357505f84806140de576140de6156b8565b868809115b156139ed576140f36001826156cc565b9695505050505050565b5f80805f19858709858702925082811083820303915050805f036141345783828161412a5761412a6156b8565b0492505050610949565b80841161417b5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b604482015260640161254b565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b610fd683836001600160401b03841661423a565b81545f9080156142325761421c8461420f60018461547d565b5f91825260209091200190565b54600160201b90046001600160e01b0316610a06565b509092915050565b825480156142f0575f6142528561420f60018561547d565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090851610156142a45760405163151b8e3f60e11b815260040160405180910390fd5b805163ffffffff8086169116036142ee57826142c58661420f60018661547d565b80546001600160e01b0392909216600160201b0263ffffffff9092169190911790555050505050565b505b506040805180820190915263ffffffff92831681526001600160e01b03918216602080830191825285546001810187555f968752952091519051909216600160201b029190921617910155565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b03811182821017156143735761437361433d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156143a1576143a161433d565b604052919050565b6001600160a01b0381168114612740575f5ffd5b803563ffffffff81168114610a75575f5ffd5b5f604082840312156143e0575f5ffd5b604080519081016001600160401b03811182821017156144025761440261433d565b6040529050808235614413816143a9565b8152614421602084016143bd565b60208201525092915050565b5f6040828403121561443d575f5ffd5b61094983836143d0565b5f5f5f60808486031215614459575f5ffd5b8335614464816143a9565b925061447385602086016143d0565b91506060840135614483816143a9565b809150509250925092565b81516001600160401b03168152602080830151600f0b9082015260408083015163ffffffff169082015260608101610a0a565b5f5f606083850312156144d2575f5ffd5b82356144dd816143a9565b91506144ec84602085016143d0565b90509250929050565b5f60208284031215614505575f5ffd5b5035919050565b5f6020828403121561451c575f5ffd5b8135610949816143a9565b80516001600160a01b0316825260209081015163ffffffff16910152565b5f8151808452602084019350602083015f5b828110156145805761456a868351614527565b6040959095019460209190910190600101614557565b5093949350505050565b602081525f6109496020830184614545565b5f5f83601f8401126145ac575f5ffd5b5081356001600160401b038111156145c2575f5ffd5b6020830191508360208260051b8501011115610d75575f5ffd5b5f5f5f604084860312156145ee575f5ffd5b83356145f9816143a9565b925060208401356001600160401b03811115614613575f5ffd5b61461f8682870161459c565b9497909650939450505050565b5f6001600160401b038211156146445761464461433d565b5060051b60200190565b5f82601f83011261465d575f5ffd5b813561467061466b8261462c565b614379565b8082825260208201915060208360051b860101925085831115614691575f5ffd5b602085015b838110156146b75780356146a9816143a9565b835260209283019201614696565b5095945050505050565b5f5f5f608084860312156146d3575f5ffd5b6146dd85856143d0565b925060408401356001600160401b038111156146f7575f5ffd5b6147038682870161464e565b92505060608401356001600160401b0381111561471e575f5ffd5b61472a8682870161464e565b9150509250925092565b5f8151808452602084019350602083015f5b82811015614580578151865260209586019590910190600101614746565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156147bb57603f198786030184526147a6858351614734565b9450602093840193919091019060010161478a565b50929695505050505050565b5f5f5f5f60a085870312156147da575f5ffd5b6147e486866143d0565b935060408501356001600160401b038111156147fe575f5ffd5b61480a8782880161464e565b93505060608501356001600160401b03811115614825575f5ffd5b6148318782880161464e565b925050614840608086016143bd565b905092959194509250565b5f5f5f5f5f6060868803121561485f575f5ffd5b853561486a816143a9565b945060208601356001600160401b03811115614884575f5ffd5b6148908882890161459c565b90955093505060408601356001600160401b038111156148ae575f5ffd5b6148ba8882890161459c565b969995985093965092949392505050565b5f5f604083850312156148dc575f5ffd5b82356148e7816143a9565b915060208301356001600160401b03811115614901575f5ffd5b830160a08186031215614912575f5ffd5b809150509250929050565b828152604060208201525f610b196040830184614734565b5f82601f830112614944575f5ffd5b813561495261466b8261462c565b8082825260208201915060208360051b860101925085831115614973575f5ffd5b602085015b838110156146b75780356001600160401b03811115614995575f5ffd5b86016060818903601f190112156149aa575f5ffd5b6149b2614351565b6149be602083016143bd565b815260408201356001600160401b038111156149d8575f5ffd5b6149e78a60208386010161464e565b602083015250606082013591506149fd826143a9565b6040810191909152835260209283019201614978565b5f5f60408385031215614a24575f5ffd5b8235614a2f816143a9565b915060208301356001600160401b03811115614a49575f5ffd5b614a5585828601614935565b9150509250929050565b5f5f60408385031215614a70575f5ffd5b8235614a7b816143a9565b91506020830135614912816143a9565b5f8151808452602084019350602083015f5b8281101561458057614ad686835180516001600160401b03168252602080820151600f0b9083015260409081015163ffffffff16910152565b6060959095019460209190910190600101614a9d565b604081525f614afe6040830185614545565b82810360208401526139ed8185614a8b565b602080825282518282018190525f918401906040840190835b81811015614b505783516001600160a01b0316835260209384019390920191600101614b29565b509095945050505050565b5f5f5f60408486031215614b6d575f5ffd5b83356001600160401b03811115614b82575f5ffd5b614b8e8682870161459c565b9094509250506020840135614483816143a9565b602080825282518282018190525f918401906040840190835b81811015614b505783516001600160401b0316835260209384019390920191600101614bbb565b5f5f5f5f60608587031215614bf5575f5ffd5b8435614c00816143a9565b9350614c0e602086016143bd565b925060408501356001600160401b03811115614c28575f5ffd5b614c348782880161459c565b95989497509550505050565b5f5f60408385031215614c51575f5ffd5b8235614c5c816143a9565b91506144ec602084016143bd565b5f60208284031215614c7a575f5ffd5b813560ff81168114610949575f5ffd5b5f5f60608385031215614c9b575f5ffd5b614ca584846143d0565b91506040830135614912816143a9565b5f60608284031215614cc5575f5ffd5b50919050565b5f60208284031215614cdb575f5ffd5b81356001600160401b03811115614cf0575f5ffd5b610a0684828501614cb5565b5f5f5f60808486031215614d0e575f5ffd5b83356001600160401b03811115614d23575f5ffd5b614d2f8682870161464e565b93505061447385602086016143d0565b602081525f6109496020830184614a8b565b5f5f5f5f60608587031215614d64575f5ffd5b8435614d6f816143a9565b935060208501356001600160401b03811115614d89575f5ffd5b614d958782880161459c565b90945092506148409050604086016143bd565b5f5f60408385031215614db9575f5ffd5b8235614dc4816143a9565b915060208301356001600160401b03811115614dde575f5ffd5b8301601f81018513614dee575f5ffd5b8035614dfc61466b8261462c565b8082825260208201915060208360051b850101925087831115614e1d575f5ffd5b602084015b83811015614f425780356001600160401b03811115614e3f575f5ffd5b85016080818b03601f19011215614e54575f5ffd5b614e5c614351565b614e698b602084016143d0565b815260608201356001600160401b03811115614e83575f5ffd5b614e928c60208386010161464e565b60208301525060808201356001600160401b03811115614eb0575f5ffd5b6020818401019250508a601f830112614ec7575f5ffd5b8135614ed561466b8261462c565b8082825260208201915060208360051b86010192508d831115614ef6575f5ffd5b6020850194505b82851015614f2c5784356001600160401b0381168114614f1b575f5ffd5b825260209485019490910190614efd565b6040840152505084525060209283019201614e22565b50809450505050509250929050565b5f60208284031215614f61575f5ffd5b81356001600160401b03811115614f76575f5ffd5b8201601f81018413614f86575f5ffd5b8035614f9461466b8261462c565b8082825260208201915060208360061b850101925086831115614fb5575f5ffd5b6020840193505b828410156140f357614fce87856143d0565b8252602082019150604084019350614fbc565b5f5f5f60408486031215614ff3575f5ffd5b8335614ffe816143a9565b925060208401356001600160401b03811115615018575f5ffd5b8401601f81018613615028575f5ffd5b80356001600160401b0381111561503d575f5ffd5b86602082840101111561504e575f5ffd5b939660209190910195509293505050565b5f5f60408385031215615070575f5ffd5b823561507b816143a9565b915060208301356001600160401b03811115615095575f5ffd5b614a5585828601614cb5565b5f5f5f5f606085870312156150b4575f5ffd5b84356150bf816143a9565b935060208501356001600160401b038111156150d9575f5ffd5b6150e587828801614935565b93505060408501356001600160401b03811115614c28575f5ffd5b5f60208284031215615110575f5ffd5b610949826143bd565b5f5f8335601e1984360301811261512e575f5ffd5b8301803591506001600160401b03821115615147575f5ffd5b6020019150600581901b3603821315610d75575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215615182575f5ffd5b813561ffff81168114610949575f5ffd5b5f602082840312156151a3575f5ffd5b81518015158114610949575f5ffd5b60408101610a0a8284614527565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff8181168382160190811115610a0a57610a0a6151c0565b8183526020830192505f815f5b848110156145805763ffffffff615213836143bd565b16865260209586019591909101906001016151fd565b6001600160a01b038581168252841660208201526060604082018190525f906140f390830184866151f0565b6001600160a01b038616815260c081016152726020830187614527565b6001600160a01b039490941660608201526001600160401b0392909216608083015263ffffffff1660a09091015292915050565b5f602082840312156152b6575f5ffd5b81516001600160401b038111156152cb575f5ffd5b8201601f810184136152db575f5ffd5b80516152e961466b8261462c565b8082825260208201915060208360051b85010192508683111561530a575f5ffd5b6020840193505b828410156140f3578351615324816143a9565b825260209384019390910190615311565b606081016153438285614527565b6001600160a01b039290921660409190910152919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f610b1960208301848661535b565b5f5f8335601e198436030181126153ab575f5ffd5b8301803591506001600160401b038211156153c4575f5ffd5b602001915036819003821315610d75575f5ffd5b6001600160a01b038781168252861660208201526080604082018190525f9061540490830186886151f0565b828103606084015261541781858761535b565b9998505050505050505050565b80516020808301519190811015614cc5575f1960209190910360031b1b16919050565b5f8235603e1983360301811261545b575f5ffd5b9190910192915050565b5f60018201615476576154766151c0565b5060010190565b81810381811115610a0a57610a0a6151c0565b6001600160401b038281168282160390811115610a0a57610a0a6151c0565b5f81600f0b60016001607f1b031981036154cb576154cb6151c0565b5f0392915050565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610a0a57610a0a6151c0565b6001600160a01b038716815260e0810161551d6020830188614527565b60608201959095526001600160a01b039390931660808401526001600160401b0391821660a08401521660c09091015292915050565b5f60208284031215615563575f5ffd5b5051919050565b6001600160a01b03881681525f60c08201615588602084018a614527565b60c060608401528690528660e083015f5b888110156155c95782356155ac816143a9565b6001600160a01b0316825260209283019290910190600101615599565b5083810360808501526155dc8188614734565b91505082810360a08401526155f281858761535b565b9a9950505050505050505050565b5f8161560e5761560e6151c0565b505f190190565b608081016156238286614527565b6001600160a01b0393909316604082015263ffffffff91909116606090910152919050565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610a0a57610a0a6151c0565b5f60208284031215615685575f5ffd5b8151610949816143a9565b634e487b7160e01b5f52603160045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b80820180821115610a0a57610a0a6151c056fea26469706673582212201718e832fb5ab045e193ee493fb8713607c22b0ff8d8e6ed0425a08e7eb7912d64736f6c634300081e00330000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a3400000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f7000000000000000000000000b8765ed72235d279c3fb53936e4606db0ef1280600000000000000000000000025e5f8b1e7adf44518d35d5b2271f114e081f0e500000000000000000000000000000000000000000000000000000000000189c0000000000000000000000000000000000000000000000000000000000001ec30
Deployed Bytecode
0x608060405234801561000f575f5ffd5b5060043610610388575f3560e01c80636c9d7c58116101df578063b66bd98911610109578063d7794857116100a9578063f231bd0811610079578063f231bd08146108d6578063f605ce08146106ab578063fabc1cbc146108e9578063fe4b84df146108fc575f5ffd5b8063d779485714610843578063db4df7611461087a578063dc2af692146108a1578063df5cf723146108af575f5ffd5b8063c221d8ae116100e4578063c221d8ae146107f7578063d1a83f541461080a578063d3d96ff41461081d578063d4a3fcce14610830575f5ffd5b8063b66bd989146107a7578063b9fbaed1146107ba578063ba1a84e5146107e9575f5ffd5b80638ce648541161017f578063a9333ec81161014f578063a9333ec8146106ab578063a982182114610781578063adc2e3d914610794578063b2447af7146105db575f5ffd5b80638ce648541461073257806394d7d00c1461074d578063952899ee1461075b578063957dc50b1461076e575f5ffd5b80636e875dba116101ba5780636e875dba1461056b57806379ae50cd1461043b5780637bc1ef61146106e4578063886f11951461070b575f5ffd5b80636c9d7c58146106985780636cfb4481146106ab5780636e3492b5146106d1575f5ffd5b80633dff8e7d116102c057806350feea20116102605780635ac86ab7116102305780635ac86ab7146106335780635c975abb14610656578063670d3ba21461065e57806367aeaa5314610671575f5ffd5b806350feea20146105f7578063547afb871461060a57806356c483e614610618578063595c6a671461062b575f5ffd5b80634657e26a1161029b5780634657e26a146105865780634a10ffe5146105ad5780634b5046ef146105c85780634cfd2939146105db575f5ffd5b80633dff8e7d1461053757806340120dab1461054a5780634177a87c1461056b575f5ffd5b8063261f84e01161032b5780632bab2c4a116103065780632bab2c4a146104dd578063304c10cd146104f057806332a879e4146105035780633635205714610516575f5ffd5b8063261f84e01461046e5780632981eb77146104815780632b453a9a146104bd575f5ffd5b80631352c3e6116103665780631352c3e614610403578063136439dd1461042657806315fe50281461043b578063260dc7581461045b575f5ffd5b80630b156bb61461038c5780630f3df50e146103d057806310e1b9b8146103e3575b5f5ffd5b6103b37f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a3481565b6040516001600160a01b0390911681526020015b60405180910390f35b6103b36103de36600461442d565b61090f565b6103f66103f1366004614447565b610950565b6040516103c7919061448e565b6104166104113660046144c1565b610995565b60405190151581526020016103c7565b6104396104343660046144f5565b610a10565b005b61044e61044936600461450c565b610a4a565b6040516103c7919061458a565b61041661046936600461442d565b610a7a565b61043961047c3660046145dc565b610aa4565b6104a87f00000000000000000000000000000000000000000000000000000000000189c081565b60405163ffffffff90911681526020016103c7565b6104d06104cb3660046146c1565b610ac3565b6040516103c79190614764565b6104d06104eb3660046147c7565b610aee565b6103b36104fe36600461450c565b610b21565b61043961051136600461484b565b610b50565b6105296105243660046148cb565b610b78565b6040516103c792919061491d565b610439610545366004614a13565b610ccd565b61055d610558366004614a5f565b610d49565b6040516103c7929190614aec565b61057961044936600461442d565b6040516103c79190614b10565b6103b37f00000000000000000000000025e5f8b1e7adf44518d35d5b2271f114e081f0e581565b6105bb6104cb366004614b5b565b6040516103c79190614ba2565b6104396105d636600461484b565b610d7c565b6105e961046936600461442d565b6040519081526020016103c7565b610439610605366004614be2565b610e18565b6105bb6104cb3660046145dc565b610439610626366004614c40565b610eec565b610439610fdb565b610416610641366004614c6a565b606654600160ff9092169190911b9081161490565b6066546105e9565b61041661066c3660046144c1565b610fef565b6104a87f000000000000000000000000000000000000000000000000000000000001ec3081565b6104396106a6366004614c8a565b611019565b6106b961066c366004614a5f565b6040516001600160401b0390911681526020016103c7565b6104396106df366004614ccb565b6110af565b6104a87f000000000000000000000000000000000000000000000000000000000001ec3081565b6103b37f000000000000000000000000b8765ed72235d279c3fb53936e4606db0ef1280681565b6107406104cb366004614cfc565b6040516103c79190614d3f565b6105bb6104eb366004614d51565b610439610769366004614da8565b61146a565b61043961077c366004614f51565b6118fb565b61043961078f366004614fe1565b611b86565b6104396107a236600461505f565b611c1b565b6104396107b5366004614be2565b611f47565b6107cd6107c836600461450c565b612084565b60408051921515835263ffffffff9091166020830152016103c7565b6105e961046936600461450c565b6105796108053660046144c1565b61211e565b6104396108183660046150a1565b612149565b61043961082b366004614a5f565b612262565b6103b361083e36600461442d565b612372565b61085661085136600461442d565b6123f9565b604080516001600160a01b03909316835263ffffffff9091166020830152016103c7565b6103b37f000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f781565b61041661046936600461450c565b6103b37f00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a81565b6104166108e436600461442d565b612429565b6104396108f73660046144f5565b612448565b61043961090a3660046144f5565b6124b5565b5f5f60a65f61091d856125c6565b815260208101919091526040015f20546001600160a01b0316905080156109445780610949565b620e16e45b9392505050565b604080516060810182525f80825260208201819052918101919091526109497f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b6001600160a01b0382165f908152609e602052604081208190816109b8856125c6565b815260208082019290925260409081015f2081518083019092525460ff8116151580835261010090910463ffffffff1692820192909252915080610a065750806020015163ffffffff164311155b9150505b92915050565b610a1861263a565b6066548181168114610a3d5760405163c61dca5d60e01b815260040160405180910390fd5b610a46826126dd565b5050565b6060610a757f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b919050565b5f610a757f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b82610aae8161271a565b610abd84610545858588612743565b50505050565b60606109497f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b6060610b197f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b949350505050565b6001600160a01b038082165f908152609760205260408120549091168015610b495780610949565b5090919050565b84610b5a8161271a565b610b7086610b6987878a612743565b8585612149565b505050505050565b5f60606001610b86816128ba565b5f6040518060400160405280876001600160a01b03168152602001866020016020810190610bb49190615100565b63ffffffff1690529050610bcb6060860186615119565b9050610bda6040870187615119565b905014610bfa576040516343714afd60e01b815260040160405180910390fd5b60208082015182516001600160a01b03165f90815260989092526040909120610c2c9163ffffffff908116906128e516565b610c4957604051631fb1705560e21b815260040160405180910390fd5b610c5f610c59602087018761450c565b82610995565b610c7c5760405163ebbff49760e01b815260040160405180910390fd5b610c8581612372565b6001600160a01b0316336001600160a01b031614610cb6576040516348f5c3ed60e01b815260040160405180910390fd5b610cc085826128fc565b9350935050509250929050565b81610cd78161271a565b6001600160a01b0383165f90815260a4602052604090205460ff16610d0f576040516348f7dbb960e01b815260040160405180910390fd5b5f5b8251811015610abd57610d4184848381518110610d3057610d3061515e565b6020026020010151620e16e4613057565b600101610d11565b606080610d757f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b9250929050565b5f610d86816128ba565b838214610da6576040516343714afd60e01b815260040160405180910390fd5b5f5b84811015610e0f57610e0787878784818110610dc657610dc661515e565b9050602002016020810190610ddb919061450c565b868685818110610ded57610ded61515e565b9050602002016020810190610e029190615172565b6131c9565b600101610da8565b50505050505050565b83610e228161271a565b6040805180820182526001600160a01b03871680825263ffffffff80881660208085018290525f93845260989052939091209192610e6192916128e516565b610e7e57604051631fb1705560e21b815260040160405180910390fd5b5f5b83811015610e0f57610ee482868684818110610e9e57610e9e61515e565b9050602002016020810190610eb3919061450c565b610edf60405180604001604052808c6001600160a01b031681526020018b63ffffffff16815250612429565b6132cd565b600101610e80565b336001600160a01b037f00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a161480610fcb57610f268361271a565b6040516336b87bd760e11b81526001600160a01b0384811660048301527f00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a1690636d70f7ae90602401602060405180830381865afa158015610f8a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fae9190615193565b610fcb5760405163ccea9e6f60e01b815260040160405180910390fd5b610fd68383836133ad565b505050565b610fe361263a565b610fed5f196126dd565b565b5f610a0a7f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b81516110248161271a565b60208084015184516001600160a01b03165f908152609890925260409091206110569163ffffffff908116906128e516565b61107357604051631fb1705560e21b815260040160405180910390fd5b5f61107d84612372565b6001600160a01b0316036110a45760405163255b0f4160e01b815260040160405180910390fd5b610fd683835f613589565b60026110ba816128ba565b6110cf6110ca602084018461450c565b61378a565b806110e857506110e86110ca604084016020850161450c565b611105576040516348f5c3ed60e01b815260040160405180910390fd5b5f5b6111146040840184615119565b90508110156113d6575f604051806040016040528085602001602081019061113c919061450c565b6001600160a01b031681526020016111576040870187615119565b858181106111675761116761515e565b905060200201602081019061117c9190615100565b63ffffffff1681525090506111c9816020015163ffffffff1660985f8760200160208101906111ab919061450c565b6001600160a01b0316815260208101919091526040015f20906128e5565b6111e657604051631fb1705560e21b815260040160405180910390fd5b609e5f6111f6602087018761450c565b6001600160a01b03166001600160a01b031681526020019081526020015f205f61121f836125c6565b815260208101919091526040015f205460ff1661124f576040516325131d4f60e01b815260040160405180910390fd5b61128961125b826125c6565b609c5f61126b602089018961450c565b6001600160a01b0316815260208101919091526040015f2090613833565b506112c161129a602086018661450c565b609a5f6112a6856125c6565b81526020019081526020015f2061383e90919063ffffffff16565b506112cf602085018561450c565b6001600160a01b03167fad34c3070be1dffbcaa499d000ba2b8d9848aefcac3059df245dd95c4ece14fe8260405161130791906151b2565b60405180910390a2604080518082019091525f81526020810161134a7f00000000000000000000000000000000000000000000000000000000000189c0436151d4565b63ffffffff169052609e5f611362602088018861450c565b6001600160a01b03166001600160a01b031681526020019081526020015f205f61138b846125c6565b81526020808201929092526040015f2082518154939092015163ffffffff166101000264ffffffff00199215159290921664ffffffffff199093169290921717905550600101611107565b506113ea6104fe604084016020850161450c565b6001600160a01b031663303ca956611405602085018561450c565b611415604086016020870161450c565b6114226040870187615119565b6040518563ffffffff1660e01b81526004016114419493929190615229565b5f604051808303815f87803b158015611458575f5ffd5b505af1158015610b70573d5f5f3e3d5ffd5b5f611474816128ba565b61147d8361271a565b5f5f5f61148986612084565b91509150816114ab5760405163fa55fc8160e01b815260040160405180910390fd5b91505f90505b83518110156118f4578381815181106114cc576114cc61515e565b602002602001015160400151518482815181106114eb576114eb61515e565b6020026020010151602001515114611516576040516343714afd60e01b815260040160405180910390fd5b5f8482815181106115295761152961515e565b602090810291909101810151518082015181516001600160a01b03165f908152609890935260409092209092506115699163ffffffff908116906128e516565b61158657604051631fb1705560e21b815260040160405180910390fd5b5f6115918783610995565b90505f5b8684815181106115a7576115a761515e565b602002602001015160200151518110156118e9575f8785815181106115ce576115ce61515e565b60200260200101516020015182815181106115eb576115eb61515e565b60200260200101519050611602898261ffff6131c9565b5f5f6116178b611611886125c6565b85613852565b91509150806040015163ffffffff165f1461164557604051630d8fcbe360e41b815260040160405180910390fd5b5f611652878584896139be565b9050611697825f01518c8a8151811061166d5761166d61515e565b602002602001015160400151878151811061168a5761168a61515e565b60200260200101516139f6565b600f0b602083018190525f036116c057604051634606179360e11b815260040160405180910390fd5b5f8260200151600f0b1215611804578015611786576117416116e1886125c6565b6001600160a01b03808f165f90815260a360209081526040808320938a16835292905220908154600160801b90819004600f0b5f818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b61176b7f00000000000000000000000000000000000000000000000000000000000189c0436151d4565b6117769060016151d4565b63ffffffff166040830152611871565b61179883602001518360200151613a0d565b6001600160401b031660208401528a518b90899081106117ba576117ba61515e565b60200260200101516040015185815181106117d7576117d761515e565b6020908102919091018101516001600160401b031683525f9083015263ffffffff43166040830152611871565b5f8260200151600f0b13156118715761182583602001518360200151613a0d565b6001600160401b03908116602085018190528451909116101561185b57604051636c9be0bf60e01b815260040160405180910390fd5b61186589436151d4565b63ffffffff1660408301525b6118868c61187e896125c6565b868686613a2c565b7f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd8c88866118bb865f01518760200151613a0d565b86604001516040516118d1959493929190615255565b60405180910390a15050600190920191506115959050565b5050506001016114b1565b5050505050565b5f5b8151811015610a465761197a82828151811061191b5761191b61515e565b60200260200101516020015163ffffffff1660985f8585815181106119425761194261515e565b60200260200101515f01516001600160a01b03166001600160a01b031681526020019081526020015f206128e590919063ffffffff16565b15611b7e575f6001600160a01b03166119ab83838151811061199e5761199e61515e565b6020026020010151612372565b6001600160a01b031603611b7e575f7f00000000000000000000000025e5f8b1e7adf44518d35d5b2271f114e081f0e56001600160a01b031663fddbdefd8484815181106119fb576119fb61515e565b6020908102919091010151516040516001600160e01b031960e084901b1681526001600160a01b039091166004820152306024820152633635205760e01b60448201526064015f60405180830381865afa158015611a5b573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611a8291908101906152a6565b90505f81515f1480611abe57505f6001600160a01b0316825f81518110611aab57611aab61515e565b60200260200101516001600160a01b0316145b15611ae757838381518110611ad557611ad561515e565b60200260200101515f01519050611b04565b815f81518110611af957611af961515e565b602002602001015190505b611b29848481518110611b1957611b1961515e565b6020026020010151826001613589565b7ff0c8fc7d71f647bd3a88ac369112517f6a4b8038e71913f2d20f71f877dfc725848481518110611b5c57611b5c61515e565b602002602001015182604051611b73929190615335565b60405180910390a150505b6001016118fd565b82611b908161271a565b6001600160a01b0384165f90815260a4602052604090205460ff16611bd2576001600160a01b0384165f90815260a460205260409020805460ff191660011790555b836001600160a01b03167fa89c1dc243d8908a96dd84944bcc97d6bc6ac00dd78e20621576be6a3c9437138484604051611c0d929190615383565b60405180910390a250505050565b6002611c26816128ba565b82611c308161271a565b6040516336b87bd760e11b81526001600160a01b0385811660048301527f00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a1690636d70f7ae90602401602060405180830381865afa158015611c94573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cb89190615193565b611cd55760405163ccea9e6f60e01b815260040160405180910390fd5b5f5b611ce46020850185615119565b9050811015611eac57604080518082019091525f9080611d07602088018861450c565b6001600160a01b03168152602001868060200190611d259190615119565b85818110611d3557611d3561515e565b9050602002016020810190611d4a9190615100565b63ffffffff90811690915260208083015183516001600160a01b03165f90815260989092526040909120929350611d869291908116906128e516565b611da357604051631fb1705560e21b815260040160405180910390fd5b611dad8682610995565b15611dcb57604051636c6c6e2760e11b815260040160405180910390fd5b611df4611dd7826125c6565b6001600160a01b0388165f908152609c6020526040902090613c64565b50611e2086609a5f611e05856125c6565b81526020019081526020015f20613c6f90919063ffffffff16565b50856001600160a01b03167f43232edf9071753d2321e5fa7e018363ee248e5f2142e6c08edd3265bfb4895e82604051611e5a91906151b2565b60405180910390a26001600160a01b0386165f908152609e60205260408120600191611e85846125c6565b815260208101919091526040015f20805460ff191691151591909117905550600101611cd7565b50611ebd6104fe602085018561450c565b6001600160a01b031663c63fd50285611ed9602087018761450c565b611ee66020880188615119565b611ef360408a018a615396565b6040518763ffffffff1660e01b8152600401611f14969594939291906153d8565b5f604051808303815f87803b158015611f2b575f5ffd5b505af1158015611f3d573d5f5f3e3d5ffd5b5050505050505050565b83611f518161271a565b6040805180820182526001600160a01b03871680825263ffffffff80881660208085018290525f93845260989052939091209192611f9092916128e516565b611fad57604051631fb1705560e21b815260040160405180910390fd5b5f611fb7826125c6565b90505f5b84811015611f3d57612000868683818110611fd857611fd861515e565b9050602002016020810190611fed919061450c565b5f8481526099602052604090209061383e565b61201d576040516331bc342760e11b815260040160405180910390fd5b7f7b4b073d80dcac55a11177d8459ad9f664ceeb91f71f27167bb14f8152a7eeee838787848181106120515761205161515e565b9050602002016020810190612066919061450c565b604051612074929190615335565b60405180910390a1600101611fbb565b6001600160a01b0381165f908152609b602090815260408083208151608081018352905463ffffffff80821680845260ff600160201b8404161515958401869052650100000000008304821694840194909452600160481b9091041660608201819052849391929190158015906121055750826060015163ffffffff164310155b15612114575050604081015160015b9590945092505050565b6060610a0a7f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b836121538161271a565b83518214612174576040516343714afd60e01b815260040160405180910390fd5b6001600160a01b0385165f90815260a4602052604090205460ff166121ac576040516348f7dbb960e01b815260040160405180910390fd5b5f5b8451811015610b70575f8484838181106121ca576121ca61515e565b90506020020160208101906121df919061450c565b90506001600160a01b038116612208576040516339b190bb60e11b815260040160405180910390fd5b620e16e3196001600160a01b03821601612235576040516364be1a3f60e11b815260040160405180910390fd5b6122598787848151811061224b5761224b61515e565b602002602001015183613057565b506001016121ae565b8161226c8161271a565b60405163b526578760e01b81526001600160a01b03848116600483015283169063b526578790602401602060405180830381865afa1580156122b0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122d49190615193565b6122f157604051631d0b13c160e31b815260040160405180910390fd5b6001600160a01b038381165f90815260976020526040902080546001600160a01b0319169184169190911790557f2ae945c40c44dc0ec263f95609c3fdc6952e0aefa22d6374e44f2c997acedf858361234981610b21565b604080516001600160a01b039384168152929091166020830152015b60405180910390a1505050565b5f5f60a75f612380856125c6565b815260208082019290925260409081015f20815160608101835281546001600160a01b0390811680835260019093015490811694820194909452600160a01b90930463ffffffff16918301829052919250158015906123e95750816040015163ffffffff164310155b1561094957506020015192915050565b5f5f6124247f0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34612629565b915091565b5f620e16e46124378361090f565b6001600160a01b0316141592915050565b612450613c83565b606654801982198116146124775760405163c61dca5d60e01b815260040160405180910390fd5b606682905560405182815233907f3582d1828e26bf56bd801502bc021ac0bc8afb57c826e4986b45593c8fad389c9060200160405180910390a25050565b5f54610100900460ff16158080156124d357505f54600160ff909116105b806124ec5750303b1580156124ec57505f5460ff166001145b6125545760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084015b60405180910390fd5b5f805460ff191660011790558015612575575f805461ff0019166101001790555b61257e826126dd565b8015610a46575f805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b5f815f0151826020015163ffffffff1660405160200161261192919060609290921b6bffffffffffffffffffffffff1916825260a01b6001600160a01b031916601482015260200190565b604051602081830303815290604052610a0a90615424565b613d3480610fd68363ffffffff8316565b60405163237dfb4760e11b81523360048201527f000000000000000000000000b8765ed72235d279c3fb53936e4606db0ef128066001600160a01b0316906346fbf68e90602401602060405180830381865afa15801561269c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c09190615193565b610fed57604051631d77d47760e21b815260040160405180910390fd5b606681905560405181815233907fab40a374bc51de372200a8bc981af8c9ecdc08dfdaef0bb6e09f88f3c616ef3d9060200160405180910390a250565b6127238161378a565b6127405760405163932d94f760e01b815260040160405180910390fd5b50565b60605f836001600160401b0381111561275e5761275e61433d565b6040519080825280602002602001820160405280156127c057816020015b6127ad60405180606001604052805f63ffffffff168152602001606081526020015f6001600160a01b031681525090565b81526020019060019003908161277c5790505b5090505f5b848110156128b15760405180606001604052808787848181106127ea576127ea61515e565b90506020028101906127fc9190615447565b61280a906020810190615100565b63ffffffff1681526020018787848181106128275761282761515e565b90506020028101906128399190615447565b612847906020810190615119565b808060200260200160405190810160405280939291908181526020018383602002808284375f920191909152505050908252506001600160a01b038616602090910152825183908390811061289e5761289e61515e565b60209081029190910101526001016127c5565b50949350505050565b606654600160ff83161b908116036127405760405163840a48d560e01b815260040160405180910390fd5b5f8181526001830160205260408120541515610949565b5f60608161290d6040860186615119565b90506001600160401b038111156129265761292661433d565b60405190808252806020026020018201604052801561294f578160200160208202803683370190505b50905061295f6040860186615119565b90506001600160401b038111156129785761297861433d565b6040519080825280602002602001820160405280156129a1578160200160208202803683370190505b50915060a55f6129b0866125c6565b81526020019081526020015f205f81546129c990615465565b918290555092505f5b6129df6040870187615119565b9050811015612fe957801580612a7257506129fd6040870187615119565b612a0860018461547d565b818110612a1757612a1761515e565b9050602002016020810190612a2c919061450c565b6001600160a01b0316612a426040880188615119565b83818110612a5257612a5261515e565b9050602002016020810190612a67919061450c565b6001600160a01b0316115b612a8f57604051639f1c805360e01b815260040160405180910390fd5b612a9c6060870187615119565b82818110612aac57612aac61515e565b905060200201355f108015612aec5750670de0b6b3a7640000612ad26060880188615119565b83818110612ae257612ae261515e565b9050602002013511155b612b0957604051631353603160e01b815260040160405180910390fd5b612b65612b196040880188615119565b83818110612b2957612b2961515e565b9050602002016020810190612b3e919061450c565b60995f612b4a896125c6565b81526020019081526020015f20613d5290919063ffffffff16565b612b82576040516331bc342760e11b815260040160405180910390fd5b5f80612bd4612b9460208a018a61450c565b612b9d896125c6565b612baa60408c018c615119565b87818110612bba57612bba61515e565b9050602002016020810190612bcf919061450c565b613852565b805191935091506001600160401b03165f03612bf1575050612fe1565b5f612c2c612c0260608b018b615119565b86818110612c1257612c1261515e565b85516001600160401b031692602090910201359050613d73565b8351909150612c476001600160401b03808416908316613d89565b868681518110612c5957612c5961515e565b60200260200101818152505081835f01818151612c769190615490565b6001600160401b0316905250835182908590612c93908390615490565b6001600160401b0316905250602084018051839190612cb3908390615490565b6001600160401b031690525060208301515f600f9190910b1215612dcb575f612d16612ce260608d018d615119565b88818110612cf257612cf261515e565b905060200201358560200151612d07906154af565b6001600160801b031690613d73565b9050806001600160401b031684602001818151612d3391906154d3565b600f0b9052507f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd612d6760208d018d61450c565b8b612d7560408f018f615119565b8a818110612d8557612d8561515e565b9050602002016020810190612d9a919061450c565b612dab885f01518960200151613a0d565b8860400151604051612dc1959493929190615255565b60405180910390a1505b612e1d612ddb60208c018c61450c565b612de48b6125c6565b612df160408e018e615119565b89818110612e0157612e0161515e565b9050602002016020810190612e16919061450c565b8787613a2c565b7f1487af5418c47ee5ea45ef4a93398668120890774a9e13487e61e9dc3baf76dd612e4b60208c018c61450c565b8a612e5960408e018e615119565b89818110612e6957612e6961515e565b9050602002016020810190612e7e919061450c565b8651604051612e9294939291904390615255565b60405180910390a1612ee3612eaa60208c018c61450c565b612eb760408d018d615119565b88818110612ec757612ec761515e565b9050602002016020810190612edc919061450c565b8651613d9d565b6001600160a01b037f00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a16635ae679a7612f1f60208d018d61450c565b8b8b8e8060400190612f319190615119565b8b818110612f4157612f4161515e565b9050602002016020810190612f56919061450c565b89516040516001600160e01b031960e088901b168152612f7e95949392918991600401615500565b6020604051808303815f875af1158015612f9a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fbe9190615553565b878681518110612fd057612fd061515e565b602002602001018181525050505050505b6001016129d2565b507f80969ad29428d6797ee7aad084f9e4a42a82fc506dcd2ca3b6fb431f85ccebe5613018602087018761450c565b856130266040890189615119565b8561303460808c018c615396565b604051613047979695949392919061556a565b60405180910390a1509250929050565b6040805180820182526001600160a01b038516808252845163ffffffff90811660208085018290525f938452609890529390912091926130989291613c6416565b6130b557604051631fb1705560e21b815260040160405180910390fd5b7f31629285ead2335ae0933f86ed2ae63321f7af77b4e6eaabc42c057880977e6c816040516130e491906151b2565b60405180910390a16001600160a01b038216620e16e414801590613179578260a65f61310f856125c6565b81526020019081526020015f205f6101000a8154816001600160a01b0302191690836001600160a01b031602179055507f90a6fa2a9b79b910872ebca540cf3bd8be827f586e6420c30d8836e30012907e8284604051613170929190615335565b60405180910390a15b5f5b8460200151518110156131b8576131b083866020015183815181106131a2576131a261515e565b6020026020010151846132cd565b60010161317b565b506118f48285604001516001613589565b6001600160a01b038381165f90815260a360209081526040808320938616835292905290812054600f81810b600160801b909204900b035b5f8111801561321357508261ffff1682105b156118f4576001600160a01b038086165f90815260a360209081526040808320938816835292905290812061324790613e1f565b90505f5f613256888489613852565b91509150806040015163ffffffff16431015613274575050506118f4565b6132818884898585613a2c565b6001600160a01b038089165f90815260a360209081526040808320938b168352929052206132ae90613e71565b506132b885615465565b94506132c384615600565b9350505050613201565b801561334f576001600160a01b03821673beac0eeeeeeeeeeeeeeeeeeeeeeeeeeeeeebeac01480159061333257507f000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f76001600160a01b0316826001600160a01b031614155b61334f57604051632711b74d60e11b815260040160405180910390fd5b61335f8260995f611e05876125c6565b61337c5760405163585cfb2f60e01b815260040160405180910390fd5b7f7ab260fe0af193db5f4986770d831bda4ea46099dc817e8b6716dcae8af8e88b8383604051612365929190615335565b6001600160a01b0383165f908152609b60209081526040918290208251608081018452905463ffffffff808216835260ff600160201b830416151593830193909352650100000000008104831693820193909352600160481b9092041660608201819052158015906134295750806060015163ffffffff164310155b1561344357604081015163ffffffff168152600160208201525b63ffffffff8316604082015281156134725763ffffffff808416825260016020830152431660608201526134b3565b61349c7f000000000000000000000000000000000000000000000000000000000001ec30436151d4565b6134a79060016151d4565b63ffffffff1660608201525b6001600160a01b0384165f818152609b60209081526040918290208451815486840151878601516060808a015163ffffffff95861664ffffffffff1990951694909417600160201b93151593909302929092176cffffffffffffffff0000000000191665010000000000918516919091026cffffffff000000000000000000191617600160481b92841692830217909355845195865290881692850192909252918301527f4e85751d6331506c6c62335f207eb31f12a61e570f34f5c17640308785c6d4db91015b60405180910390a150505050565b6001600160a01b0382166135b0576040516339b190bb60e11b815260040160405180910390fd5b5f60a75f6135bd866125c6565b815260208082019290925260409081015f20815160608101835281546001600160a01b03908116825260019092015491821693810193909352600160a01b900463ffffffff16908201819052909150158015906136245750806040015163ffffffff164310155b1561363a5760208101516001600160a01b031681525b80602001516001600160a01b0316836001600160a01b03161480156136685750806040015163ffffffff1643105b156136735750505050565b6001600160a01b038316602082015281156136a5576001600160a01b038316815263ffffffff431660408201526136e6565b6136cf7f000000000000000000000000000000000000000000000000000000000001ec30436151d4565b6136da9060016151d4565b63ffffffff1660408201525b8060a75f6136f3876125c6565b815260208082019290925260409081015f20835181546001600160a01b039182166001600160a01b031990911617825592840151600190910180549483015163ffffffff16600160a01b026001600160c01b031990951691909316179290921790558181015190517f3873f29d7a65a4d75f5ba28909172f486216a1420e77c3c2720815951a6b4f579161357b9187918791615615565b604051631beb2b9760e31b81526001600160a01b0382811660048301523360248301523060448301525f80356001600160e01b0319166064840152917f00000000000000000000000025e5f8b1e7adf44518d35d5b2271f114e081f0e59091169063df595cb890608401602060405180830381865afa15801561380f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0a9190615193565b5f6109498383613eee565b5f610949836001600160a01b038416613eee565b6040805180820182525f80825260208083018290528351606081018552828152808201839052808501839052845180860186526001600160a01b03898116855260a18452868520908816855290925293822092939281906138b290613fd1565b6001600160401b0390811682526001600160a01b038981165f81815260a260209081526040808320948c168084529482528083205486169682019690965291815260a082528481208b8252825284812092815291815290839020835160608101855290549283168152600160401b8304600f0b91810191909152600160c01b90910463ffffffff169181018290529192504310156139545790925090506139b6565b613965815f01518260200151613a0d565b6001600160401b0316815260208101515f600f9190910b12156139a35761399482602001518260200151613a0d565b6001600160401b031660208301525b5f60408201819052602082015290925090505b935093915050565b5f6139cf8460995f612b4a896125c6565b80156139d85750815b80156139ed575082516001600160401b031615155b95945050505050565b5f6109496001600160401b03808516908416615648565b5f610949613a24836001600160401b0386166154d3565b600f0b613fe4565b6020808301516001600160a01b038088165f90815260a284526040808220928816825291909352909120546001600160401b03908116911614613af257602082810180516001600160a01b038881165f81815260a286526040808220938a1680835293875290819020805467ffffffffffffffff19166001600160401b0395861617905593518451918252948101919091529216908201527facf9095feb3a370c9cf692421c69ef320d4db5c66e6a7d29c7694eb02364fc559060600160405180910390a15b6001600160a01b038086165f90815260a060209081526040808320888452825280832093871683529281529082902083518154928501519385015163ffffffff16600160c01b0263ffffffff60c01b196001600160801b038616600160401b026001600160c01b03199095166001600160401b03909316929092179390931716919091179055600f0b15613bd4576001600160a01b0385165f908152609f602090815260408083208784529091529020613bac9084613c6f565b506001600160a01b0385165f908152609d60205260409020613bce9085613c64565b506118f4565b80516001600160401b03165f036118f4576001600160a01b0385165f908152609f602090815260408083208784529091529020613c11908461383e565b506001600160a01b0385165f908152609f602090815260408083208784529091529020613c3d9061404f565b5f036118f4576001600160a01b0385165f908152609d60205260409020610b709085613833565b5f6109498383614058565b5f610949836001600160a01b038416614058565b7f000000000000000000000000b8765ed72235d279c3fb53936e4606db0ef128066001600160a01b031663eab66d7a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613cdf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190613d039190615675565b6001600160a01b0316336001600160a01b031614610fed5760405163794821ff60e01b815260040160405180910390fd5b365f5f375f5f365f845af43d5f5f3e808015613d4e573d5ff35b3d5ffd5b6001600160a01b0381165f9081526001830160205260408120541515610949565b5f6109498383670de0b6b3a764000060016140a4565b5f61094983670de0b6b3a7640000846140fd565b6001600160a01b038084165f90815260a160209081526040808320938616835292905220613dcc9043836141e2565b604080516001600160a01b038086168252841660208201526001600160401b038316918101919091527f1c6458079a41077d003c11faf9bf097e693bd67979e4e6500bac7b29db779b5c90606001612365565b5f613e398254600f81810b600160801b909204900b131590565b15613e5757604051631ed9509560e11b815260040160405180910390fd5b508054600f0b5f9081526001909101602052604090205490565b5f613e8b8254600f81810b600160801b909204900b131590565b15613ea957604051631ed9509560e11b815260040160405180910390fd5b508054600f0b5f818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b5f8181526001830160205260408120548015613fc8575f613f1060018361547d565b85549091505f90613f239060019061547d565b9050818114613f82575f865f018281548110613f4157613f4161515e565b905f5260205f200154905080875f018481548110613f6157613f6161515e565b5f918252602080832090910192909255918252600188019052604090208390555b8554869080613f9357613f93615690565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610a0a565b5f915050610a0a565b5f610a0a82670de0b6b3a76400006141f6565b5f6001600160401b0382111561404b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b606482015260840161254b565b5090565b5f610a0a825490565b5f81815260018301602052604081205461409d57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610a0a565b505f610a0a565b5f5f6140b18686866140fd565b905060018360028111156140c7576140c76156a4565b1480156140e357505f84806140de576140de6156b8565b868809115b156139ed576140f36001826156cc565b9695505050505050565b5f80805f19858709858702925082811083820303915050805f036141345783828161412a5761412a6156b8565b0492505050610949565b80841161417b5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b604482015260640161254b565b5f8486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091025f889003889004909101858311909403939093029303949094049190911702949350505050565b610fd683836001600160401b03841661423a565b81545f9080156142325761421c8461420f60018461547d565b5f91825260209091200190565b54600160201b90046001600160e01b0316610a06565b509092915050565b825480156142f0575f6142528561420f60018561547d565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090851610156142a45760405163151b8e3f60e11b815260040160405180910390fd5b805163ffffffff8086169116036142ee57826142c58661420f60018661547d565b80546001600160e01b0392909216600160201b0263ffffffff9092169190911790555050505050565b505b506040805180820190915263ffffffff92831681526001600160e01b03918216602080830191825285546001810187555f968752952091519051909216600160201b029190921617910155565b634e487b7160e01b5f52604160045260245ffd5b604051606081016001600160401b03811182821017156143735761437361433d565b60405290565b604051601f8201601f191681016001600160401b03811182821017156143a1576143a161433d565b604052919050565b6001600160a01b0381168114612740575f5ffd5b803563ffffffff81168114610a75575f5ffd5b5f604082840312156143e0575f5ffd5b604080519081016001600160401b03811182821017156144025761440261433d565b6040529050808235614413816143a9565b8152614421602084016143bd565b60208201525092915050565b5f6040828403121561443d575f5ffd5b61094983836143d0565b5f5f5f60808486031215614459575f5ffd5b8335614464816143a9565b925061447385602086016143d0565b91506060840135614483816143a9565b809150509250925092565b81516001600160401b03168152602080830151600f0b9082015260408083015163ffffffff169082015260608101610a0a565b5f5f606083850312156144d2575f5ffd5b82356144dd816143a9565b91506144ec84602085016143d0565b90509250929050565b5f60208284031215614505575f5ffd5b5035919050565b5f6020828403121561451c575f5ffd5b8135610949816143a9565b80516001600160a01b0316825260209081015163ffffffff16910152565b5f8151808452602084019350602083015f5b828110156145805761456a868351614527565b6040959095019460209190910190600101614557565b5093949350505050565b602081525f6109496020830184614545565b5f5f83601f8401126145ac575f5ffd5b5081356001600160401b038111156145c2575f5ffd5b6020830191508360208260051b8501011115610d75575f5ffd5b5f5f5f604084860312156145ee575f5ffd5b83356145f9816143a9565b925060208401356001600160401b03811115614613575f5ffd5b61461f8682870161459c565b9497909650939450505050565b5f6001600160401b038211156146445761464461433d565b5060051b60200190565b5f82601f83011261465d575f5ffd5b813561467061466b8261462c565b614379565b8082825260208201915060208360051b860101925085831115614691575f5ffd5b602085015b838110156146b75780356146a9816143a9565b835260209283019201614696565b5095945050505050565b5f5f5f608084860312156146d3575f5ffd5b6146dd85856143d0565b925060408401356001600160401b038111156146f7575f5ffd5b6147038682870161464e565b92505060608401356001600160401b0381111561471e575f5ffd5b61472a8682870161464e565b9150509250925092565b5f8151808452602084019350602083015f5b82811015614580578151865260209586019590910190600101614746565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156147bb57603f198786030184526147a6858351614734565b9450602093840193919091019060010161478a565b50929695505050505050565b5f5f5f5f60a085870312156147da575f5ffd5b6147e486866143d0565b935060408501356001600160401b038111156147fe575f5ffd5b61480a8782880161464e565b93505060608501356001600160401b03811115614825575f5ffd5b6148318782880161464e565b925050614840608086016143bd565b905092959194509250565b5f5f5f5f5f6060868803121561485f575f5ffd5b853561486a816143a9565b945060208601356001600160401b03811115614884575f5ffd5b6148908882890161459c565b90955093505060408601356001600160401b038111156148ae575f5ffd5b6148ba8882890161459c565b969995985093965092949392505050565b5f5f604083850312156148dc575f5ffd5b82356148e7816143a9565b915060208301356001600160401b03811115614901575f5ffd5b830160a08186031215614912575f5ffd5b809150509250929050565b828152604060208201525f610b196040830184614734565b5f82601f830112614944575f5ffd5b813561495261466b8261462c565b8082825260208201915060208360051b860101925085831115614973575f5ffd5b602085015b838110156146b75780356001600160401b03811115614995575f5ffd5b86016060818903601f190112156149aa575f5ffd5b6149b2614351565b6149be602083016143bd565b815260408201356001600160401b038111156149d8575f5ffd5b6149e78a60208386010161464e565b602083015250606082013591506149fd826143a9565b6040810191909152835260209283019201614978565b5f5f60408385031215614a24575f5ffd5b8235614a2f816143a9565b915060208301356001600160401b03811115614a49575f5ffd5b614a5585828601614935565b9150509250929050565b5f5f60408385031215614a70575f5ffd5b8235614a7b816143a9565b91506020830135614912816143a9565b5f8151808452602084019350602083015f5b8281101561458057614ad686835180516001600160401b03168252602080820151600f0b9083015260409081015163ffffffff16910152565b6060959095019460209190910190600101614a9d565b604081525f614afe6040830185614545565b82810360208401526139ed8185614a8b565b602080825282518282018190525f918401906040840190835b81811015614b505783516001600160a01b0316835260209384019390920191600101614b29565b509095945050505050565b5f5f5f60408486031215614b6d575f5ffd5b83356001600160401b03811115614b82575f5ffd5b614b8e8682870161459c565b9094509250506020840135614483816143a9565b602080825282518282018190525f918401906040840190835b81811015614b505783516001600160401b0316835260209384019390920191600101614bbb565b5f5f5f5f60608587031215614bf5575f5ffd5b8435614c00816143a9565b9350614c0e602086016143bd565b925060408501356001600160401b03811115614c28575f5ffd5b614c348782880161459c565b95989497509550505050565b5f5f60408385031215614c51575f5ffd5b8235614c5c816143a9565b91506144ec602084016143bd565b5f60208284031215614c7a575f5ffd5b813560ff81168114610949575f5ffd5b5f5f60608385031215614c9b575f5ffd5b614ca584846143d0565b91506040830135614912816143a9565b5f60608284031215614cc5575f5ffd5b50919050565b5f60208284031215614cdb575f5ffd5b81356001600160401b03811115614cf0575f5ffd5b610a0684828501614cb5565b5f5f5f60808486031215614d0e575f5ffd5b83356001600160401b03811115614d23575f5ffd5b614d2f8682870161464e565b93505061447385602086016143d0565b602081525f6109496020830184614a8b565b5f5f5f5f60608587031215614d64575f5ffd5b8435614d6f816143a9565b935060208501356001600160401b03811115614d89575f5ffd5b614d958782880161459c565b90945092506148409050604086016143bd565b5f5f60408385031215614db9575f5ffd5b8235614dc4816143a9565b915060208301356001600160401b03811115614dde575f5ffd5b8301601f81018513614dee575f5ffd5b8035614dfc61466b8261462c565b8082825260208201915060208360051b850101925087831115614e1d575f5ffd5b602084015b83811015614f425780356001600160401b03811115614e3f575f5ffd5b85016080818b03601f19011215614e54575f5ffd5b614e5c614351565b614e698b602084016143d0565b815260608201356001600160401b03811115614e83575f5ffd5b614e928c60208386010161464e565b60208301525060808201356001600160401b03811115614eb0575f5ffd5b6020818401019250508a601f830112614ec7575f5ffd5b8135614ed561466b8261462c565b8082825260208201915060208360051b86010192508d831115614ef6575f5ffd5b6020850194505b82851015614f2c5784356001600160401b0381168114614f1b575f5ffd5b825260209485019490910190614efd565b6040840152505084525060209283019201614e22565b50809450505050509250929050565b5f60208284031215614f61575f5ffd5b81356001600160401b03811115614f76575f5ffd5b8201601f81018413614f86575f5ffd5b8035614f9461466b8261462c565b8082825260208201915060208360061b850101925086831115614fb5575f5ffd5b6020840193505b828410156140f357614fce87856143d0565b8252602082019150604084019350614fbc565b5f5f5f60408486031215614ff3575f5ffd5b8335614ffe816143a9565b925060208401356001600160401b03811115615018575f5ffd5b8401601f81018613615028575f5ffd5b80356001600160401b0381111561503d575f5ffd5b86602082840101111561504e575f5ffd5b939660209190910195509293505050565b5f5f60408385031215615070575f5ffd5b823561507b816143a9565b915060208301356001600160401b03811115615095575f5ffd5b614a5585828601614cb5565b5f5f5f5f606085870312156150b4575f5ffd5b84356150bf816143a9565b935060208501356001600160401b038111156150d9575f5ffd5b6150e587828801614935565b93505060408501356001600160401b03811115614c28575f5ffd5b5f60208284031215615110575f5ffd5b610949826143bd565b5f5f8335601e1984360301811261512e575f5ffd5b8301803591506001600160401b03821115615147575f5ffd5b6020019150600581901b3603821315610d75575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215615182575f5ffd5b813561ffff81168114610949575f5ffd5b5f602082840312156151a3575f5ffd5b81518015158114610949575f5ffd5b60408101610a0a8284614527565b634e487b7160e01b5f52601160045260245ffd5b63ffffffff8181168382160190811115610a0a57610a0a6151c0565b8183526020830192505f815f5b848110156145805763ffffffff615213836143bd565b16865260209586019591909101906001016151fd565b6001600160a01b038581168252841660208201526060604082018190525f906140f390830184866151f0565b6001600160a01b038616815260c081016152726020830187614527565b6001600160a01b039490941660608201526001600160401b0392909216608083015263ffffffff1660a09091015292915050565b5f602082840312156152b6575f5ffd5b81516001600160401b038111156152cb575f5ffd5b8201601f810184136152db575f5ffd5b80516152e961466b8261462c565b8082825260208201915060208360051b85010192508683111561530a575f5ffd5b6020840193505b828410156140f3578351615324816143a9565b825260209384019390910190615311565b606081016153438285614527565b6001600160a01b039290921660409190910152919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b602081525f610b1960208301848661535b565b5f5f8335601e198436030181126153ab575f5ffd5b8301803591506001600160401b038211156153c4575f5ffd5b602001915036819003821315610d75575f5ffd5b6001600160a01b038781168252861660208201526080604082018190525f9061540490830186886151f0565b828103606084015261541781858761535b565b9998505050505050505050565b80516020808301519190811015614cc5575f1960209190910360031b1b16919050565b5f8235603e1983360301811261545b575f5ffd5b9190910192915050565b5f60018201615476576154766151c0565b5060010190565b81810381811115610a0a57610a0a6151c0565b6001600160401b038281168282160390811115610a0a57610a0a6151c0565b5f81600f0b60016001607f1b031981036154cb576154cb6151c0565b5f0392915050565b600f81810b9083900b0160016001607f1b03811360016001607f1b031982121715610a0a57610a0a6151c0565b6001600160a01b038716815260e0810161551d6020830188614527565b60608201959095526001600160a01b039390931660808401526001600160401b0391821660a08401521660c09091015292915050565b5f60208284031215615563575f5ffd5b5051919050565b6001600160a01b03881681525f60c08201615588602084018a614527565b60c060608401528690528660e083015f5b888110156155c95782356155ac816143a9565b6001600160a01b0316825260209283019290910190600101615599565b5083810360808501526155dc8188614734565b91505082810360a08401526155f281858761535b565b9a9950505050505050505050565b5f8161560e5761560e6151c0565b505f190190565b608081016156238286614527565b6001600160a01b0393909316604082015263ffffffff91909116606090910152919050565b600f82810b9082900b0360016001607f1b0319811260016001607f1b0382131715610a0a57610a0a6151c0565b5f60208284031215615685575f5ffd5b8151610949816143a9565b634e487b7160e01b5f52603160045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601260045260245ffd5b80820180821115610a0a57610a0a6151c056fea26469706673582212201718e832fb5ab045e193ee493fb8713607c22b0ff8d8e6ed0425a08e7eb7912d64736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a3400000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f7000000000000000000000000b8765ed72235d279c3fb53936e4606db0ef1280600000000000000000000000025e5f8b1e7adf44518d35d5b2271f114e081f0e500000000000000000000000000000000000000000000000000000000000189c0000000000000000000000000000000000000000000000000000000000001ec30
-----Decoded View---------------
Arg [0] : _allocationManagerView (address): 0x0D4e5723daAD06510CFd6864b8eB8a08CF0c4a34
Arg [1] : _delegation (address): 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A
Arg [2] : _eigenStrategy (address): 0xaCB55C530Acdb2849e6d4f36992Cd8c9D50ED8F7
Arg [3] : _pauserRegistry (address): 0xB8765ed72235d279c3Fb53936E4606db0Ef12806
Arg [4] : _permissionController (address): 0x25E5F8B1E7aDf44518d35D5B2271f114e081f0E5
Arg [5] : _DEALLOCATION_DELAY (uint32): 100800
Arg [6] : _ALLOCATION_CONFIGURATION_DELAY (uint32): 126000
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000d4e5723daad06510cfd6864b8eb8a08cf0c4a34
Arg [1] : 00000000000000000000000039053d51b77dc0d36036fc1fcc8cb819df8ef37a
Arg [2] : 000000000000000000000000acb55c530acdb2849e6d4f36992cd8c9d50ed8f7
Arg [3] : 000000000000000000000000b8765ed72235d279c3fb53936e4606db0ef12806
Arg [4] : 00000000000000000000000025e5f8b1e7adf44518d35d5b2271f114e081f0e5
Arg [5] : 00000000000000000000000000000000000000000000000000000000000189c0
Arg [6] : 000000000000000000000000000000000000000000000000000000000001ec30
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 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.