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