Skip to content

Commit ac12473

Browse files
committed
feat: slashers
1 parent 9d5c200 commit ac12473

File tree

3 files changed

+171
-4
lines changed

3 files changed

+171
-4
lines changed

src/slashers/Slasher.sol

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.12;
3+
4+
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
5+
import {SlasherBase} from "./SlasherBase.sol";
6+
7+
contract Slasher is SlasherBase {
8+
uint256 public nextRequestId;
9+
10+
event Slashed(
11+
uint256 indexed requestId,
12+
address indexed operator,
13+
uint32 indexed operatorSetId,
14+
uint256 wadToSlash,
15+
string description
16+
);
17+
18+
function initialize(address _serviceManager) public initializer {
19+
__SlasherBase_init(_serviceManager);
20+
}
21+
22+
function fulfillSlashingRequest(
23+
address operator,
24+
uint32 operatorSetId,
25+
IStrategy[] memory strategies,
26+
uint256 wadToSlash,
27+
string memory description
28+
) external virtual {
29+
uint256 requestId = nextRequestId++;
30+
_fulfillSlashingRequest(
31+
operator,
32+
operatorSetId,
33+
strategies,
34+
wadToSlash,
35+
description
36+
);
37+
emit Slashed(requestId, operator, operatorSetId, wadToSlash, description);
38+
}
39+
}

src/slashers/SimpleSlasher.sol renamed to src/slashers/SlasherBase.sol

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,33 @@ import {SlasherStorage} from "./SlasherStorage.sol";
77
import {IAllocationManagerTypes} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
88
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
99

10-
contract SimpleSlasher is Initializable, SlasherStorage {
11-
function initialize(address _serviceManager) public initializer {
10+
abstract contract SlasherBase is Initializable, SlasherStorage {
11+
enum SlashingStatus {
12+
Null,
13+
Requested,
14+
Completed,
15+
Cancelled
16+
}
17+
18+
event OperatorSlashed(
19+
address indexed operator,
20+
uint32 indexed operatorSetId,
21+
IStrategy[] strategies,
22+
uint256 wadToSlash,
23+
string description
24+
);
25+
26+
function __SlasherBase_init(address _serviceManager) internal onlyInitializing {
1227
serviceManager = _serviceManager;
1328
}
1429

15-
function slashOperator(
30+
function _fulfillSlashingRequest(
1631
address operator,
1732
uint32 operatorSetId,
1833
IStrategy[] memory strategies,
1934
uint256 wadToSlash,
2035
string memory description
21-
) external {
36+
) internal virtual {
2237

2338
IAllocationManagerTypes.SlashingParams memory params = IAllocationManagerTypes.SlashingParams({
2439
operator: operator,
@@ -28,6 +43,12 @@ contract SimpleSlasher is Initializable, SlasherStorage {
2843
description: description
2944
});
3045

46+
emit OperatorSlashed(operator, operatorSetId, strategies, wadToSlash, description);
47+
3148
IServiceManager(serviceManager).slashOperator(params);
3249
}
3350
}
51+
52+
53+
54+

src/slashers/VetoableSlasher.sol

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.12;
3+
4+
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
5+
import {SlasherBase} from "./SlasherBase.sol";
6+
7+
contract VetoableSlashing is SlasherBase {
8+
struct SlashingRequest {
9+
address operator;
10+
uint32 operatorSetId;
11+
IStrategy[] strategies;
12+
uint256 wadToSlash;
13+
string description;
14+
uint256 requestTimestamp;
15+
SlashingStatus status;
16+
}
17+
18+
uint256 public constant VETO_PERIOD = 3 days;
19+
address public vetoCommittee;
20+
uint256 public nextRequestId;
21+
mapping(uint256 => SlashingRequest) public slashingRequests;
22+
23+
event SlashingRequested(
24+
uint256 indexed requestId,
25+
address indexed operator,
26+
uint32 indexed operatorSetId,
27+
uint256 wadToSlash,
28+
string description
29+
);
30+
31+
event SlashingRequestCancelled(uint256 indexed requestId);
32+
33+
modifier onlyVetoCommittee() {
34+
require(msg.sender == vetoCommittee, "VetoableSlashing: caller is not the veto committee");
35+
_;
36+
}
37+
38+
function initialize(address _serviceManager, address _vetoCommittee) external virtual initializer {
39+
__SlasherBase_init(_serviceManager);
40+
vetoCommittee = _vetoCommittee;
41+
}
42+
43+
function queueSlashingRequest(
44+
address operator,
45+
uint32 operatorSetId,
46+
IStrategy[] memory strategies,
47+
uint256 wadToSlash,
48+
string memory description
49+
) external virtual {
50+
_queueSlashingRequest(operator, operatorSetId, strategies, wadToSlash, description);
51+
}
52+
53+
function cancelSlashingRequest(uint256 requestId) external virtual onlyVetoCommittee {
54+
require(
55+
block.timestamp < slashingRequests[requestId].requestTimestamp + VETO_PERIOD,
56+
"VetoableSlashing: veto period has passed"
57+
);
58+
require(slashingRequests[requestId].status == SlashingStatus.Requested, "VetoableSlashing: request is not in Requested status");
59+
60+
_cancelSlashingRequest(requestId);
61+
}
62+
63+
function fulfillSlashingRequest(uint256 requestId) external virtual {
64+
SlashingRequest storage request = slashingRequests[requestId];
65+
require(
66+
block.timestamp >= request.requestTimestamp + VETO_PERIOD,
67+
"VetoableSlashing: veto period has not passed"
68+
);
69+
require(request.status == SlashingStatus.Requested, "VetoableSlashing: request has been cancelled");
70+
71+
_fulfillSlashingRequest(
72+
request.operator,
73+
request.operatorSetId,
74+
request.strategies,
75+
request.wadToSlash,
76+
request.description
77+
);
78+
79+
delete slashingRequests[requestId];
80+
}
81+
82+
function _queueSlashingRequest(
83+
address operator,
84+
uint32 operatorSetId,
85+
IStrategy[] memory strategies,
86+
uint256 wadToSlash,
87+
string memory description
88+
) internal virtual {
89+
uint256 requestId = nextRequestId++;
90+
slashingRequests[requestId] = SlashingRequest({
91+
operator: operator,
92+
operatorSetId: operatorSetId,
93+
strategies: strategies,
94+
wadToSlash: wadToSlash,
95+
description: description,
96+
requestTimestamp: block.timestamp,
97+
status: SlashingStatus.Requested
98+
});
99+
100+
emit SlashingRequested(requestId, operator, operatorSetId, wadToSlash, description);
101+
}
102+
103+
function _cancelSlashingRequest(uint256 requestId) internal virtual {
104+
slashingRequests[requestId].status = SlashingStatus.Cancelled;
105+
emit SlashingRequestCancelled(requestId);
106+
}
107+
}

0 commit comments

Comments
 (0)