Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/slashing/VetoableSlasher.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Creates and queues a new slashing request that will be executable after the veto
#### `cancelSlashingRequest`
```solidity
function cancelSlashingRequest(
uint256 requestId
uint256 slashId
)
external
virtual
Expand All @@ -68,7 +68,7 @@ Allows the veto committee to cancel a pending slashing request within the veto w
#### `fulfillSlashingRequest`
```solidity
function fulfillSlashingRequest(
uint256 requestId
uint256 slashId
)
external
virtual
Expand Down
15 changes: 12 additions & 3 deletions src/interfaces/IInstantSlasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,18 @@ import {ISlasher} from "./ISlasher.sol";
/// @dev Extends base interfaces to provide access controlled slashing functionality
interface IInstantSlasher is ISlasher {
/// @notice Immediately executes a slashing request
/// @param _slashingParams Parameters defining the slashing request including operator and amount
/// @param params Parameters defining the slashing request including operator and amount
/// @dev Can only be called by the authorized slasher
/// @return slashId The ID of the slashing request
function fulfillSlashingRequest(
IAllocationManager.SlashingParams memory _slashingParams
) external;
IAllocationManager.SlashingParams memory params
) external returns (uint256 slashId);

/// @notice Immediately executes a slashing request and burns or redistributes shares
/// @param params Parameters defining the slashing request including operator and amount
/// @dev Can only be called by the authorized slasher
/// @return slashId The ID of the slashing request
function fulfillSlashingRequestAndBurnOrRedistribute(
IAllocationManager.SlashingParams memory params
) external returns (uint256 slashId);
}
5 changes: 1 addition & 4 deletions src/interfaces/ISlasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface ISlasherTypes {
interface ISlasherEvents is ISlasherTypes {
/// @notice Emitted when an operator is successfully slashed
event OperatorSlashed(
uint256 indexed slashingRequestId,
uint256 indexed slashId,
address indexed operator,
uint32 indexed operatorSetId,
uint256[] wadsToSlash,
Expand All @@ -33,7 +33,4 @@ interface ISlasherEvents is ISlasherTypes {
interface ISlasher is ISlasherErrors, ISlasherEvents {
/// @notice Returns the address authorized to create and fulfill slashing requests
function slasher() external view returns (address);

/// @notice Returns the next slashing request ID
function nextRequestId() external view returns (uint256);
}
19 changes: 13 additions & 6 deletions src/interfaces/IVetoableSlasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ interface IVetoableSlasherTypes {
interface IVetoableSlasherEvents {
/// @notice Emitted when a new slashing request is created
event SlashingRequested(
uint256 indexed requestId,
uint256 indexed slashId,
address indexed operator,
uint32 operatorSetId,
uint256[] wadsToSlash,
string description
);

/// @notice Emitted when a slashing request is cancelled by the veto committee
event SlashingRequestCancelled(uint256 indexed requestId);
event SlashingRequestCancelled(uint256 indexed slashId);
}

/// @title IVetoableSlasher
Expand All @@ -71,16 +71,23 @@ interface IVetoableSlasher is
) external;

/// @notice Cancels a pending slashing request
/// @param requestId The ID of the slashing request to cancel
/// @param slashId The ID of the slashing request to cancel
/// @dev Can only be called by the veto committee during the veto period
function cancelSlashingRequest(
uint256 requestId
uint256 slashId
) external;

/// @notice Executes a slashing request after the veto period has passed
/// @param requestId The ID of the slashing request to fulfill
/// @param slashId The ID of the slashing request to fulfill
/// @dev Can only be called by the authorized slasher after the veto period
function fulfillSlashingRequest(
uint256 requestId
uint256 slashId
) external;

/// @notice Executes a slashing request after the veto period has passed and burns or redistributes shares
/// @param slashId The ID of the slashing request to fulfill
/// @dev Can only be called by the authorized slasher after the veto period
function fulfillSlashingRequestAndBurnOrRedistribute(
uint256 slashId
) external;
}
20 changes: 12 additions & 8 deletions src/slashers/InstantSlasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.27;
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {IAllocationManager} from
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol";
import {SlasherBase} from "./base/SlasherBase.sol";
import {ISlashingRegistryCoordinator} from "../interfaces/ISlashingRegistryCoordinator.sol";
import {IInstantSlasher} from "../interfaces/IInstantSlasher.sol";
Expand All @@ -14,19 +15,22 @@ import {IInstantSlasher} from "../interfaces/IInstantSlasher.sol";
contract InstantSlasher is IInstantSlasher, SlasherBase {
constructor(
IAllocationManager _allocationManager,
IStrategyManager _strategyManager,
ISlashingRegistryCoordinator _slashingRegistryCoordinator,
address _slasher
) SlasherBase(_allocationManager, _slashingRegistryCoordinator, _slasher) {}
) SlasherBase(_allocationManager, _strategyManager, _slashingRegistryCoordinator, _slasher) {}

/// @inheritdoc IInstantSlasher
function fulfillSlashingRequest(
IAllocationManager.SlashingParams calldata _slashingParams
) external virtual override(IInstantSlasher) onlySlasher {
uint256 requestId = nextRequestId++;
_fulfillSlashingRequest(requestId, _slashingParams);
IAllocationManager.SlashingParams calldata params
) external virtual override(IInstantSlasher) onlySlasher returns (uint256 slashId) {
slashId = _fulfillSlashingRequest(params);
}

address[] memory operators = new address[](1);
operators[0] = _slashingParams.operator;
slashingRegistryCoordinator.updateOperators(operators);
/// @inheritdoc IInstantSlasher
function fulfillSlashingRequestAndBurnOrRedistribute(
IAllocationManager.SlashingParams calldata params
) external virtual override onlySlasher returns (uint256 slashId) {
slashId = _fulfillSlashingRequestAndBurnOrRedistribute(params);
}
}
68 changes: 41 additions & 27 deletions src/slashers/VetoableSlasher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
pragma solidity ^0.8.27;

import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {IAllocationManager} from
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {
IAllocationManager,
OperatorSet
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol";
import {SlasherBase} from "./base/SlasherBase.sol";
import {ISlashingRegistryCoordinator} from "../interfaces/ISlashingRegistryCoordinator.sol";
import {IVetoableSlasher, IVetoableSlasherTypes} from "../interfaces/IVetoableSlasher.sol";
Expand All @@ -29,11 +32,12 @@ contract VetoableSlasher is IVetoableSlasher, SlasherBase {

constructor(
IAllocationManager _allocationManager,
IStrategyManager _strategyManager,
ISlashingRegistryCoordinator _slashingRegistryCoordinator,
address _slasher,
address _vetoCommittee,
uint32 _vetoWindowBlocks
) SlasherBase(_allocationManager, _slashingRegistryCoordinator, _slasher) {
) SlasherBase(_allocationManager, _strategyManager, _slashingRegistryCoordinator, _slasher) {
vetoWindowBlocks = _vetoWindowBlocks;
vetoCommittee = _vetoCommittee;
}
Expand All @@ -47,72 +51,82 @@ contract VetoableSlasher is IVetoableSlasher, SlasherBase {

/// @inheritdoc IVetoableSlasher
function cancelSlashingRequest(
uint256 requestId
uint256 slashId
) external virtual override onlyVetoCommittee {
_cancelSlashingRequest(requestId);
_cancelSlashingRequest(slashId);
}

/// @inheritdoc IVetoableSlasher
function fulfillSlashingRequest(
uint256 requestId
uint256 slashId
) external virtual override onlySlasher {
_fulfillSlashingRequestAndMarkAsCompleted(requestId);
IVetoableSlasherTypes.VetoableSlashingRequest storage request = slashingRequests[slashId];
_markAsCompleted(request);
_fulfillSlashingRequest(request.params);
}

/// @inheritdoc IVetoableSlasher
function fulfillSlashingRequestAndBurnOrRedistribute(
uint256 slashId
) external virtual override onlySlasher {
IVetoableSlasherTypes.VetoableSlashingRequest storage request = slashingRequests[slashId];
_markAsCompleted(request);
_fulfillSlashingRequestAndBurnOrRedistribute(request.params);
}

/// @notice Internal function to create and store a new slashing request
/// @param params Parameters defining the slashing request
function _queueSlashingRequest(
IAllocationManager.SlashingParams memory params
) internal virtual {
uint256 requestId = nextRequestId++;
slashingRequests[requestId] = IVetoableSlasherTypes.VetoableSlashingRequest({
uint256 nextSlashId = allocationManager.getSlashCount(
OperatorSet({avs: slashingRegistryCoordinator.avs(), id: params.operatorSetId})
);
slashingRequests[nextSlashId] = IVetoableSlasherTypes.VetoableSlashingRequest({
params: params,
requestBlock: block.number,
status: IVetoableSlasherTypes.SlashingStatus.Requested
});

emit SlashingRequested(
requestId, params.operator, params.operatorSetId, params.wadsToSlash, params.description
nextSlashId,
params.operator,
params.operatorSetId,
params.wadsToSlash,
params.description
);
}

/// @notice Internal function to mark a slashing request as cancelled
/// @param requestId The ID of the slashing request to cancel
/// @param slashId The ID of the slashing request to cancel
function _cancelSlashingRequest(
uint256 requestId
uint256 slashId
) internal virtual {
require(
block.number < slashingRequests[requestId].requestBlock + vetoWindowBlocks,
block.number < slashingRequests[slashId].requestBlock + vetoWindowBlocks,
VetoPeriodPassed()
);
require(
slashingRequests[requestId].status == IVetoableSlasherTypes.SlashingStatus.Requested,
slashingRequests[slashId].status == IVetoableSlasherTypes.SlashingStatus.Requested,
SlashingRequestNotRequested()
);

slashingRequests[requestId].status = IVetoableSlasherTypes.SlashingStatus.Cancelled;
emit SlashingRequestCancelled(requestId);
slashingRequests[slashId].status = IVetoableSlasherTypes.SlashingStatus.Cancelled;
emit SlashingRequestCancelled(slashId);
}

/// @notice Internal function to fulfill a slashing request and mark it as completed
/// @param requestId The ID of the slashing request to fulfill
function _fulfillSlashingRequestAndMarkAsCompleted(
uint256 requestId
/// @notice Internal function to mark a slashing request as completed
/// @param request The request to mark as completed
function _markAsCompleted(
IVetoableSlasherTypes.VetoableSlashingRequest storage request
) internal virtual {
IVetoableSlasherTypes.VetoableSlashingRequest storage request = slashingRequests[requestId];
require(block.number >= request.requestBlock + vetoWindowBlocks, VetoPeriodNotPassed());
require(
request.status == IVetoableSlasherTypes.SlashingStatus.Requested,
SlashingRequestIsCancelled()
);

request.status = IVetoableSlasherTypes.SlashingStatus.Completed;

_fulfillSlashingRequest(requestId, request.params);

address[] memory operators = new address[](1);
operators[0] = request.params.operator;
slashingRegistryCoordinator.updateOperators(operators);
}

/// @notice Internal function to verify if an account is the veto committee
Expand Down
45 changes: 33 additions & 12 deletions src/slashers/base/SlasherBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ pragma solidity ^0.8.27;

import {SlasherStorage, ISlashingRegistryCoordinator} from "./SlasherStorage.sol";
import {
OperatorSet,
IAllocationManagerTypes,
IAllocationManager
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol";
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";

/// @title SlasherBase
Expand All @@ -24,26 +26,45 @@ abstract contract SlasherBase is SlasherStorage {
/// @param _slasher The address of the slasher
constructor(
IAllocationManager _allocationManager,
IStrategyManager _strategyManager,
ISlashingRegistryCoordinator _registryCoordinator,
address _slasher
) SlasherStorage(_allocationManager, _registryCoordinator, _slasher) {}
) SlasherStorage(_allocationManager, _strategyManager, _registryCoordinator, _slasher) {}

/// @notice Internal function to execute a slashing request
/// @param _requestId The ID of the slashing request to fulfill
/// @param _params Parameters defining the slashing request including operator, strategies, and amounts
/// @param params Parameters defining the slashing request including operator, strategies, and amounts
/// @dev Calls AllocationManager.slashOperator to perform the actual slashing
function _fulfillSlashingRequest(
uint256 _requestId,
IAllocationManager.SlashingParams memory _params
) internal virtual {
allocationManager.slashOperator({avs: slashingRegistryCoordinator.avs(), params: _params});
IAllocationManager.SlashingParams memory params
) internal virtual returns (uint256 slashId) {
(slashId,) = allocationManager.slashOperator({
avs: slashingRegistryCoordinator.avs(),
params: params
});
emit OperatorSlashed(
_requestId,
_params.operator,
_params.operatorSetId,
_params.wadsToSlash,
_params.description
slashId, params.operator, params.operatorSetId, params.wadsToSlash, params.description
);

// Update operator stake weights
address[] memory operators = new address[](1);
operators[0] = params.operator;
slashingRegistryCoordinator.updateOperators(operators);
}

/// @notice Internal function to optionally fulfill burn or redistribution instead of waiting for cron job
function _fulfillBurnOrRedistribution(uint32 operatorSetId, uint256 slashId) internal virtual {
strategyManager.clearBurnOrRedistributableShares({
operatorSet: OperatorSet({avs: slashingRegistryCoordinator.avs(), id: operatorSetId}),
slashId: slashId
});
}

/// @notice Internal function to fulfill a slashing request and burn or redistribute shares
function _fulfillSlashingRequestAndBurnOrRedistribute(
IAllocationManager.SlashingParams memory params
) internal virtual returns (uint256 slashId) {
slashId = _fulfillSlashingRequest(params);
_fulfillBurnOrRedistribution(params.operatorSetId, slashId);
}

/// @notice Internal function to verify if an account is the authorized slasher
Expand Down
13 changes: 10 additions & 3 deletions src/slashers/base/SlasherStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.27;

import {IAllocationManager} from
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IStrategyManager} from "eigenlayer-contracts/src/contracts/interfaces/IStrategyManager.sol";
import {ISlashingRegistryCoordinator} from "../../interfaces/ISlashingRegistryCoordinator.sol";
import {ISlasher} from "../../interfaces/ISlasher.sol";

Expand All @@ -16,21 +17,27 @@ abstract contract SlasherStorage is ISlasher {
*
*/

/// @notice the AllocationManager that tracks OperatorSets and Slashing in EigenLayer
/// @notice The `AllocationManager` tracks operator sets, operator set allocations, and slashing in EigenLayer.
IAllocationManager public immutable allocationManager;
/// @notice the SlashingRegistryCoordinator for this AVS
/// @notice The `StrategyManager` handles strategy inflows/outflows.
IStrategyManager public immutable strategyManager;
/// @notice The `SlashingRegistryCoordinator` for this AVS.
ISlashingRegistryCoordinator public immutable slashingRegistryCoordinator;

/// @notice the address of the slasher
address public immutable slasher;

uint256 public nextRequestId;
/// @dev DEPRECATED -- `AllocationManager` now tracks monotonically increasing `slashId`.
uint256 private __deprecated_nextRequestId;

constructor(
IAllocationManager _allocationManager,
IStrategyManager _strategyManager,
ISlashingRegistryCoordinator _slashingRegistryCoordinator,
address _slasher
) {
allocationManager = _allocationManager;
strategyManager = _strategyManager;
slashingRegistryCoordinator = _slashingRegistryCoordinator;
slasher = _slasher;
}
Expand Down
Loading
Loading