misc: remove slasher middleware solidity contracts (#366)

## Summary

This PR remove the middlewares contracts from eigen layer. Instead we
are planning to use the eigne layer contract directly. It also removes
the tests related to the middleware slasher code and the mock contract
used in it.

## Motivation

When slashing an operator in the Dathaven we are going through the
substrate slashing pallet already implemented. It already allow to
configure a slashing window and/or to cancel a slashing. In the future
it will also be compatible with a government pallet. This part of code
is therefore redundant. For the same reason we remove the tests because
we are not using the slashing middleware contracts.

## What changed

* Remove the slasher middleware files
* Remove the tests related to the middleware slasher file
This commit is contained in:
undercover-cactus 2025-12-29 14:55:21 +01:00 committed by GitHub
parent 41788d56bb
commit 863250d555
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
30 changed files with 11 additions and 1763 deletions

View file

@ -101,9 +101,8 @@ datahaven/
### Key Components
1. **DataHavenServiceManager**: Core AVS contract managing operator lifecycle
2. **RewardsRegistry**: Tracks validator performance and reward distribution
3. **VetoableSlasher**: Implements slashing with veto period for dispute resolution
4. **External Validators Pallet**: Manages validator set on Substrate side
5. **Native Transfer Pallet**: Handles cross-chain token transfers via Snowbridge
3. **External Validators Pallet**: Manages validator set on Substrate side
4. **Native Transfer Pallet**: Handles cross-chain token transfers via Snowbridge
### Testing Strategy
- **Unit Tests**: Component-specific (`cargo test`, `forge test`)

View file

@ -23,7 +23,6 @@ DataHaven bridges two major blockchain ecosystems:
│ │ EigenLayer AVS Contracts │ │
│ │ • DataHavenServiceManager (operator lifecycle) │ │
│ │ • RewardsRegistry (performance tracking) │ │
│ │ • VetoableSlasher (misbehavior penalties) │ │
│ └────────────────────────────────────────────────────────┘ │
│ ↕ │
│ Snowbridge Protocol │
@ -148,7 +147,7 @@ Full Ethereum Virtual Machine support via Frontier pallets:
Validator security anchored to Ethereum:
- Operators register via `DataHavenServiceManager` contract
- Economic security through ETH restaking
- Slashing protection with veto period via `VetoableSlasher`
- Slashing protection with veto period
- Performance-based rewards through `RewardsRegistry`
### Cross-chain Communication

View file

@ -8,7 +8,7 @@ Implements the Actively Validated Service (AVS) logic for DataHaven, secured by
contracts/
├── src/
│ ├── DataHavenServiceManager.sol # Core AVS service manager
│ ├── middleware/ # RewardsRegistry, VetoableSlasher, Snowbridge helpers
│ ├── middleware/ # RewardsRegistry, Snowbridge helpers
│ ├── interfaces/ # Contract interfaces
│ └── libraries/ # Utility libraries
├── script/ # Deployment & setup scripts
@ -20,7 +20,6 @@ contracts/
- **DataHavenServiceManager** (`src/DataHavenServiceManager.sol`): Core contract for operator lifecycle; inherits `ServiceManagerBase`.
- **RewardsRegistry** (`src/middleware/RewardsRegistry.sol`): Tracks validator performance and distributes rewards via Snowbridge.
- **VetoableSlasher** (`src/middleware/VetoableSlasher.sol`): Handles slashing requests with a dispute resolution veto window.
## Development
@ -43,7 +42,7 @@ Deployment parameters (EigenLayer addresses, initial validators, owners) are def
## Deployment
Two deployment paths exist: **Local** (Anvil) and **Testnet** (Hoodi). Both install the **DataHaven AVS contracts** (ServiceManager, RewardsRegistry, VetoableSlasher) and **Snowbridge** (BeefyClient, Gateway, Agent). They differ in EigenLayer setup:
Two deployment paths exist: **Local** (Anvil) and **Testnet** (Hoodi). Both install the **DataHaven AVS contracts** (ServiceManager, RewardsRegistry) and **Snowbridge** (BeefyClient, Gateway, Agent). They differ in EigenLayer setup:
### Local (Anvil)
**`DeployLocal.s.sol`** bootstraps a full EigenLayer core deployment (DelegationManager, StrategyManager, AVSDirectory, etc.) alongside DataHaven AVS and Snowbridge.
@ -66,6 +65,6 @@ Supported networks: `hoodi` (no mainnet config yet). Artifacts → `contracts/de
1. **Registration**: Validators register with EigenLayer via `DataHavenServiceManager`.
2. **Performance Tracking**: DataHaven computes reward points and sends a Merkle root to `RewardsRegistry` on Ethereum via Snowbridge.
3. **Rewards Claims**: Validators claim rewards on Ethereum from `RewardsRegistry` using Merkle proofs.
4. **Slashing**: Misbehavior triggers `VetoableSlasher` (subject to veto period).
4. **Slashing**: Misbehavior triggers slashing (subject to veto period).
See `test/README.md` for full network integration tests.

View file

@ -1,5 +1 @@
{
"RewardsAgent": "0xac06641381166cf085281c45292147f833C622d7",
"RewardsAgentOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000",
"updateRewardsMerkleRootSelector": "0xdc3d04ec"
}
{"RewardsAgent": "0xac06641381166cf085281c45292147f833C622d7","RewardsAgentOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000","updateRewardsMerkleRootSelector": "0xdc3d04ec"}

View file

@ -1,28 +1 @@
{
"network": "anvil",
"BeefyClient": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf",
"AgentExecutor": "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF",
"Gateway": "0x9d4454B023096f34B160D6B654540c56A1F81688",
"ServiceManager": "0x809d550fca64d94Bd9F66E60752A544199cfAC3D",
"ServiceManagerImplementation": "0x36C02dA8a0983159322a80FFE9F24b1acfF8B570",
"VetoableSlasher": "0x4c5859f0F772848b2D91F1D83E2Fe57935348029",
"RewardsRegistry": "0x1291Be112d480055DaFd8a610b7d1e203891C274",
"RewardsAgent": "0xac06641381166cf085281c45292147f833C622d7",
"DelegationManager": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"StrategyManager": "0x9A676e781A523b5d0C0e43731313A708CB607508",
"AVSDirectory": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"EigenPodManager": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"EigenPodBeacon": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1",
"RewardsCoordinator": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE",
"AllocationManager": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed",
"PermissionController": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
"ETHPOSDeposit": "0xC7f2Cf4845C6db0e1a1e91ED41Bcd0FcC1b0E141",
"BaseStrategyImplementation": "0xf5059a5D33d5853360D16C683c16e67980206f36",
"DeployedStrategies": [
{
"address": "0x998abeb3E57409262aE5b751f60747921B33613E",
"underlyingToken": "0x95401dc811bb5740090279Ba06cfA8fcF6113778",
"tokenCreator": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
}
]
}
{"network": "anvil","BeefyClient": "0x99bbA657f2BbC93c02D617f8bA121cB8Fc104Acf","AgentExecutor": "0x0E801D84Fa97b50751Dbf25036d067dCf18858bF","Gateway": "0x9d4454B023096f34B160D6B654540c56A1F81688","ServiceManager": "0x809d550fca64d94Bd9F66E60752A544199cfAC3D","ServiceManagerImplementation": "0x36C02dA8a0983159322a80FFE9F24b1acfF8B570","RewardsRegistry": "0x4c5859f0F772848b2D91F1D83E2Fe57935348029","RewardsAgent": "0xac06641381166cf085281c45292147f833C622d7","DelegationManager": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82","StrategyManager": "0x9A676e781A523b5d0C0e43731313A708CB607508","AVSDirectory": "0x0B306BF915C4d645ff596e518fAf3F9669b97016","EigenPodManager": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1","EigenPodBeacon": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1","RewardsCoordinator": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE","AllocationManager": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed","PermissionController": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c","ETHPOSDeposit": "0xC7f2Cf4845C6db0e1a1e91ED41Bcd0FcC1b0E141","BaseStrategyImplementation": "0xf5059a5D33d5853360D16C683c16e67980206f36","DeployedStrategies": [{"address": "0x998abeb3E57409262aE5b751f60747921B33613E","underlyingToken": "0x95401dc811bb5740090279Ba06cfA8fcF6113778","tokenCreator": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"}]}

View file

@ -40,7 +40,6 @@ import {IETHPOSDeposit} from "eigenlayer-contracts/src/contracts/interfaces/IETH
// DataHaven imports
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
import {MerkleUtils} from "../../src/libraries/MerkleUtils.sol";
import {VetoableSlasher} from "../../src/middleware/VetoableSlasher.sol";
import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol";
import {IRewardsRegistry} from "../../src/interfaces/IRewardsRegistry.sol";
import {ValidatorsUtils} from "../../script/utils/ValidatorsUtils.sol";
@ -134,7 +133,6 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
(
DataHavenServiceManager serviceManager,
DataHavenServiceManager serviceManagerImplementation,
VetoableSlasher vetoableSlasher,
RewardsRegistry rewardsRegistry,
bytes4 updateRewardsMerkleRootSelector
) = _deployDataHavenContracts(avsConfig, proxyAdmin, gateway);
@ -162,7 +160,6 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
gateway,
serviceManager,
serviceManagerImplementation,
vetoableSlasher,
rewardsRegistry,
rewardsAgentAddress
);
@ -256,16 +253,7 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
AVSConfig memory avsConfig,
ProxyAdmin proxyAdmin,
IGatewayV2 gateway
)
internal
returns (
DataHavenServiceManager,
DataHavenServiceManager,
VetoableSlasher,
RewardsRegistry,
bytes4
)
{
) internal returns (DataHavenServiceManager, DataHavenServiceManager, RewardsRegistry, bytes4) {
Logging.logHeader("DATAHAVEN CUSTOM CONTRACTS DEPLOYMENT");
// Deploy the Service Manager
@ -290,16 +278,6 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
_createServiceManagerProxy(serviceManagerImplementation, proxyAdmin, initParams);
Logging.logContractDeployed("ServiceManager Proxy", address(serviceManager));
// Deploy VetoableSlasher
vm.broadcast(_deployerPrivateKey);
VetoableSlasher vetoableSlasher = new VetoableSlasher(
allocationManager,
serviceManager,
avsConfig.vetoCommitteeMember,
avsConfig.vetoWindowBlocks
);
Logging.logContractDeployed("VetoableSlasher", address(vetoableSlasher));
// Deploy RewardsRegistry
vm.broadcast(_deployerPrivateKey);
RewardsRegistry rewardsRegistry = new RewardsRegistry(
@ -320,15 +298,6 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
Logging.logInfo("TX EXECUTION DISABLED: call updateAVSMetadataURI via multisig");
}
// Set the slasher in the ServiceManager
if (_txExecutionEnabled) {
vm.broadcast(_avsOwnerPrivateKey);
serviceManager.setSlasher(vetoableSlasher);
Logging.logStep("Slasher set in ServiceManager");
} else {
Logging.logInfo("TX EXECUTION DISABLED: call setSlasher via multisig");
}
// Set the RewardsRegistry in the ServiceManager
uint32 validatorsSetId = serviceManager.VALIDATORS_SET_ID();
if (_txExecutionEnabled) {
@ -342,7 +311,6 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
return (
serviceManager,
serviceManagerImplementation,
vetoableSlasher,
rewardsRegistry,
updateRewardsMerkleRootSelector
);
@ -366,7 +334,6 @@ abstract contract DeployBase is Script, DeployParams, Accounts {
IGatewayV2 gateway,
DataHavenServiceManager serviceManager,
DataHavenServiceManager serviceManagerImplementation,
VetoableSlasher vetoableSlasher,
RewardsRegistry rewardsRegistry,
address rewardsAgent
) internal virtual;

View file

@ -25,7 +25,6 @@ import {ud60x18} from "snowbridge/lib/prb-math/src/UD60x18.sol";
import {BeefyClient} from "snowbridge/src/BeefyClient.sol";
// DataHaven imports for function signatures
import {VetoableSlasher} from "../../src/middleware/VetoableSlasher.sol";
import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol";
// Additional imports specific to local deployment
@ -71,7 +70,6 @@ import {
import {EmptyContract} from "eigenlayer-contracts/src/test/mocks/EmptyContract.sol";
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
import {VetoableSlasher} from "../../src/middleware/VetoableSlasher.sol";
import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol";
import {IRewardsRegistry} from "../../src/interfaces/IRewardsRegistry.sol";
@ -209,7 +207,6 @@ contract DeployLocal is DeployBase {
IGatewayV2 gateway,
DataHavenServiceManager serviceManager,
DataHavenServiceManager serviceManagerImplementation,
VetoableSlasher vetoableSlasher,
RewardsRegistry rewardsRegistry,
address rewardsAgent
) internal override {
@ -223,7 +220,6 @@ contract DeployLocal is DeployBase {
Logging.logSection("DataHaven Contracts");
Logging.logContractDeployed("ServiceManager", address(serviceManager));
Logging.logContractDeployed("VetoableSlasher", address(vetoableSlasher));
Logging.logContractDeployed("RewardsRegistry", address(rewardsRegistry));
Logging.logSection("EigenLayer Core Contracts");
@ -274,9 +270,6 @@ contract DeployLocal is DeployBase {
vm.toString(address(serviceManagerImplementation)),
'",'
);
json = string.concat(
json, '"VetoableSlasher": "', vm.toString(address(vetoableSlasher)), '",'
);
json = string.concat(
json, '"RewardsRegistry": "', vm.toString(address(rewardsRegistry)), '",'
);

View file

@ -13,7 +13,6 @@ import {IGatewayV2} from "snowbridge/src/v2/IGateway.sol";
import {Logging} from "../utils/Logging.sol";
// DataHaven imports for function signatures
import {VetoableSlasher} from "../../src/middleware/VetoableSlasher.sol";
import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol";
// EigenLayer core contract imports for type casting
@ -140,7 +139,6 @@ contract DeployTestnet is DeployBase {
IGatewayV2 gateway,
DataHavenServiceManager serviceManager,
DataHavenServiceManager serviceManagerImplementation,
VetoableSlasher vetoableSlasher,
RewardsRegistry rewardsRegistry,
address rewardsAgent
) internal override {
@ -154,7 +152,6 @@ contract DeployTestnet is DeployBase {
Logging.logSection("DataHaven Contracts");
Logging.logContractDeployed("ServiceManager", address(serviceManager));
Logging.logContractDeployed("VetoableSlasher", address(vetoableSlasher));
Logging.logContractDeployed("RewardsRegistry", address(rewardsRegistry));
Logging.logSection(
@ -193,9 +190,6 @@ contract DeployTestnet is DeployBase {
vm.toString(address(serviceManagerImplementation)),
'",'
);
json = string.concat(
json, '"VetoableSlasher": "', vm.toString(address(vetoableSlasher)), '",'
);
json = string.concat(
json, '"RewardsRegistry": "', vm.toString(address(rewardsRegistry)), '",'
);

View file

@ -6,7 +6,6 @@ import {Script} from "forge-std/Script.sol";
// DataHaven imports
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
import {VetoableSlasher} from "../../src/middleware/VetoableSlasher.sol";
import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol";
/**
@ -16,7 +15,6 @@ import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol";
contract DHScriptStorage is Script {
// DataHaven Contract declarations
DataHavenServiceManager public serviceManager;
VetoableSlasher public vetoableSlasher;
RewardsRegistry public rewardsRegistry;
/**
@ -32,7 +30,6 @@ contract DHScriptStorage is Script {
// Store the contract addresses
serviceManager =
DataHavenServiceManager(vm.parseJsonAddress(deploymentFile, ".ServiceManager"));
vetoableSlasher = VetoableSlasher(vm.parseJsonAddress(deploymentFile, ".VetoableSlasher"));
rewardsRegistry =
RewardsRegistry(payable(vm.parseJsonAddress(deploymentFile, ".RewardsRegistry")));
}

View file

@ -2,7 +2,6 @@
pragma solidity ^0.8.27;
// EigenLayer imports
import {IAVSRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IAVSRegistrar.sol";
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
/**

View file

@ -1,40 +0,0 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {
IAllocationManager
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
interface ISlasherErrors {
/// @notice Thrown when a caller without slasher privileges attempts a restricted operation
error OnlySlasher();
}
interface ISlasherTypes {
/// @notice Structure containing details about a slashing request
struct SlashingRequest {
IAllocationManager.SlashingParams params;
uint256 requestTimestamp;
}
}
interface ISlasherEvents is ISlasherTypes {
/// @notice Emitted when an operator is successfully slashed
event OperatorSlashed(
uint256 indexed slashingRequestId,
address indexed operator,
uint32 indexed operatorSetId,
uint256[] wadsToSlash,
string description
);
}
/// @title ISlasher
/// @notice Base interface containing shared functionality for all slasher implementations
interface ISlasher is ISlasherErrors, ISlasherEvents {
/// @notice Returns the address authorized to create and fulfil slashing requests
function slasher() external view returns (address);
/// @notice Returns the next slashing request ID
function nextRequestId() external view returns (uint256);
}

View file

@ -1,87 +0,0 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {
IAllocationManager
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {ISlasher} from "./ISlasher.sol";
interface IVetoableSlasherErrors {
/// @notice Thrown when a caller without veto committee privileges attempts a restricted operation
error OnlyVetoCommittee();
/// @notice Thrown when attempting to veto a slashing request after the veto period has expired
error VetoPeriodPassed();
/// @notice Thrown when attempting to execute a slashing request before the veto period has ended
error VetoPeriodNotPassed();
/// @notice Thrown when attempting to interact with a slashing request that has been cancelled
error SlashingRequestIsCancelled();
/// @notice Thrown when attempting to modify a slashing request that does not exist
error SlashingRequestNotRequested();
}
interface IVetoableSlasherTypes {
/// @notice Structure containing details about a vetoable slashing request
struct VetoableSlashingRequest {
IAllocationManager.SlashingParams params;
uint256 requestBlock;
bool isPending;
}
}
interface IVetoableSlasherEvents {
/// @notice Emitted when a new slashing request is created
event SlashingRequested(
uint256 indexed requestId,
address indexed operator,
uint32 operatorSetId,
uint256[] wadsToSlash,
string description
);
/// @notice Emitted when a slashing request is cancelled by the veto committee
event SlashingRequestCancelled(
address indexed operator, uint32 operatorSetId, uint256[] wadsToSlash, string description
);
/// @notice Emitted when a slashing request is fulfilled
event SlashingRequestFulfilled(
address indexed operator, uint32 operatorSetId, uint256[] wadsToSlash, string description
);
}
/// @title IVetoableSlasher
/// @notice A slashing contract that implements a veto mechanism allowing a designated committee to cancel slashing requests
/// @dev Extends base interfaces and adds a veto period during which slashing requests can be cancelled
interface IVetoableSlasher is
ISlasher,
IVetoableSlasherErrors,
IVetoableSlasherTypes,
IVetoableSlasherEvents
{
/// @notice Duration of the veto period during which the veto committee can cancel slashing requests
function vetoWindowBlocks() external view returns (uint32);
/// @notice Address of the committee that has veto power over slashing requests
function vetoCommittee() external view returns (address);
/// @notice Queues a new slashing request
/// @param params Parameters defining the slashing request including operator and amount
/// @dev Can only be called by the authorized slasher
function queueSlashingRequest(
IAllocationManager.SlashingParams calldata params
) external;
/// @notice Cancels a pending slashing request
/// @param requestId 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
) external;
/// @notice Executes a slashing request after the veto period has passed
/// @param requestId The ID of the slashing request to fulfil
/// @dev Can only be called by the authorized slasher after the veto period
function fulfilSlashingRequest(
uint256 requestId
) external;
}

View file

@ -26,7 +26,6 @@ import {
import {IServiceManager, IServiceManagerUI} from "../interfaces/IServiceManager.sol";
import {IRewardsRegistry} from "../interfaces/IRewardsRegistry.sol";
import {IVetoableSlasher} from "../interfaces/IVetoableSlasher.sol";
import {ServiceManagerBaseStorage} from "./ServiceManagerBaseStorage.sol";
/**
@ -60,17 +59,6 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage, IAVSRegistrar
_setRewardsInitiator(_rewardsInitiator);
}
/**
* @notice Sets the slasher contract
* @param slasher The slasher contract address
* @dev Only callable by the owner
*/
function setSlasher(
IVetoableSlasher slasher
) external virtual onlyOwner {
_slasher = slasher;
}
/**
* @notice Updates the metadata URI for the AVS
* @param _metadataURI is the metadata URI for the AVS
@ -111,30 +99,6 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage, IAVSRegistrar
_allocationManager.removeStrategiesFromOperatorSet(address(this), operatorSetId, strategies);
}
/**
* Queue a slashing request in the vetoable slasher
* @param params Parameters defining the slashing request
* @dev Can only be called by the owner
*/
function queueSlashingRequest(
IAllocationManager.SlashingParams calldata params
) external virtual onlyOwner {
require(address(_slasher) != address(0), "Slasher not set");
_slasher.queueSlashingRequest(params);
}
/**
* fulfils a slashing request that has passed the veto period
* @param requestId The ID of the slashing request to fulfil
* @dev Can be called by anyone
*/
function fulfilSlashingRequest(
uint256 requestId
) external virtual {
require(address(_slasher) != address(0), "Slasher not set");
_slasher.fulfilSlashingRequest(requestId);
}
/**
* @dev DEPRECATED This function is not used. This contract distributes rewards directly to operators
* instead of using the RewardsCoordinator.

View file

@ -16,7 +16,6 @@ import {
IPermissionController
} from "eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol";
import {IVetoableSlasher} from "../interfaces/IVetoableSlasher.sol";
import {IServiceManager} from "../interfaces/IServiceManager.sol";
import {IRewardsRegistry} from "../interfaces/IRewardsRegistry.sol";
@ -41,9 +40,6 @@ abstract contract ServiceManagerBaseStorage is IServiceManager, OwnableUpgradeab
*
*/
/// @notice The slasher contract that handles operator slashing
IVetoableSlasher internal _slasher;
/// @notice The address of the entity that can initiate rewards
address public rewardsInitiator;

View file

@ -1,61 +0,0 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {SlasherStorage, IServiceManager} from "./SlasherBaseStorage.sol";
import {
IAllocationManagerTypes,
IAllocationManager
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
/// @title SlasherBase
/// @notice Base contract for implementing slashing functionality in an EigenLayer AVS
/// @dev Provides core slashing functionality and interfaces with EigenLayer's AllocationManager
abstract contract SlasherBase is SlasherStorage {
/// @notice Ensures only the authorized slasher can call certain functions
modifier onlySlasher() {
_checkSlasher(msg.sender);
_;
}
/// @notice Constructs the base slasher contract
/// @param _allocationManager The EigenLayer allocation manager contract
/// @param _serviceManager The service manager that will manage this slasher
constructor(
IAllocationManager _allocationManager,
IServiceManager _serviceManager
) SlasherStorage(_allocationManager, _serviceManager) {}
/// @notice Internal function to execute a slashing request
/// @param _requestId The ID of the slashing request to fulfil
/// @param _params Parameters defining the slashing request including operator, strategies, and amounts
/// @dev Calls AllocationManager.slashOperator to perform the actual slashing
function _fulfilSlashingRequest(
uint256 _requestId,
IAllocationManager.SlashingParams memory _params
) internal virtual {
allocationManager.slashOperator({avs: serviceManager.avs(), params: _params});
emit OperatorSlashed(
_requestId,
_params.operator,
_params.operatorSetId,
_params.wadsToSlash,
_params.description
);
}
/// @notice Internal function to verify if an account is the authorized slasher
/// @param account The address to check
/// @dev Reverts if the account is not the ServiceManager
function _checkSlasher(
address account
) internal view virtual {
require(account == address(serviceManager), OnlySlasher());
}
/// @notice Returns the address of the ServiceManager
/// @return The address of the ServiceManager
function slasher() external view returns (address) {
return address(serviceManager);
}
}

View file

@ -1,35 +0,0 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {
IAllocationManager
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {ISlasher} from "../interfaces/ISlasher.sol";
import {IServiceManager} from "../interfaces/IServiceManager.sol";
/// @title SlasherStorage
/// @notice Base storage contract for slashing functionality
/// @dev Provides storage variables and events for slashing operations
abstract contract SlasherStorage is ISlasher {
/**
*
* CONSTANTS AND IMMUTABLES
*
*/
/// @notice the AllocationManager that tracks OperatorSets and Slashing in EigenLayer
IAllocationManager public immutable allocationManager;
/// @notice the ServiceManager of the AVS
IServiceManager public immutable serviceManager;
uint256 public nextRequestId;
constructor(
IAllocationManager _allocationManager,
IServiceManager _serviceManager
) {
allocationManager = _allocationManager;
serviceManager = _serviceManager;
}
uint256[49] private __gap;
}

View file

@ -1,127 +0,0 @@
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.27;
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {IServiceManager} from "../interfaces/IServiceManager.sol";
import {
IAllocationManager
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {SlasherBase} from "./SlasherBase.sol";
import {IVetoableSlasher, IVetoableSlasherTypes} from "../interfaces/IVetoableSlasher.sol";
/// @title VetoableSlasher
/// @notice A slashing contract that implements a veto mechanism allowing a designated committee to cancel slashing requests
/// @dev Extends SlasherBase and adds a veto period during which slashing requests can be cancelled
contract VetoableSlasher is IVetoableSlasher, SlasherBase {
/// @inheritdoc IVetoableSlasher
uint32 public immutable override vetoWindowBlocks;
/// @inheritdoc IVetoableSlasher
address public immutable override vetoCommittee;
/// @notice Mapping of request IDs to their corresponding slashing request details
mapping(uint256 => IVetoableSlasherTypes.VetoableSlashingRequest) public slashingRequests;
/// @notice Modifier to restrict function access to only the veto committee
modifier onlyVetoCommittee() {
_checkVetoCommittee(msg.sender);
_;
}
constructor(
IAllocationManager _allocationManager,
IServiceManager _serviceManager,
address _vetoCommittee,
uint32 _vetoWindowBlocks
) SlasherBase(_allocationManager, _serviceManager) {
vetoWindowBlocks = _vetoWindowBlocks;
vetoCommittee = _vetoCommittee;
}
/// @inheritdoc IVetoableSlasher
function queueSlashingRequest(
IAllocationManager.SlashingParams calldata params
) external override onlySlasher {
_queueSlashingRequest(params);
}
/// @inheritdoc IVetoableSlasher
function cancelSlashingRequest(
uint256 requestId
) external override onlyVetoCommittee {
_cancelSlashingRequest(requestId);
}
/// @inheritdoc IVetoableSlasher
function fulfilSlashingRequest(
uint256 requestId
) external override {
_fulfilSlashingRequestAndMarkAsCompleted(requestId);
}
/// @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({
params: params, requestBlock: block.number, isPending: true
});
emit SlashingRequested(
requestId, 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
function _cancelSlashingRequest(
uint256 requestId
) internal virtual {
IVetoableSlasherTypes.VetoableSlashingRequest storage request = slashingRequests[requestId];
require(block.number < request.requestBlock + vetoWindowBlocks, VetoPeriodPassed());
require(request.isPending, SlashingRequestNotRequested());
emit SlashingRequestCancelled(
request.params.operator,
request.params.operatorSetId,
request.params.wadsToSlash,
request.params.description
);
delete slashingRequests[requestId];
}
/// @notice Internal function to fullfill a slashing request and mark it as completed
/// @param requestId The ID of the slashing request to fulfil
function _fulfilSlashingRequestAndMarkAsCompleted(
uint256 requestId
) internal virtual {
IVetoableSlasherTypes.VetoableSlashingRequest storage request = slashingRequests[requestId];
require(block.number >= request.requestBlock + vetoWindowBlocks, VetoPeriodNotPassed());
require(request.isPending, SlashingRequestIsCancelled());
request.isPending = false;
_fulfilSlashingRequest(requestId, request.params);
emit SlashingRequestFulfilled(
request.params.operator,
request.params.operatorSetId,
request.params.wadsToSlash,
request.params.description
);
delete slashingRequests[requestId];
}
/// @notice Internal function to verify if an account is the veto committee
/// @param account The address to check
/// @dev Reverts if the account is not the veto committee
function _checkVetoCommittee(
address account
) internal view virtual {
require(account == vetoCommittee, OnlyVetoCommittee());
}
}

View file

@ -1,235 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.27;
/* solhint-disable func-name-mixedcase */
import {Test, console} from "forge-std/Test.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {
IRewardsCoordinator
} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {
IAllocationManagerErrors,
IAllocationManager,
IAllocationManagerTypes
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {AVSDeployer} from "./utils/AVSDeployer.sol";
import {IServiceManager} from "../src/interfaces/IServiceManager.sol";
import {ISlasher, ISlasherErrors, ISlasherEvents} from "../src/interfaces/ISlasher.sol";
import {SlasherBase} from "../src/middleware/SlasherBase.sol";
import {SlasherMock} from "./mocks/SlasherBaseMock.sol";
contract SlasherBaseTest is AVSDeployer {
SlasherMock public slasherContract;
address public nonServiceManagerRole;
function setUp() public virtual {
_deployMockEigenLayerAndAVS();
// Set up roles for testing
nonServiceManagerRole = address(0x5678);
// Deploy the SlasherMock contract, to specifically test the SlasherBase contract
slasherContract = new SlasherMock(allocationManager, serviceManager);
}
// Test constructor initializes state correctly
function test_constructor() public view {
assertEq(
address(slasherContract.allocationManager()),
address(allocationManager),
"AllocationManager address mismatch"
);
assertEq(
address(slasherContract.serviceManager()),
address(serviceManager),
"ServiceManager address mismatch"
);
assertEq(slasherContract.nextRequestId(), 0, "NextRequestId should be initialized to 0");
}
// Test that a function with the onlySlasher modifier reverts when called by non-ServiceManager
function test_onlySlasherModifier_nonSlasher() public {
vm.prank(nonServiceManagerRole);
vm.expectRevert(abi.encodeWithSelector(ISlasherErrors.OnlySlasher.selector));
slasherContract.restrictedFunction();
}
// Test that a function with the onlySlasher modifier allows access when called by ServiceManager
function test_onlySlasherModifier_slasher() public {
vm.prank(address(serviceManager));
// This should not revert
slasherContract.restrictedFunction();
}
// Test that fulfilSlashingRequest can be called by anyone now that the onlySlasher modifier has been removed
function test_fulfilSlashingRequest_anyoneCanCall() public {
// Setup mock params
address operator = address(0xabcd);
uint32 operatorSetId = 1;
IStrategy[] memory strategies = new IStrategy[](1);
strategies[0] = deployedStrategies[0];
uint256[] memory wadsToSlash = new uint256[](1);
wadsToSlash[0] = 1e16;
string memory description = "Test slashing by non-ServiceManager";
IAllocationManagerTypes.SlashingParams memory params = IAllocationManagerTypes.SlashingParams({
operator: operator,
operatorSetId: operatorSetId,
strategies: strategies,
wadsToSlash: wadsToSlash,
description: description
});
// Mock the allocationManager.slashOperator call
uint256[] memory slashedShares = new uint256[](strategies.length);
vm.mockCall(
address(allocationManager),
abi.encodeWithSelector(
IAllocationManager.slashOperator.selector, serviceManager.avs(), params
),
abi.encode(uint256(0), slashedShares)
);
uint256 requestId = 5;
// A random address should be able to call fulfilSlashingRequest
vm.prank(nonServiceManagerRole);
vm.expectEmit(true, true, true, true);
emit ISlasherEvents.OperatorSlashed(
requestId, operator, operatorSetId, wadsToSlash, description
);
slasherContract.fulfilSlashingRequest(requestId, params);
}
// Test the _checkSlasher internal function
function test_checkSlasher() public {
// Should succeed for ServiceManager
vm.prank(address(serviceManager));
slasherContract.checkSlasher(address(serviceManager));
// Should revert for non-ServiceManager
vm.expectRevert(abi.encodeWithSelector(ISlasherErrors.OnlySlasher.selector));
slasherContract.checkSlasher(nonServiceManagerRole);
}
// Test the _fulfilSlashingRequest internal function with different parameters
function test_fulfilSlashingRequest_withMultipleStrategies() public {
// Setup mock params with multiple strategies
address operator = address(0xabcd);
uint32 operatorSetId = 1;
IStrategy[] memory strategies = new IStrategy[](2);
strategies[0] = deployedStrategies[0];
strategies[1] = deployedStrategies[1];
uint256[] memory wadsToSlash = new uint256[](2);
wadsToSlash[0] = 1e16; // 1% of the operator's stake
wadsToSlash[1] = 2e16; // 2% of the operator's stake
string memory description = "Multiple strategy slashing";
IAllocationManagerTypes.SlashingParams memory params = IAllocationManagerTypes.SlashingParams({
operator: operator,
operatorSetId: operatorSetId,
strategies: strategies,
wadsToSlash: wadsToSlash,
description: description
});
// Mock the allocationManager.slashOperator call
uint256[] memory slashedShares = new uint256[](strategies.length);
vm.mockCall(
address(allocationManager),
abi.encodeWithSelector(
IAllocationManager.slashOperator.selector, serviceManager.avs(), params
),
abi.encode(uint256(0), slashedShares)
);
uint256 requestId = 2;
// ServiceManager should be able to call fulfilSlashingRequest
vm.prank(address(serviceManager));
vm.expectEmit(true, true, true, true);
emit ISlasherEvents.OperatorSlashed(
requestId, operator, operatorSetId, wadsToSlash, description
);
slasherContract.fulfilSlashingRequest(requestId, params);
}
// Test fulfilSlashingRequest with zero wads to slash
function test_fulfilSlashingRequest_zeroWadsToSlash() public {
// Setup mock params with zero wads
address operator = address(0xabcd);
uint32 operatorSetId = 1;
IStrategy[] memory strategies = new IStrategy[](1);
strategies[0] = deployedStrategies[0];
uint256[] memory wadsToSlash = new uint256[](1);
wadsToSlash[0] = 0; // Zero tokens
string memory description = "Zero wad slashing";
IAllocationManagerTypes.SlashingParams memory params = IAllocationManagerTypes.SlashingParams({
operator: operator,
operatorSetId: operatorSetId,
strategies: strategies,
wadsToSlash: wadsToSlash,
description: description
});
// Mock the allocationManager.slashOperator call
uint256[] memory slashedShares = new uint256[](strategies.length);
vm.mockCall(
address(allocationManager),
abi.encodeWithSelector(
IAllocationManager.slashOperator.selector, serviceManager.avs(), params
),
abi.encode(uint256(0), slashedShares)
);
uint256 requestId = 3;
// ServiceManager should be able to call fulfilSlashingRequest
vm.prank(address(serviceManager));
vm.expectEmit(true, true, true, true);
emit ISlasherEvents.OperatorSlashed(
requestId, operator, operatorSetId, wadsToSlash, description
);
slasherContract.fulfilSlashingRequest(requestId, params);
}
// Test error handling when allocationManager.slashOperator reverts
function test_fulfilSlashingRequest_allocationManagerReverts() public {
// Setup mock params
address operator = address(0xabcd);
uint32 operatorSetId = 1;
IStrategy[] memory strategies = new IStrategy[](1);
strategies[0] = deployedStrategies[0];
uint256[] memory wadsToSlash = new uint256[](1);
wadsToSlash[0] = 1e16; // 1% of the operator's stake
string memory description = "Revert test";
IAllocationManagerTypes.SlashingParams memory params = IAllocationManagerTypes.SlashingParams({
operator: operator,
operatorSetId: operatorSetId,
strategies: strategies,
wadsToSlash: wadsToSlash,
description: description
});
// Mock the allocationManager.slashOperator call to revert
vm.mockCallRevert(
address(allocationManager),
abi.encodeWithSelector(
IAllocationManager.slashOperator.selector, serviceManager.avs(), params
),
abi.encodeWithSignature("SomeError()")
);
uint256 requestId = 4;
// ServiceManager should be able to call fulfilSlashingRequest
vm.prank(address(serviceManager));
vm.expectRevert(abi.encodeWithSignature("SomeError()"));
slasherContract.fulfilSlashingRequest(requestId, params);
}
}

View file

@ -1,399 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.27;
/* solhint-disable func-name-mixedcase */
import {Test, console} from "forge-std/Test.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {
IRewardsCoordinator
} from "eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
import {
IAllocationManagerErrors,
IAllocationManager,
IAllocationManagerTypes
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {AVSDeployer} from "./utils/AVSDeployer.sol";
import {IServiceManager} from "../src/interfaces/IServiceManager.sol";
import {ISlasher, ISlasherErrors, ISlasherEvents} from "../src/interfaces/ISlasher.sol";
import {
IVetoableSlasher,
IVetoableSlasherTypes,
IVetoableSlasherErrors,
IVetoableSlasherEvents
} from "../src/interfaces/IVetoableSlasher.sol";
import {SlasherBase} from "../src/middleware/SlasherBase.sol";
import {VetoableSlasher} from "../src/middleware/VetoableSlasher.sol";
contract VetoableSlasherTest is AVSDeployer {
address public nonServiceManagerRole;
address public nonVetoCommittee;
// Events for testing
event SlashingRequested(
uint256 indexed requestId,
address indexed operator,
uint32 indexed operatorSetId,
uint256[] wadsToSlash,
string description
);
event SlashingRequestCancelled(
address indexed operator, uint32 operatorSetId, uint256[] wadsToSlash, string description
);
event SlashingRequestFulfilled(
address indexed operator, uint32 operatorSetId, uint256[] wadsToSlash, string description
);
function setUp() public virtual {
_deployMockEigenLayerAndAVS();
// Set up roles for testing
nonServiceManagerRole = address(0x5678);
nonVetoCommittee = address(0xdcba);
}
// Test constructor initializes state correctly
function test_constructor() public view {
assertEq(
address(vetoableSlasher.allocationManager()),
address(allocationManager),
"AllocationManager address mismatch"
);
assertEq(
address(vetoableSlasher.serviceManager()),
address(serviceManager),
"ServiceManager address mismatch"
);
assertEq(
vetoableSlasher.vetoCommittee(), vetoCommitteeMember, "Veto committee address mismatch"
);
assertEq(
vetoableSlasher.vetoWindowBlocks(), vetoWindowBlocks, "Veto window blocks mismatch"
);
assertEq(vetoableSlasher.nextRequestId(), 0, "NextRequestId should be initialized to 0");
}
// Test queueSlashingRequest reverts when called by non-ServiceManager
function test_queueSlashingRequest_nonServiceManager() public {
IAllocationManagerTypes.SlashingParams memory params;
vm.prank(nonServiceManagerRole);
vm.expectRevert(abi.encodeWithSelector(ISlasherErrors.OnlySlasher.selector));
vetoableSlasher.queueSlashingRequest(params);
}
// Test queueSlashingRequest succeeds when called by ServiceManager
function test_queueSlashingRequest_serviceManager() public {
// Setup mock params
address operator = address(0x1111);
uint32 operatorSetId = 1;
IStrategy[] memory strategies = new IStrategy[](1);
strategies[0] = deployedStrategies[0];
uint256[] memory wadsToSlash = new uint256[](1);
wadsToSlash[0] = 1e16; // 1% of the operator's stake
string memory description = "Test slashing";
IAllocationManagerTypes.SlashingParams memory params = IAllocationManagerTypes.SlashingParams({
operator: operator,
operatorSetId: operatorSetId,
strategies: strategies,
wadsToSlash: wadsToSlash,
description: description
});
uint256 requestId = 0; // First request
vm.prank(address(serviceManager));
vm.expectEmit(true, true, true, true);
emit IVetoableSlasherEvents.SlashingRequested(
requestId, operator, operatorSetId, wadsToSlash, description
);
vetoableSlasher.queueSlashingRequest(params);
// Verify request is stored correctly
(
IAllocationManagerTypes.SlashingParams memory storedParams,
uint256 requestBlock,
bool isPending
) = _getSlashingRequest(requestId);
assertEq(storedParams.operator, operator, "Operator mismatch");
assertEq(storedParams.operatorSetId, operatorSetId, "OperatorSetId mismatch");
assertEq(storedParams.wadsToSlash[0], wadsToSlash[0], "WadsToSlash mismatch");
assertEq(storedParams.description, description, "Description mismatch");
assertEq(requestBlock, block.number, "Request block mismatch");
assertEq(isPending, true, "Status mismatch");
// Verify nextRequestId is incremented
assertEq(vetoableSlasher.nextRequestId(), 1, "NextRequestId should be incremented");
}
// Test cancelSlashingRequest reverts when called by non-veto committee
function test_cancelSlashingRequest_nonVetoCommittee() public {
// First create a request
_createSlashingRequest();
vm.prank(nonVetoCommittee);
vm.expectRevert(abi.encodeWithSelector(IVetoableSlasherErrors.OnlyVetoCommittee.selector));
vetoableSlasher.cancelSlashingRequest(0);
}
// Test cancelSlashingRequest succeeds when called by veto committee within veto period
function test_cancelSlashingRequest_withinVetoPeriod() public {
// First create a request
uint256 requestId = _createSlashingRequest();
(IAllocationManagerTypes.SlashingParams memory params,,) = _getSlashingRequest(requestId);
vm.prank(vetoCommitteeMember);
vm.expectEmit(true, false, false, false);
emit IVetoableSlasherEvents.SlashingRequestCancelled(
params.operator, params.operatorSetId, params.wadsToSlash, params.description
);
vetoableSlasher.cancelSlashingRequest(requestId);
// Verify request status is updated
(,, bool isPending) = _getSlashingRequest(requestId);
assertEq(isPending, false, "Status should be Cancelled");
}
// Test cancelSlashingRequest reverts when veto period has passed
function test_cancelSlashingRequest_afterVetoPeriod() public {
// First create a request
uint256 requestId = _createSlashingRequest();
// Fast forward past veto period
vm.roll(block.number + vetoWindowBlocks + 1);
vm.prank(vetoCommitteeMember);
vm.expectRevert(abi.encodeWithSelector(IVetoableSlasherErrors.VetoPeriodPassed.selector));
vetoableSlasher.cancelSlashingRequest(requestId);
}
// Test cancelSlashingRequest reverts when request is not in Requested state
function test_cancelSlashingRequest_notRequested() public {
// First create a request
uint256 requestId = _createSlashingRequest();
// Cancel it once
vm.prank(vetoCommitteeMember);
vetoableSlasher.cancelSlashingRequest(requestId);
// Try to cancel it again
vm.prank(vetoCommitteeMember);
vm.expectRevert(
abi.encodeWithSelector(IVetoableSlasherErrors.SlashingRequestNotRequested.selector)
);
vetoableSlasher.cancelSlashingRequest(requestId);
}
// Test fulfilSlashingRequest reverts before veto period has passed
function test_fulfilSlashingRequest_beforeVetoPeriod() public {
// First create a request
uint256 requestId = _createSlashingRequest();
vm.prank(address(serviceManager));
vm.expectRevert(abi.encodeWithSelector(IVetoableSlasherErrors.VetoPeriodNotPassed.selector));
vetoableSlasher.fulfilSlashingRequest(requestId);
}
// Test fulfilSlashingRequest reverts when request is cancelled
function test_fulfilSlashingRequest_cancelled() public {
// First create a request
uint256 requestId = _createSlashingRequest();
// Cancel it
vm.prank(vetoCommitteeMember);
vetoableSlasher.cancelSlashingRequest(requestId);
// Fast forward past veto period
vm.roll(block.number + vetoWindowBlocks + 1);
vm.prank(address(serviceManager));
vm.expectRevert(
abi.encodeWithSelector(IVetoableSlasherErrors.SlashingRequestIsCancelled.selector)
);
vetoableSlasher.fulfilSlashingRequest(requestId);
}
// Test fulfilSlashingRequest succeeds after veto period has passed
function test_fulfilSlashingRequest_afterVetoPeriod() public {
// First create a request
uint256 requestId = _createSlashingRequest();
address operator = address(0x1111);
uint32 operatorSetId = 1;
// Setup the mock for slashing
IAllocationManagerTypes.SlashingParams memory params;
(params,,) = _getSlashingRequest(requestId);
uint256[] memory slashedShares = new uint256[](params.strategies.length);
vm.mockCall(
address(allocationManager),
abi.encodeWithSelector(
IAllocationManager.slashOperator.selector, serviceManager.avs(), params
),
abi.encode(uint256(0), slashedShares)
);
// Fast forward past veto period
vm.roll(block.number + vetoWindowBlocks + 1);
vm.prank(address(serviceManager));
vm.expectEmit(true, true, true, true);
emit ISlasherEvents.OperatorSlashed(
requestId, operator, operatorSetId, params.wadsToSlash, params.description
);
vm.expectEmit(true, true, true, true);
emit SlashingRequestFulfilled(
operator, operatorSetId, params.wadsToSlash, params.description
);
vetoableSlasher.fulfilSlashingRequest(requestId);
// Verify request is deleted from storage
(
IAllocationManagerTypes.SlashingParams memory emptyParams,
uint256 requestBlock,
bool isPending
) = _getSlashingRequest(requestId);
assertEq(
emptyParams.operator, address(0), "Request should be deleted - operator not zeroed"
);
assertEq(requestBlock, 0, "Request should be deleted - requestBlock not zeroed");
assertEq(isPending, false, "Request should be deleted - isPending not false");
}
// Test cancelSlashingRequest properly deletes the request from storage
function test_cancelSlashingRequest_deletesFromStorage() public {
// First create a request
uint256 requestId = _createSlashingRequest();
(IAllocationManagerTypes.SlashingParams memory params,,) = _getSlashingRequest(requestId);
vm.prank(vetoCommitteeMember);
vm.expectEmit(true, true, true, true);
emit SlashingRequestCancelled(
params.operator, params.operatorSetId, params.wadsToSlash, params.description
);
vetoableSlasher.cancelSlashingRequest(requestId);
// Verify request is deleted from storage
(
IAllocationManagerTypes.SlashingParams memory emptyParams,
uint256 requestBlock,
bool isPending
) = _getSlashingRequest(requestId);
assertEq(
emptyParams.operator, address(0), "Request should be deleted - operator not zeroed"
);
assertEq(requestBlock, 0, "Request should be deleted - requestBlock not zeroed");
assertEq(isPending, false, "Request should be deleted - isPending not false");
}
// Test multiple requests flow
function test_multipleRequests() public {
// Create first request
uint256 requestId1 = _createSlashingRequest();
// Create second request with different parameters
address operator2 = address(0x2222);
uint32 operatorSetId2 = 2;
IStrategy[] memory strategies2 = new IStrategy[](1);
strategies2[0] = deployedStrategies[1];
uint256[] memory wadsToSlash2 = new uint256[](1);
wadsToSlash2[0] = 2e16; // 2% of the operator's stake
string memory description2 = "Second slashing";
IAllocationManagerTypes.SlashingParams memory params2 =
IAllocationManagerTypes.SlashingParams({
operator: operator2,
operatorSetId: operatorSetId2,
strategies: strategies2,
wadsToSlash: wadsToSlash2,
description: description2
});
uint256 requestId2 = 1; // Second request
vm.prank(address(serviceManager));
vetoableSlasher.queueSlashingRequest(params2);
// Cancel the first request
vm.prank(vetoCommitteeMember);
vetoableSlasher.cancelSlashingRequest(requestId1);
// Setup the mock for slashing the second request
uint256[] memory slashedShares = new uint256[](params2.strategies.length);
vm.mockCall(
address(allocationManager),
abi.encodeWithSelector(
IAllocationManager.slashOperator.selector, serviceManager.avs(), params2
),
abi.encode(uint256(0), slashedShares)
);
// Fast forward past veto period
vm.roll(block.number + vetoWindowBlocks + 1);
// Try to fulfil the first (cancelled) request - should revert
vm.prank(address(serviceManager));
vm.expectRevert(
abi.encodeWithSelector(IVetoableSlasherErrors.SlashingRequestIsCancelled.selector)
);
vetoableSlasher.fulfilSlashingRequest(requestId1);
// fulfil the second request - should succeed
vm.prank(address(serviceManager));
vetoableSlasher.fulfilSlashingRequest(requestId2);
// Verify states
(,, bool isPending1) = _getSlashingRequest(requestId1);
(,, bool isPending2) = _getSlashingRequest(requestId2);
assertEq(isPending1, false, "Request 1 status should be Cancelled");
assertEq(isPending2, false, "Request 2 status should be Completed");
}
// Helper function to create a standard slashing request
function _createSlashingRequest() internal returns (uint256) {
address operator = address(0x1111);
uint32 operatorSetId = 1;
IStrategy[] memory strategies = new IStrategy[](1);
strategies[0] = deployedStrategies[0];
uint256[] memory wadsToSlash = new uint256[](1);
wadsToSlash[0] = 1e16; // 1% of the operator's stake
string memory description = "Test slashing";
IAllocationManagerTypes.SlashingParams memory params = IAllocationManagerTypes.SlashingParams({
operator: operator,
operatorSetId: operatorSetId,
strategies: strategies,
wadsToSlash: wadsToSlash,
description: description
});
uint256 requestId = vetoableSlasher.nextRequestId();
vm.prank(address(serviceManager));
vetoableSlasher.queueSlashingRequest(params);
return requestId;
}
// Helper function to extract SlashingRequest from storage
function _getSlashingRequest(
uint256 requestId
)
internal
view
returns (
IAllocationManagerTypes.SlashingParams memory params,
uint256 requestBlock,
bool isPending
)
{
(params, requestBlock, isPending) = vetoableSlasher.slashingRequests(requestId);
}
}

View file

@ -1,37 +0,0 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.27;
import {SlasherBase} from "../../src/middleware/SlasherBase.sol";
import {
IAllocationManager,
IAllocationManagerTypes
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IServiceManager} from "../../src/interfaces/IServiceManager.sol";
// SlasherMock implementation for testing
contract SlasherMock is SlasherBase {
constructor(
IAllocationManager _allocationManager,
IServiceManager _serviceManager
) SlasherBase(_allocationManager, _serviceManager) {}
// Expose the internal _fulfilSlashingRequest function for testing
function fulfilSlashingRequest(
uint256 _requestId,
IAllocationManagerTypes.SlashingParams memory _params
) external {
_fulfilSlashingRequest(_requestId, _params);
}
// Function with the onlySlasher modifier for testing
function restrictedFunction() external onlySlasher {
// Do nothing, just for testing the modifier
}
// Expose the internal _checkSlasher function for testing
function checkSlasher(
address account
) external view {
_checkSlasher(account);
}
}

View file

@ -30,8 +30,6 @@ import {StrategyManager} from "eigenlayer-contracts/src/contracts/core/StrategyM
import {IEigenPodManager} from "eigenlayer-contracts/src/contracts/interfaces/IEigenPodManager.sol";
import {ERC20FixedSupply} from "./ERC20FixedSupply.sol";
import {IServiceManager} from "../../src/interfaces/IServiceManager.sol";
import {VetoableSlasher} from "../../src/middleware/VetoableSlasher.sol";
import {IVetoableSlasher} from "../../src/interfaces/IVetoableSlasher.sol";
import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol";
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
// Mocks
@ -52,10 +50,8 @@ contract AVSDeployer is Test {
// AVS contracts
DataHavenServiceManager public serviceManager;
DataHavenServiceManager public serviceManagerImplementation;
VetoableSlasher public vetoableSlasher;
RewardsRegistry public rewardsRegistry;
// VetoableSlasher roles and parameters
address public vetoCommitteeMember =
address(uint160(uint256(keccak256("vetoCommitteeMember"))));
uint32 public vetoWindowBlocks = 100; // 100 blocks veto window for tests
@ -278,18 +274,6 @@ contract AVSDeployer is Test {
cheats.stopPrank();
console.log("ServiceManager implementation deployed");
// Deploy and configure the VetoableSlasher
cheats.prank(regularDeployer);
vetoableSlasher = new VetoableSlasher(
allocationManager, serviceManager, vetoCommitteeMember, vetoWindowBlocks
);
// Set the slasher in the ServiceManager
cheats.prank(avsOwner);
serviceManager.setSlasher(vetoableSlasher);
console.log("VetoableSlasher deployed and configured");
// Deploy the RewardsRegistry contract
cheats.prank(regularDeployer);
rewardsRegistry = new RewardsRegistry(address(serviceManager), mockRewardsAgent);
@ -390,7 +374,6 @@ contract AVSDeployer is Test {
cheats.label(address(allocationManagerImplementation), "AllocationManagerImplementation");
cheats.label(address(serviceManager), "ServiceManager");
cheats.label(address(serviceManagerImplementation), "ServiceManagerImplementation");
cheats.label(address(vetoableSlasher), "VetoableSlasher");
}
/// @dev Sort to ensure that the array is in ascending order for strategies

View file

@ -83,7 +83,6 @@ bun cli launch --deploy-contracts --execute-owner-transactions
When tx execution is off, the CLI prints a list of `{to, data, value}` objects for:
1. `updateAVSMetadataURI("")`
2. `setSlasher(vetoableSlasher)`
3. `setRewardsRegistry(validatorsSetId, rewardsRegistry)`
4. `setRewardsAgent(validatorsSetId, rewardsAgent)`

View file

@ -4,7 +4,7 @@ Deploy DataHaven AVS contracts to supported chains (Hoodi, Mainnet).
## What Gets Deployed
- **DataHaven**: ServiceManager, VetoableSlasher, RewardsRegistry
- **DataHaven**: ServiceManager, RewardsRegistry
- **Snowbridge**: BeefyClient, AgentExecutor, Gateway, RewardsAgent
- **EigenLayer**: References existing contracts (not deployed)

View file

@ -74,7 +74,6 @@ const showDatahavenContractStatus = async (chain: string, rpcUrl: string) => {
try {
const contracts = [
{ name: "DataHavenServiceManager", key: "ServiceManagerImplementation" },
{ name: "VetoableSlasher", key: "VetoableSlasher" },
{ name: "RewardsRegistry", key: "RewardsRegistry" },
{ name: "Snowbridge BeefyClient", key: "BeefyClient" },
{ name: "Snowbridge AgentExecutor", key: "AgentExecutor" },

View file

@ -49,18 +49,6 @@ export const verifyContracts = async (options: ContractsVerifyOptions) => {
],
constructorArgTypes: ["address", "address", "address"]
},
{
name: "VetoableSlasher",
address: deployments.VetoableSlasher,
artifactName: "VetoableSlasher",
constructorArgs: [
deployments.AllocationManager,
deployments.ServiceManager,
"0x0000000000000000000000000000000000000000",
"0"
],
constructorArgTypes: ["address", "address", "address", "uint32"]
},
{
name: "RewardsRegistry",
address: deployments.RewardsRegistry,

View file

@ -2289,13 +2289,6 @@ export const dataHavenServiceManagerAbi = [
outputs: [],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [{ name: 'requestId', internalType: 'uint256', type: 'uint256' }],
name: 'fulfilSlashingRequest',
outputs: [],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [{ name: 'operator', internalType: 'address', type: 'address' }],
@ -2346,30 +2339,6 @@ export const dataHavenServiceManagerAbi = [
outputs: [{ name: '', internalType: 'address', type: 'address' }],
stateMutability: 'view',
},
{
type: 'function',
inputs: [
{
name: 'params',
internalType: 'struct IAllocationManagerTypes.SlashingParams',
type: 'tuple',
components: [
{ name: 'operator', internalType: 'address', type: 'address' },
{ name: 'operatorSetId', internalType: 'uint32', type: 'uint32' },
{
name: 'strategies',
internalType: 'contract IStrategy[]',
type: 'address[]',
},
{ name: 'wadsToSlash', internalType: 'uint256[]', type: 'uint256[]' },
{ name: 'description', internalType: 'string', type: 'string' },
],
},
],
name: 'queueSlashingRequest',
outputs: [],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [
@ -2538,19 +2507,6 @@ export const dataHavenServiceManagerAbi = [
outputs: [],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [
{
name: 'slasher',
internalType: 'contract IVetoableSlasher',
type: 'address',
},
],
name: 'setSlasher',
outputs: [],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [
@ -9693,287 +9649,6 @@ export const upgradeableBeaconAbi = [
},
] as const
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// VetoableSlasher
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
export const vetoableSlasherAbi = [
{
type: 'constructor',
inputs: [
{
name: '_allocationManager',
internalType: 'contract IAllocationManager',
type: 'address',
},
{
name: '_serviceManager',
internalType: 'contract IServiceManager',
type: 'address',
},
{ name: '_vetoCommittee', internalType: 'address', type: 'address' },
{ name: '_vetoWindowBlocks', internalType: 'uint32', type: 'uint32' },
],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [],
name: 'allocationManager',
outputs: [
{
name: '',
internalType: 'contract IAllocationManager',
type: 'address',
},
],
stateMutability: 'view',
},
{
type: 'function',
inputs: [{ name: 'requestId', internalType: 'uint256', type: 'uint256' }],
name: 'cancelSlashingRequest',
outputs: [],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [{ name: 'requestId', internalType: 'uint256', type: 'uint256' }],
name: 'fulfilSlashingRequest',
outputs: [],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [],
name: 'nextRequestId',
outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
stateMutability: 'view',
},
{
type: 'function',
inputs: [
{
name: 'params',
internalType: 'struct IAllocationManagerTypes.SlashingParams',
type: 'tuple',
components: [
{ name: 'operator', internalType: 'address', type: 'address' },
{ name: 'operatorSetId', internalType: 'uint32', type: 'uint32' },
{
name: 'strategies',
internalType: 'contract IStrategy[]',
type: 'address[]',
},
{ name: 'wadsToSlash', internalType: 'uint256[]', type: 'uint256[]' },
{ name: 'description', internalType: 'string', type: 'string' },
],
},
],
name: 'queueSlashingRequest',
outputs: [],
stateMutability: 'nonpayable',
},
{
type: 'function',
inputs: [],
name: 'serviceManager',
outputs: [
{ name: '', internalType: 'contract IServiceManager', type: 'address' },
],
stateMutability: 'view',
},
{
type: 'function',
inputs: [],
name: 'slasher',
outputs: [{ name: '', internalType: 'address', type: 'address' }],
stateMutability: 'view',
},
{
type: 'function',
inputs: [{ name: '', internalType: 'uint256', type: 'uint256' }],
name: 'slashingRequests',
outputs: [
{
name: 'params',
internalType: 'struct IAllocationManagerTypes.SlashingParams',
type: 'tuple',
components: [
{ name: 'operator', internalType: 'address', type: 'address' },
{ name: 'operatorSetId', internalType: 'uint32', type: 'uint32' },
{
name: 'strategies',
internalType: 'contract IStrategy[]',
type: 'address[]',
},
{ name: 'wadsToSlash', internalType: 'uint256[]', type: 'uint256[]' },
{ name: 'description', internalType: 'string', type: 'string' },
],
},
{ name: 'requestBlock', internalType: 'uint256', type: 'uint256' },
{ name: 'isPending', internalType: 'bool', type: 'bool' },
],
stateMutability: 'view',
},
{
type: 'function',
inputs: [],
name: 'vetoCommittee',
outputs: [{ name: '', internalType: 'address', type: 'address' }],
stateMutability: 'view',
},
{
type: 'function',
inputs: [],
name: 'vetoWindowBlocks',
outputs: [{ name: '', internalType: 'uint32', type: 'uint32' }],
stateMutability: 'view',
},
{
type: 'event',
anonymous: false,
inputs: [
{
name: 'slashingRequestId',
internalType: 'uint256',
type: 'uint256',
indexed: true,
},
{
name: 'operator',
internalType: 'address',
type: 'address',
indexed: true,
},
{
name: 'operatorSetId',
internalType: 'uint32',
type: 'uint32',
indexed: true,
},
{
name: 'wadsToSlash',
internalType: 'uint256[]',
type: 'uint256[]',
indexed: false,
},
{
name: 'description',
internalType: 'string',
type: 'string',
indexed: false,
},
],
name: 'OperatorSlashed',
},
{
type: 'event',
anonymous: false,
inputs: [
{
name: 'operator',
internalType: 'address',
type: 'address',
indexed: true,
},
{
name: 'operatorSetId',
internalType: 'uint32',
type: 'uint32',
indexed: false,
},
{
name: 'wadsToSlash',
internalType: 'uint256[]',
type: 'uint256[]',
indexed: false,
},
{
name: 'description',
internalType: 'string',
type: 'string',
indexed: false,
},
],
name: 'SlashingRequestCancelled',
},
{
type: 'event',
anonymous: false,
inputs: [
{
name: 'operator',
internalType: 'address',
type: 'address',
indexed: true,
},
{
name: 'operatorSetId',
internalType: 'uint32',
type: 'uint32',
indexed: false,
},
{
name: 'wadsToSlash',
internalType: 'uint256[]',
type: 'uint256[]',
indexed: false,
},
{
name: 'description',
internalType: 'string',
type: 'string',
indexed: false,
},
],
name: 'SlashingRequestFulfilled',
},
{
type: 'event',
anonymous: false,
inputs: [
{
name: 'requestId',
internalType: 'uint256',
type: 'uint256',
indexed: true,
},
{
name: 'operator',
internalType: 'address',
type: 'address',
indexed: true,
},
{
name: 'operatorSetId',
internalType: 'uint32',
type: 'uint32',
indexed: false,
},
{
name: 'wadsToSlash',
internalType: 'uint256[]',
type: 'uint256[]',
indexed: false,
},
{
name: 'description',
internalType: 'string',
type: 'string',
indexed: false,
},
],
name: 'SlashingRequested',
},
{ type: 'error', inputs: [], name: 'OnlySlasher' },
{ type: 'error', inputs: [], name: 'OnlyVetoCommittee' },
{ type: 'error', inputs: [], name: 'SlashingRequestIsCancelled' },
{ type: 'error', inputs: [], name: 'SlashingRequestNotRequested' },
{ type: 'error', inputs: [], name: 'VetoPeriodNotPassed' },
{ type: 'error', inputs: [], name: 'VetoPeriodPassed' },
] as const
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Action
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -11675,15 +11350,6 @@ export const writeDataHavenServiceManagerDeregisterOperatorFromOperatorSets =
functionName: 'deregisterOperatorFromOperatorSets',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"fulfilSlashingRequest"`
*/
export const writeDataHavenServiceManagerFulfilSlashingRequest =
/*#__PURE__*/ createWriteContract({
abi: dataHavenServiceManagerAbi,
functionName: 'fulfilSlashingRequest',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"initialise"`
*/
@ -11693,15 +11359,6 @@ export const writeDataHavenServiceManagerInitialise =
functionName: 'initialise',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"queueSlashingRequest"`
*/
export const writeDataHavenServiceManagerQueueSlashingRequest =
/*#__PURE__*/ createWriteContract({
abi: dataHavenServiceManagerAbi,
functionName: 'queueSlashingRequest',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"registerOperator"`
*/
@ -11837,15 +11494,6 @@ export const writeDataHavenServiceManagerSetRewardsRegistry =
functionName: 'setRewardsRegistry',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"setSlasher"`
*/
export const writeDataHavenServiceManagerSetSlasher =
/*#__PURE__*/ createWriteContract({
abi: dataHavenServiceManagerAbi,
functionName: 'setSlasher',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"setSnowbridgeGateway"`
*/
@ -12005,15 +11653,6 @@ export const simulateDataHavenServiceManagerDeregisterOperatorFromOperatorSets =
functionName: 'deregisterOperatorFromOperatorSets',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"fulfilSlashingRequest"`
*/
export const simulateDataHavenServiceManagerFulfilSlashingRequest =
/*#__PURE__*/ createSimulateContract({
abi: dataHavenServiceManagerAbi,
functionName: 'fulfilSlashingRequest',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"initialise"`
*/
@ -12023,15 +11662,6 @@ export const simulateDataHavenServiceManagerInitialise =
functionName: 'initialise',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"queueSlashingRequest"`
*/
export const simulateDataHavenServiceManagerQueueSlashingRequest =
/*#__PURE__*/ createSimulateContract({
abi: dataHavenServiceManagerAbi,
functionName: 'queueSlashingRequest',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"registerOperator"`
*/
@ -12167,15 +11797,6 @@ export const simulateDataHavenServiceManagerSetRewardsRegistry =
functionName: 'setRewardsRegistry',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"setSlasher"`
*/
export const simulateDataHavenServiceManagerSetSlasher =
/*#__PURE__*/ createSimulateContract({
abi: dataHavenServiceManagerAbi,
functionName: 'setSlasher',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link dataHavenServiceManagerAbi}__ and `functionName` set to `"setSnowbridgeGateway"`
*/
@ -17562,183 +17183,3 @@ export const watchUpgradeableBeaconUpgradedEvent =
abi: upgradeableBeaconAbi,
eventName: 'Upgraded',
})
/**
* Wraps __{@link readContract}__ with `abi` set to __{@link vetoableSlasherAbi}__
*/
export const readVetoableSlasher = /*#__PURE__*/ createReadContract({
abi: vetoableSlasherAbi,
})
/**
* Wraps __{@link readContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"allocationManager"`
*/
export const readVetoableSlasherAllocationManager =
/*#__PURE__*/ createReadContract({
abi: vetoableSlasherAbi,
functionName: 'allocationManager',
})
/**
* Wraps __{@link readContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"nextRequestId"`
*/
export const readVetoableSlasherNextRequestId =
/*#__PURE__*/ createReadContract({
abi: vetoableSlasherAbi,
functionName: 'nextRequestId',
})
/**
* Wraps __{@link readContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"serviceManager"`
*/
export const readVetoableSlasherServiceManager =
/*#__PURE__*/ createReadContract({
abi: vetoableSlasherAbi,
functionName: 'serviceManager',
})
/**
* Wraps __{@link readContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"slasher"`
*/
export const readVetoableSlasherSlasher = /*#__PURE__*/ createReadContract({
abi: vetoableSlasherAbi,
functionName: 'slasher',
})
/**
* Wraps __{@link readContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"slashingRequests"`
*/
export const readVetoableSlasherSlashingRequests =
/*#__PURE__*/ createReadContract({
abi: vetoableSlasherAbi,
functionName: 'slashingRequests',
})
/**
* Wraps __{@link readContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"vetoCommittee"`
*/
export const readVetoableSlasherVetoCommittee =
/*#__PURE__*/ createReadContract({
abi: vetoableSlasherAbi,
functionName: 'vetoCommittee',
})
/**
* Wraps __{@link readContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"vetoWindowBlocks"`
*/
export const readVetoableSlasherVetoWindowBlocks =
/*#__PURE__*/ createReadContract({
abi: vetoableSlasherAbi,
functionName: 'vetoWindowBlocks',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link vetoableSlasherAbi}__
*/
export const writeVetoableSlasher = /*#__PURE__*/ createWriteContract({
abi: vetoableSlasherAbi,
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"cancelSlashingRequest"`
*/
export const writeVetoableSlasherCancelSlashingRequest =
/*#__PURE__*/ createWriteContract({
abi: vetoableSlasherAbi,
functionName: 'cancelSlashingRequest',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"fulfilSlashingRequest"`
*/
export const writeVetoableSlasherFulfilSlashingRequest =
/*#__PURE__*/ createWriteContract({
abi: vetoableSlasherAbi,
functionName: 'fulfilSlashingRequest',
})
/**
* Wraps __{@link writeContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"queueSlashingRequest"`
*/
export const writeVetoableSlasherQueueSlashingRequest =
/*#__PURE__*/ createWriteContract({
abi: vetoableSlasherAbi,
functionName: 'queueSlashingRequest',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link vetoableSlasherAbi}__
*/
export const simulateVetoableSlasher = /*#__PURE__*/ createSimulateContract({
abi: vetoableSlasherAbi,
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"cancelSlashingRequest"`
*/
export const simulateVetoableSlasherCancelSlashingRequest =
/*#__PURE__*/ createSimulateContract({
abi: vetoableSlasherAbi,
functionName: 'cancelSlashingRequest',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"fulfilSlashingRequest"`
*/
export const simulateVetoableSlasherFulfilSlashingRequest =
/*#__PURE__*/ createSimulateContract({
abi: vetoableSlasherAbi,
functionName: 'fulfilSlashingRequest',
})
/**
* Wraps __{@link simulateContract}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `functionName` set to `"queueSlashingRequest"`
*/
export const simulateVetoableSlasherQueueSlashingRequest =
/*#__PURE__*/ createSimulateContract({
abi: vetoableSlasherAbi,
functionName: 'queueSlashingRequest',
})
/**
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link vetoableSlasherAbi}__
*/
export const watchVetoableSlasherEvent = /*#__PURE__*/ createWatchContractEvent(
{ abi: vetoableSlasherAbi },
)
/**
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `eventName` set to `"OperatorSlashed"`
*/
export const watchVetoableSlasherOperatorSlashedEvent =
/*#__PURE__*/ createWatchContractEvent({
abi: vetoableSlasherAbi,
eventName: 'OperatorSlashed',
})
/**
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `eventName` set to `"SlashingRequestCancelled"`
*/
export const watchVetoableSlasherSlashingRequestCancelledEvent =
/*#__PURE__*/ createWatchContractEvent({
abi: vetoableSlasherAbi,
eventName: 'SlashingRequestCancelled',
})
/**
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `eventName` set to `"SlashingRequestFulfilled"`
*/
export const watchVetoableSlasherSlashingRequestFulfilledEvent =
/*#__PURE__*/ createWatchContractEvent({
abi: vetoableSlasherAbi,
eventName: 'SlashingRequestFulfilled',
})
/**
* Wraps __{@link watchContractEvent}__ with `abi` set to __{@link vetoableSlasherAbi}__ and `eventName` set to `"SlashingRequested"`
*/
export const watchVetoableSlasherSlashingRequestedEvent =
/*#__PURE__*/ createWatchContractEvent({
abi: vetoableSlasherAbi,
eventName: 'SlashingRequested',
})

View file

@ -54,7 +54,6 @@ After the infrastructure is set up, we deploy all the necessary smart contracts
- **DataHaven Contracts**
- DataHavenServiceManager: Main contract for managing the DataHaven service
- RewardsRegistry: Handles validator rewards
- VetoableSlasher: Manages slashing with veto capabilities
### Initial Configuration
@ -208,7 +207,6 @@ Another testing scenario is testing the operational aspects of the validator set
3. **Slashing Mechanisms**
- Test slashing for various offenses
- Verify VetoableSlasher functions correctly
- Test veto committee mechanisms
4. **Operator Set Modifications**

View file

@ -297,11 +297,10 @@ const emitOwnerTransactionCalldata = async (chain?: string) => {
const rewardsInfo = await parseRewardsInfoFile(chain);
const serviceManager = deployments.ServiceManager;
const vetoableSlasher = deployments.VetoableSlasher;
const rewardsRegistry = deployments.RewardsRegistry;
const rewardsAgent = rewardsInfo.RewardsAgent;
if (!serviceManager || !vetoableSlasher || !rewardsRegistry || !rewardsAgent) {
if (!serviceManager || !rewardsRegistry || !rewardsAgent) {
logger.warn("⚠️ Missing deployment artifacts; cannot produce multisig calldata.");
return;
}
@ -318,17 +317,6 @@ const emitOwnerTransactionCalldata = async (chain?: string) => {
args: [""]
})
},
{
label: "Set slasher",
description: "DataHavenServiceManager.setSlasher(address)",
to: serviceManager,
value: "0",
data: encodeFunctionData({
abi: dataHavenServiceManagerAbi,
functionName: "setSlasher",
args: [vetoableSlasher]
})
},
{
label: "Attach RewardsRegistry",
description: "DataHavenServiceManager.setRewardsRegistry(VALIDATORS_SET_ID, address)",

View file

@ -29,7 +29,6 @@ const DeploymentsSchema = z.object({
Gateway: ethAddressCustom,
ServiceManager: ethAddressCustom,
ServiceManagerImplementation: ethAddressCustom,
VetoableSlasher: ethAddressCustom,
RewardsRegistry: ethAddressCustom,
RewardsAgent: ethAddressCustom,
DelegationManager: ethAddressCustom,
@ -99,7 +98,6 @@ const abiMap = {
Gateway: generated.gatewayAbi,
ServiceManager: generated.dataHavenServiceManagerAbi,
ServiceManagerImplementation: generated.dataHavenServiceManagerAbi,
VetoableSlasher: generated.vetoableSlasherAbi,
RewardsRegistry: generated.rewardsRegistryAbi,
RewardsAgent: generated.agentAbi,
DelegationManager: generated.delegationManagerAbi,

View file

@ -12,7 +12,6 @@ export default defineConfig({
"AgentExecutor.sol/**",
"Gateway.sol/**",
"TransparentUpgradeableProxy.sol/**",
"VetoableSlasher.sol/**",
"RewardsRegistry.sol/**",
"Agent.sol/**",
"StrategyManager.sol/**",