Skip to content

Commit 9e4afb8

Browse files
stevennevins0xClandestineneutiyooypatil12
authored
test: unit test slashers (#380)
* fix: remappings * fix: remove unused OnlySlasher error (#376) * refactor: VetoableSlasher (#377) * chore: use inheritdoc for SlashingRegCoord (#378) * test: slasher contracts and add some natspec * chore: unneeded comment * chore: redundant comments * test: more extensive setup for slashOperator * test: integrate core deployment lib * test: unit test slashing * test: vetoable slasher * chore: forge fmt * chore: format and solve interfaces with inheritdoc --------- Co-authored-by: clandestine.eth <[email protected]> Co-authored-by: Noel <[email protected]> Co-authored-by: Yash Patil <[email protected]>
1 parent 9994210 commit 9e4afb8

12 files changed

+1203
-102
lines changed

src/RegistryCoordinator.sol

-10
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,4 @@ contract RegistryCoordinator is RegistryCoordinatorStorage {
237237
) external view returns (bool) {
238238
return _isM2Quorum(quorumNumber);
239239
}
240-
241-
/**
242-
* @notice Returns the message hash that an operator must sign to register their BLS public key.
243-
* @param operator is the address of the operator registering their BLS public key
244-
*/
245-
function calculatePubkeyRegistrationMessageHash(
246-
address operator
247-
) public view returns (bytes32) {
248-
return _hashTypedDataV4(keccak256(abi.encode(PUBKEY_REGISTRATION_TYPEHASH, operator)));
249-
}
250240
}

src/SlashingRegistryCoordinator.sol

+10
Original file line numberDiff line numberDiff line change
@@ -1066,4 +1066,14 @@ contract SlashingRegistryCoordinator is
10661066
_hashTypedDataV4(keccak256(abi.encode(PUBKEY_REGISTRATION_TYPEHASH, operator)))
10671067
);
10681068
}
1069+
1070+
/**
1071+
* @notice Returns the message hash that an operator must sign to register their BLS public key.
1072+
* @param operator is the address of the operator registering their BLS public key
1073+
*/
1074+
function calculatePubkeyRegistrationMessageHash(
1075+
address operator
1076+
) public view returns (bytes32) {
1077+
return _hashTypedDataV4(keccak256(abi.encode(PUBKEY_REGISTRATION_TYPEHASH, operator)));
1078+
}
10691079
}

src/interfaces/IInstantSlasher.sol

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {IAllocationManager} from
5+
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
6+
import {ISlasher} from "./ISlasher.sol";
7+
8+
/// @title IInstantSlasher
9+
/// @notice A slashing contract that immediately executes slashing requests without any delay or veto period
10+
/// @dev Extends base interfaces to provide access controlled slashing functionality
11+
interface IInstantSlasher is ISlasher {
12+
/// @notice Initializes the contract with a slasher address
13+
/// @param _slasher Address authorized to create and fulfill slashing requests
14+
function initialize(
15+
address _slasher
16+
) external;
17+
18+
/// @notice Immediately executes a slashing request
19+
/// @param _slashingParams Parameters defining the slashing request including operator and amount
20+
/// @dev Can only be called by the authorized slasher
21+
function fulfillSlashingRequest(
22+
IAllocationManager.SlashingParams memory _slashingParams
23+
) external;
24+
}

src/interfaces/ISlasher.sol

+9-65
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,24 @@
11
// SPDX-License-Identifier: BUSL-1.1
22
pragma solidity ^0.8.27;
33

4-
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
54
import {IAllocationManager} from
65
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
76

87
interface ISlasherErrors {
9-
/// @notice Thrown when a caller without veto committee privileges attempts a restricted operation.
10-
error OnlyVetoCommittee();
11-
/// @notice Thrown when a caller without slasher privileges attempts a restricted operation.
8+
/// @notice Thrown when a caller without slasher privileges attempts a restricted operation
129
error OnlySlasher();
13-
/// @notice Thrown when attempting to veto a slashing request after the veto period has expired.
14-
error VetoPeriodPassed();
15-
/// @notice Thrown when attempting to execute a slashing request before the veto period has ended.
16-
error VetoPeriodNotPassed();
17-
/// @notice Thrown when attempting to interact with a slashing request that has been cancelled.
18-
error SlashingRequestIsCancelled();
19-
/// @notice Thrown when attempting to modify a slashing request that does not exist.
20-
error SlashingRequestNotRequested();
2110
}
2211

