diff --git a/CLAUDE.md b/CLAUDE.md index e4776637..19e6e5ef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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`) diff --git a/README.md b/README.md index 264cb027..916be9e7 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/contracts/README.md b/contracts/README.md index 98e37ecf..9a737048 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -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. diff --git a/contracts/deployments/anvil-rewards-info.json b/contracts/deployments/anvil-rewards-info.json index f0457513..7ae4285e 100644 --- a/contracts/deployments/anvil-rewards-info.json +++ b/contracts/deployments/anvil-rewards-info.json @@ -1,5 +1 @@ -{ - "RewardsAgent": "0xac06641381166cf085281c45292147f833C622d7", - "RewardsAgentOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000", - "updateRewardsMerkleRootSelector": "0xdc3d04ec" -} \ No newline at end of file +{"RewardsAgent": "0xac06641381166cf085281c45292147f833C622d7","RewardsAgentOrigin": "0x0000000000000000000000000000000000000000000000000000000000000000","updateRewardsMerkleRootSelector": "0xdc3d04ec"} \ No newline at end of file diff --git a/contracts/deployments/anvil.json b/contracts/deployments/anvil.json index 575263a5..3cce64e8 100644 --- a/contracts/deployments/anvil.json +++ b/contracts/deployments/anvil.json @@ -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" - } - ] -} \ No newline at end of file +{"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"}]} \ No newline at end of file diff --git a/contracts/script/deploy/DeployBase.s.sol b/contracts/script/deploy/DeployBase.s.sol index 664b62ff..df441b2e 100644 --- a/contracts/script/deploy/DeployBase.s.sol +++ b/contracts/script/deploy/DeployBase.s.sol @@ -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; diff --git a/contracts/script/deploy/DeployLocal.s.sol b/contracts/script/deploy/DeployLocal.s.sol index 0c6c7066..755412a3 100644 --- a/contracts/script/deploy/DeployLocal.s.sol +++ b/contracts/script/deploy/DeployLocal.s.sol @@ -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)), '",' ); diff --git a/contracts/script/deploy/DeployTestnet.s.sol b/contracts/script/deploy/DeployTestnet.s.sol index d1ec6c45..037af8fc 100644 --- a/contracts/script/deploy/DeployTestnet.s.sol +++ b/contracts/script/deploy/DeployTestnet.s.sol @@ -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)), '",' ); diff --git a/contracts/script/utils/DHScriptStorage.s.sol b/contracts/script/utils/DHScriptStorage.s.sol index 3e6b8c34..ee2a1932 100644 --- a/contracts/script/utils/DHScriptStorage.s.sol +++ b/contracts/script/utils/DHScriptStorage.s.sol @@ -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"))); } diff --git a/contracts/src/interfaces/IDataHavenServiceManager.sol b/contracts/src/interfaces/IDataHavenServiceManager.sol index 89b663cc..07d8c20c 100644 --- a/contracts/src/interfaces/IDataHavenServiceManager.sol +++ b/contracts/src/interfaces/IDataHavenServiceManager.sol @@ -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"; /** diff --git a/contracts/src/interfaces/ISlasher.sol b/contracts/src/interfaces/ISlasher.sol deleted file mode 100644 index 777e348b..00000000 --- a/contracts/src/interfaces/ISlasher.sol +++ /dev/null @@ -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); -} diff --git a/contracts/src/interfaces/IVetoableSlasher.sol b/contracts/src/interfaces/IVetoableSlasher.sol deleted file mode 100644 index a1afb16f..00000000 --- a/contracts/src/interfaces/IVetoableSlasher.sol +++ /dev/null @@ -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; -} diff --git a/contracts/src/middleware/ServiceManagerBase.sol b/contracts/src/middleware/ServiceManagerBase.sol index b0117571..192c1456 100644 --- a/contracts/src/middleware/ServiceManagerBase.sol +++ b/contracts/src/middleware/ServiceManagerBase.sol @@ -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. diff --git a/contracts/src/middleware/ServiceManagerBaseStorage.sol b/contracts/src/middleware/ServiceManagerBaseStorage.sol index b13c13b0..a504075a 100644 --- a/contracts/src/middleware/ServiceManagerBaseStorage.sol +++ b/contracts/src/middleware/ServiceManagerBaseStorage.sol @@ -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; diff --git a/contracts/src/middleware/SlasherBase.sol b/contracts/src/middleware/SlasherBase.sol deleted file mode 100644 index 1e060fb4..00000000 --- a/contracts/src/middleware/SlasherBase.sol +++ /dev/null @@ -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); - } -} diff --git a/contracts/src/middleware/SlasherBaseStorage.sol b/contracts/src/middleware/SlasherBaseStorage.sol deleted file mode 100644 index 4b0ea029..00000000 --- a/contracts/src/middleware/SlasherBaseStorage.sol +++ /dev/null @@ -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; -} diff --git a/contracts/src/middleware/VetoableSlasher.sol b/contracts/src/middleware/VetoableSlasher.sol deleted file mode 100644 index ce992c4a..00000000 --- a/contracts/src/middleware/VetoableSlasher.sol +++ /dev/null @@ -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()); - } -} diff --git a/contracts/test/SlasherBase.t.sol b/contracts/test/SlasherBase.t.sol deleted file mode 100644 index 51c3fa33..00000000 --- a/contracts/test/SlasherBase.t.sol +++ /dev/null @@ -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); - } -} diff --git a/contracts/test/VetoableSlasher.t.sol b/contracts/test/VetoableSlasher.t.sol deleted file mode 100644 index 3bb20c44..00000000 --- a/contracts/test/VetoableSlasher.t.sol +++ /dev/null @@ -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); - } -} diff --git a/contracts/test/mocks/SlasherBaseMock.sol b/contracts/test/mocks/SlasherBaseMock.sol deleted file mode 100644 index 7ce6ec02..00000000 --- a/contracts/test/mocks/SlasherBaseMock.sol +++ /dev/null @@ -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); - } -} diff --git a/contracts/test/utils/AVSDeployer.sol b/contracts/test/utils/AVSDeployer.sol index b29b59d9..c5df92ca 100644 --- a/contracts/test/utils/AVSDeployer.sol +++ b/contracts/test/utils/AVSDeployer.sol @@ -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 diff --git a/test/README.md b/test/README.md index 8a6750b0..6f3ff3b1 100644 --- a/test/README.md +++ b/test/README.md @@ -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)` diff --git a/test/cli/handlers/contracts/README.md b/test/cli/handlers/contracts/README.md index a961a3a7..08307513 100644 --- a/test/cli/handlers/contracts/README.md +++ b/test/cli/handlers/contracts/README.md @@ -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) diff --git a/test/cli/handlers/contracts/status.ts b/test/cli/handlers/contracts/status.ts index c984ec6f..52cd1159 100644 --- a/test/cli/handlers/contracts/status.ts +++ b/test/cli/handlers/contracts/status.ts @@ -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" }, diff --git a/test/cli/handlers/contracts/verify.ts b/test/cli/handlers/contracts/verify.ts index 68cf363c..18f6fc5c 100644 --- a/test/cli/handlers/contracts/verify.ts +++ b/test/cli/handlers/contracts/verify.ts @@ -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, diff --git a/test/contract-bindings/generated.ts b/test/contract-bindings/generated.ts index 50c57c14..5f0ee8b8 100644 --- a/test/contract-bindings/generated.ts +++ b/test/contract-bindings/generated.ts @@ -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', - }) diff --git a/test/resources/datahaven-integration-test-flow.md b/test/resources/datahaven-integration-test-flow.md index 191bb8bb..82b2a7f6 100644 --- a/test/resources/datahaven-integration-test-flow.md +++ b/test/resources/datahaven-integration-test-flow.md @@ -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** diff --git a/test/scripts/deploy-contracts.ts b/test/scripts/deploy-contracts.ts index a6eaf734..e6e7bcb4 100644 --- a/test/scripts/deploy-contracts.ts +++ b/test/scripts/deploy-contracts.ts @@ -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)", diff --git a/test/utils/contracts.ts b/test/utils/contracts.ts index 1301472e..3433e718 100644 --- a/test/utils/contracts.ts +++ b/test/utils/contracts.ts @@ -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, diff --git a/test/wagmi.config.ts b/test/wagmi.config.ts index 134f8656..d2520010 100644 --- a/test/wagmi.config.ts +++ b/test/wagmi.config.ts @@ -12,7 +12,6 @@ export default defineConfig({ "AgentExecutor.sol/**", "Gateway.sol/**", "TransparentUpgradeableProxy.sol/**", - "VetoableSlasher.sol/**", "RewardsRegistry.sol/**", "Agent.sol/**", "StrategyManager.sol/**",