2312
interface ISlasherTypes {
24-
/**
25-
* @notice Represents the current status of a slashing request.
26-
* @dev The status of a slashing request can be one of the following:
27-
* - Null: Default state, no request exists.
28-
* - Requested: Slashing has been requested but not yet executed.
29-
* - Completed: Slashing has been successfully executed.
30-
* - Cancelled: Slashing request was cancelled by veto committee.
31-
*/
32-
enum SlashingStatus {
33-
Null,
34-
Requested,
35-
Completed,
36-
Cancelled
37-
}
38-
39-
/**
40-
* @notice Contains all information related to a slashing request.
41-
* @param params The slashing parameters from the allocation manager.
42-
* @param requestTimestamp The timestamp when the slashing request was created.
43-
* @param status The current status of the slashing request.
44-
*/
13+
/// @notice Structure containing details about a slashing request
4514
struct SlashingRequest {
4615
IAllocationManager.SlashingParams params;
4716
uint256 requestTimestamp;
48-
SlashingStatus status;
4917
}
5018
}
5119

5220
interface ISlasherEvents is ISlasherTypes {
53-
/**
54-
* @notice Emitted when a new slashing request is created.
55-
* @param requestId The unique identifier for the slashing request (indexed).
56-
* @param operator The address of the operator to be slashed (indexed).
57-
* @param operatorSetId The ID of the operator set involved (indexed).
58-
* @param wadsToSlash The amounts to slash from each strategy.
59-
* @param description A human-readable description of the slashing reason.
60-
*/
61-
event SlashingRequested(
62-
uint256 indexed requestId,
63-
address indexed operator,
64-
uint32 indexed operatorSetId,
65-
uint256[] wadsToSlash,
66-
string description
67-
);
68-
69-
/**
70-
* @notice Emitted when a slashing request is cancelled by the veto committee.
71-
* @param requestId The unique identifier of the cancelled request (indexed).
72-
*/
73-
event SlashingRequestCancelled(uint256 indexed requestId);
74-
75-
/**
76-
* @notice Emitted when an operator is successfully slashed.
77-
* @param slashingRequestId The ID of the executed slashing request (indexed).
78-
* @param operator The address of the slashed operator (indexed).
79-
* @param operatorSetId The ID of the operator set involved (indexed).
80-
* @param wadsToSlash The amounts slashed from each strategy.
81-
* @param description A human-readable description of why the operator was slashed.
82-
*/
21+
/// @notice Emitted when an operator is successfully slashed
8322
event OperatorSlashed(
8423
uint256 indexed slashingRequestId,
8524
address indexed operator,
@@ -89,4 +28,9 @@ interface ISlasherEvents is ISlasherTypes {
8928
);
9029
}
9130

92-
interface ISlasher is ISlasherErrors, ISlasherEvents {}
31+
/// @title ISlasher
32+
/// @notice Base interface containing shared functionality for all slasher implementations
33+
interface ISlasher is ISlasherErrors, ISlasherEvents {
34+
/// @notice Returns the address authorized to create and fulfill slashing requests
35+
function slasher() external view returns (address);
36+
}

src/interfaces/ISlashingRegistryCoordinator.sol

+8
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,14 @@ interface ISlashingRegistryCoordinator is
452452

453453
/// VIEW
454454

455+
/**
456+
* @notice Returns the hash of the message that operators must sign with their BLS key to register
457+
* @param operator The operator's Ethereum address
458+
*/
459+
function calculatePubkeyRegistrationMessageHash(
460+
address operator
461+
) external view returns (bytes32);
462+
455463
/**
456464
* @notice Returns the operator set parameters for a given quorum.
457465
* @param quorumNumber The identifier of the quorum to query.

src/interfaces/IVetoableSlasher.sol

+92
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {IAllocationManager} from
5+
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
6+
import {ISlasher} from "./ISlasher.sol";
7+
8+
interface IVetoableSlasherErrors {
9+
/// @notice Thrown when a caller without veto committee privileges attempts a restricted operation
10+
error OnlyVetoCommittee();
11+
/// @notice Thrown when attempting to veto a slashing request after the veto period has expired
12+
error VetoPeriodPassed();
13+
/// @notice Thrown when attempting to execute a slashing request before the veto period has ended
14+
error VetoPeriodNotPassed();
15+
/// @notice Thrown when attempting to interact with a slashing request that has been cancelled
16+
error SlashingRequestIsCancelled();
17+
/// @notice Thrown when attempting to modify a slashing request that does not exist
18+
error SlashingRequestNotRequested();
19+
}
20+
21+
interface IVetoableSlasherTypes {
22+
/// @notice Represents the status of a slashing request
23+
enum SlashingStatus {
24+
Requested,
25+
Cancelled,
26+
Completed
27+
}
28+
29+
/// @notice Structure containing details about a vetoable slashing request
30+
struct VetoableSlashingRequest {
31+
IAllocationManager.SlashingParams params;
32+
uint256 requestTimestamp;
33+
SlashingStatus status;
34+
}
35+
}
36+
37+
interface IVetoableSlasherEvents {
38+
/// @notice Emitted when a new slashing request is created
39+
event SlashingRequested(
40+
uint256 indexed requestId,
41+
address indexed operator,
42+
uint32 operatorSetId,
43+
uint256[] wadsToSlash,
44+
string description
45+
);
46+
47+
/// @notice Emitted when a slashing request is cancelled by the veto committee
48+
event SlashingRequestCancelled(uint256 indexed requestId);
49+
}
50+
51+
/// @title IVetoableSlasher
52+
/// @notice A slashing contract that implements a veto mechanism allowing a designated committee to cancel slashing requests
53+
/// @dev Extends base interfaces and adds a veto period during which slashing requests can be cancelled
54+
interface IVetoableSlasher is
55+
ISlasher,
56+
IVetoableSlasherErrors,
57+
IVetoableSlasherTypes,
58+
IVetoableSlasherEvents
59+
{
60+
/// @notice Duration of the veto period during which the veto committee can cancel slashing requests
61+
/// @dev Set to 3 days (259,200 seconds)
62+
function VETO_PERIOD() external view returns (uint256);
63+
64+
/// @notice Address of the committee that has veto power over slashing requests
65+
function vetoCommittee() external view returns (address);
66+
67+
/// @notice Initializes the contract with a veto committee and slasher address
68+
/// @param _vetoCommittee Address of the committee that can veto slashing requests
69+
/// @param _slasher Address authorized to create and fulfill slashing requests
70+
function initialize(address _vetoCommittee, address _slasher) external;
71+
72+
/// @notice Queues a new slashing request
73+
/// @param params Parameters defining the slashing request including operator and amount
74+
/// @dev Can only be called by the authorized slasher
75+
function queueSlashingRequest(
76+
IAllocationManager.SlashingParams calldata params
77+
) external;
78+
79+
/// @notice Cancels a pending slashing request
80+
/// @param requestId The ID of the slashing request to cancel
81+
/// @dev Can only be called by the veto committee during the veto period
82+
function cancelSlashingRequest(
83+
uint256 requestId
84+
) external;
85+
86+
/// @notice Executes a slashing request after the veto period has passed
87+
/// @param requestId The ID of the slashing request to fulfill
88+
/// @dev Can only be called by the authorized slasher after the veto period
89+
function fulfillSlashingRequest(
90+
uint256 requestId
91+
) external;
92+
}

src/slashers/InstantSlasher.sol

+11-5
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,31 @@ pragma solidity ^0.8.27;
44
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
55
import {IAllocationManager} from
66
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
7-
import {ISlashingRegistryCoordinator} from "../interfaces/ISlashingRegistryCoordinator.sol";
87
import {SlasherBase} from "./base/SlasherBase.sol";
8+
import {ISlashingRegistryCoordinator} from "../interfaces/ISlashingRegistryCoordinator.sol";
9+
import {IInstantSlasher} from "../interfaces/IInstantSlasher.sol";
910

10-
contract InstantSlasher is SlasherBase {
11+
/// @title InstantSlasher
12+
/// @notice A slashing contract that immediately executes slashing requests without any delay or veto period
13+
/// @dev Extends SlasherBase to provide access controlled slashing functionality
14+
contract InstantSlasher is IInstantSlasher, SlasherBase {
1115
constructor(
1216
IAllocationManager _allocationManager,
1317
ISlashingRegistryCoordinator _slashingRegistryCoordinator,
1418
address _slasher
1519
) SlasherBase(_allocationManager, _slashingRegistryCoordinator) {}
1620

21+
/// @inheritdoc IInstantSlasher
1722
function initialize(
1823
address _slasher
19-
) external initializer {
24+
) external override initializer {
2025
__SlasherBase_init(_slasher);
2126
}
2227

28+
/// @inheritdoc IInstantSlasher
2329
function fulfillSlashingRequest(
24-
IAllocationManager.SlashingParams memory _slashingParams
25-
) external virtual onlySlasher {
30+
IAllocationManager.SlashingParams calldata _slashingParams
31+
) external virtual override(IInstantSlasher) onlySlasher {
2632
uint256 requestId = nextRequestId++;
2733
_fulfillSlashingRequest(requestId, _slashingParams);
2834
}

0 commit comments

Comments
 (0)