mirror of
https://github.com/datahaven-xyz/datahaven
synced 2026-05-24 09:50:01 +00:00
feat: ✨ Relay Validators operator set through Snowbridge (#39)
In this PR:
1. Implement application-specific functionalities in the
`DataHavenServiceManager` contract:
1. Registering of 3 operator sets: Validators, BSPs and MSPs.
2. Allowlisted sign up of operators.
3. Integration with Snowbridge to send message of new validator set.
2. Basic testing of the above functionalities.
3. Tests now use less mocked contracts (especially from EigenLayer).
4. Refactor of `SignUpOperator` script, which now supports the three
kinds of Operator sets.
This commit is contained in:
parent
f8fadebc1b
commit
5baa789f52
23 changed files with 1381 additions and 191 deletions
|
|
@ -29,7 +29,10 @@
|
|||
"avsOwner": "0x976EA74026E726554dB657fA54763abd0C3a0aa9",
|
||||
"rewardsInitiator": "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955",
|
||||
"vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f",
|
||||
"vetoWindowBlocks": 100
|
||||
"vetoWindowBlocks": 100,
|
||||
"validatorsStrategies": [],
|
||||
"bspsStrategies": [],
|
||||
"mspsStrategies": []
|
||||
},
|
||||
|
||||
"snowbridge": {
|
||||
|
|
|
|||
|
|
@ -73,7 +73,13 @@
|
|||
/// The address of the account that is a member of the Veto Committee for vetoing slashing.
|
||||
"vetoCommitteeMember": "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f",
|
||||
/// The number of blocks that the Veto Committee will have to submit a veto.
|
||||
"vetoWindowBlocks": 100
|
||||
"vetoWindowBlocks": 100,
|
||||
/// The EigenLayer strategy addresses for the Validators to stake into.
|
||||
"validatorsStrategies": [],
|
||||
/// The EigenLayer strategy addresses for the Backup Storage Providers to stake into.
|
||||
"bspsStrategies": [],
|
||||
/// The EigenLayer strategy addresses for the Main Storage Providers to stake into.
|
||||
"mspsStrategies": []
|
||||
},
|
||||
|
||||
"snowbridge": {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@ contract Config {
|
|||
address rewardsInitiator;
|
||||
address vetoCommitteeMember;
|
||||
uint32 vetoWindowBlocks;
|
||||
address[] validatorsStrategies;
|
||||
address[] bspsStrategies;
|
||||
address[] mspsStrategies;
|
||||
}
|
||||
|
||||
// EigenLayer parameters
|
||||
|
|
|
|||
|
|
@ -58,6 +58,15 @@ import {MerkleUtils} from "../../src/libraries/MerkleUtils.sol";
|
|||
import {VetoableSlasher} from "../../src/middleware/VetoableSlasher.sol";
|
||||
import {RewardsRegistry} from "../../src/middleware/RewardsRegistry.sol";
|
||||
|
||||
struct ServiceManagerInitParams {
|
||||
address avsOwner;
|
||||
address rewardsInitiator;
|
||||
address[] validatorsStrategies;
|
||||
address[] bspsStrategies;
|
||||
address[] mspsStrategies;
|
||||
address gateway;
|
||||
}
|
||||
|
||||
contract Deploy is Script, DeployParams, Accounts {
|
||||
// Progress indicator
|
||||
uint16 public deploymentStep = 0;
|
||||
|
|
@ -146,7 +155,7 @@ contract Deploy is Script, DeployParams, Accounts {
|
|||
_deployImplementations(eigenLayerConfig, pauserRegistry);
|
||||
Logging.logStep("Implementation contracts deployed successfully");
|
||||
|
||||
// Upgrade proxies to point to implementations and initialize
|
||||
// Upgrade proxies to point to implementations and initialise
|
||||
Logging.logSection("Initializing Contracts");
|
||||
_upgradeAndInitializeProxies(eigenLayerConfig, proxyAdmin);
|
||||
Logging.logStep("Proxies upgraded and initialized successfully");
|
||||
|
|
@ -166,86 +175,6 @@ contract Deploy is Script, DeployParams, Accounts {
|
|||
Logging.logFooter();
|
||||
_logProgress();
|
||||
|
||||
// Deploy DataHaven custom contracts
|
||||
Logging.logHeader("DATAHAVEN CUSTOM CONTRACTS DEPLOYMENT");
|
||||
|
||||
// Deploy the Service Manager
|
||||
vm.broadcast(_deployerPrivateKey);
|
||||
DataHavenServiceManager serviceManagerImplementation =
|
||||
new DataHavenServiceManager(rewardsCoordinator, permissionController, allocationManager);
|
||||
Logging.logContractDeployed(
|
||||
"ServiceManager Implementation", address(serviceManagerImplementation)
|
||||
);
|
||||
|
||||
vm.broadcast(_deployerPrivateKey);
|
||||
DataHavenServiceManager serviceManager = DataHavenServiceManager(
|
||||
address(
|
||||
new TransparentUpgradeableProxy(
|
||||
address(serviceManagerImplementation),
|
||||
address(proxyAdmin),
|
||||
abi.encodeWithSelector(
|
||||
DataHavenServiceManager.initialize.selector,
|
||||
avsConfig.avsOwner,
|
||||
avsConfig.rewardsInitiator
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
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(
|
||||
address(serviceManager),
|
||||
address(0) // Will be set to the Agent address after creation
|
||||
);
|
||||
Logging.logContractDeployed("RewardsRegistry", address(rewardsRegistry));
|
||||
|
||||
Logging.logSection("Configuring Service Manager");
|
||||
|
||||
// Register the DataHaven service in the AllocationManager
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.updateAVSMetadataURI("");
|
||||
Logging.logStep("DataHaven service registered in AllocationManager");
|
||||
|
||||
// Set the slasher in the ServiceManager
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.setSlasher(vetoableSlasher);
|
||||
Logging.logStep("Slasher set in ServiceManager");
|
||||
|
||||
// Set the RewardsRegistry in the ServiceManager
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.setRewardsRegistry(0, rewardsRegistry);
|
||||
Logging.logStep("RewardsRegistry set in ServiceManager");
|
||||
|
||||
// Create an operator set in the DataHaven service
|
||||
IAllocationManagerTypes.CreateSetParams[] memory operatorSetParams =
|
||||
new IAllocationManagerTypes.CreateSetParams[](1);
|
||||
IStrategy[] memory strategies = new IStrategy[](deployedStrategies.length);
|
||||
for (uint256 i = 0; i < deployedStrategies.length; i++) {
|
||||
strategies[i] = IStrategy(deployedStrategies[i]);
|
||||
}
|
||||
operatorSetParams[0] =
|
||||
IAllocationManagerTypes.CreateSetParams({operatorSetId: 0, strategies: strategies});
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.createOperatorSets(operatorSetParams);
|
||||
Logging.logStep(
|
||||
"Operator set created in DataHaven service with all the deployed strategies"
|
||||
);
|
||||
|
||||
Logging.logFooter();
|
||||
_logProgress();
|
||||
|
||||
// Deploy Snowbridge and configure Agent
|
||||
Logging.logHeader("SNOWBRIDGE DEPLOYMENT");
|
||||
|
||||
|
|
@ -259,6 +188,16 @@ contract Deploy is Script, DeployParams, Accounts {
|
|||
Logging.logFooter();
|
||||
_logProgress();
|
||||
|
||||
// Deploy DataHaven custom contracts
|
||||
(
|
||||
DataHavenServiceManager serviceManager,
|
||||
VetoableSlasher vetoableSlasher,
|
||||
RewardsRegistry rewardsRegistry
|
||||
) = _deployDataHavenContracts(avsConfig, proxyAdmin, gateway);
|
||||
|
||||
Logging.logFooter();
|
||||
_logProgress();
|
||||
|
||||
// Set the Agent in the RewardsRegistry
|
||||
Logging.logHeader("FINAL CONFIGURATION");
|
||||
// This needs to be executed by the AVS owner
|
||||
|
|
@ -778,4 +717,114 @@ contract Deploy is Script, DeployParams, Accounts {
|
|||
vm.writeFile(deploymentPath, json);
|
||||
Logging.logInfo(string.concat("Deployment info saved to: ", deploymentPath));
|
||||
}
|
||||
|
||||
function _deployDataHavenContracts(
|
||||
AVSConfig memory avsConfig,
|
||||
ProxyAdmin proxyAdmin,
|
||||
IGatewayV2 gateway
|
||||
) internal returns (DataHavenServiceManager, VetoableSlasher, RewardsRegistry) {
|
||||
Logging.logHeader("DATAHAVEN CUSTOM CONTRACTS DEPLOYMENT");
|
||||
|
||||
// Deploy the Service Manager
|
||||
vm.broadcast(_deployerPrivateKey);
|
||||
DataHavenServiceManager serviceManagerImplementation =
|
||||
new DataHavenServiceManager(rewardsCoordinator, permissionController, allocationManager);
|
||||
Logging.logContractDeployed(
|
||||
"ServiceManager Implementation", address(serviceManagerImplementation)
|
||||
);
|
||||
|
||||
// Extract strategies logic to a helper function to reduce local variables
|
||||
_prepareStrategiesForServiceManager(avsConfig, deployedStrategies);
|
||||
|
||||
// Create service manager initialisation parameters struct to reduce stack variables
|
||||
ServiceManagerInitParams memory initParams = ServiceManagerInitParams({
|
||||
avsOwner: avsConfig.avsOwner,
|
||||
rewardsInitiator: avsConfig.rewardsInitiator,
|
||||
validatorsStrategies: avsConfig.validatorsStrategies,
|
||||
bspsStrategies: avsConfig.bspsStrategies,
|
||||
mspsStrategies: avsConfig.mspsStrategies,
|
||||
gateway: address(gateway)
|
||||
});
|
||||
|
||||
// Create the service manager proxy
|
||||
DataHavenServiceManager serviceManager =
|
||||
_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(
|
||||
address(serviceManager),
|
||||
address(0) // Will be set to the Agent address after creation
|
||||
);
|
||||
Logging.logContractDeployed("RewardsRegistry", address(rewardsRegistry));
|
||||
|
||||
Logging.logSection("Configuring Service Manager");
|
||||
|
||||
// Register the DataHaven service in the AllocationManager
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.updateAVSMetadataURI("");
|
||||
Logging.logStep("DataHaven service registered in AllocationManager");
|
||||
|
||||
// Set the slasher in the ServiceManager
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.setSlasher(vetoableSlasher);
|
||||
Logging.logStep("Slasher set in ServiceManager");
|
||||
|
||||
// Set the RewardsRegistry in the ServiceManager
|
||||
uint32 validatorsSetId = serviceManager.VALIDATORS_SET_ID();
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.setRewardsRegistry(validatorsSetId, rewardsRegistry);
|
||||
Logging.logStep("RewardsRegistry set in ServiceManager");
|
||||
|
||||
return (serviceManager, vetoableSlasher, rewardsRegistry);
|
||||
}
|
||||
|
||||
function _createServiceManagerProxy(
|
||||
DataHavenServiceManager implementation,
|
||||
ProxyAdmin proxyAdmin,
|
||||
ServiceManagerInitParams memory params
|
||||
) internal returns (DataHavenServiceManager) {
|
||||
vm.broadcast(_deployerPrivateKey);
|
||||
bytes memory initData = abi.encodeWithSelector(
|
||||
DataHavenServiceManager.initialise.selector,
|
||||
params.avsOwner,
|
||||
params.rewardsInitiator,
|
||||
params.validatorsStrategies,
|
||||
params.bspsStrategies,
|
||||
params.mspsStrategies,
|
||||
params.gateway
|
||||
);
|
||||
|
||||
TransparentUpgradeableProxy proxy =
|
||||
new TransparentUpgradeableProxy(address(implementation), address(proxyAdmin), initData);
|
||||
|
||||
return DataHavenServiceManager(address(proxy));
|
||||
}
|
||||
|
||||
function _prepareStrategiesForServiceManager(
|
||||
AVSConfig memory config,
|
||||
StrategyBaseTVLLimits[] memory strategies
|
||||
) internal pure {
|
||||
if (config.validatorsStrategies.length == 0) {
|
||||
config.validatorsStrategies = new address[](strategies.length);
|
||||
config.bspsStrategies = new address[](strategies.length);
|
||||
config.mspsStrategies = new address[](strategies.length);
|
||||
for (uint256 i = 0; i < strategies.length; i++) {
|
||||
config.validatorsStrategies[i] = address(strategies[i]);
|
||||
config.bspsStrategies[i] = address(strategies[i]);
|
||||
config.mspsStrategies[i] = address(strategies[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,10 @@ contract DeployParams is Script, Config {
|
|||
config.rewardsInitiator = vm.parseJsonAddress(configJson, ".avs.rewardsInitiator");
|
||||
config.vetoCommitteeMember = vm.parseJsonAddress(configJson, ".avs.vetoCommitteeMember");
|
||||
config.vetoWindowBlocks = uint32(vm.parseJsonUint(configJson, ".avs.vetoWindowBlocks"));
|
||||
config.validatorsStrategies =
|
||||
vm.parseJsonAddressArray(configJson, ".avs.validatorsStrategies");
|
||||
config.bspsStrategies = vm.parseJsonAddressArray(configJson, ".avs.bspsStrategies");
|
||||
config.mspsStrategies = vm.parseJsonAddressArray(configJson, ".avs.mspsStrategies");
|
||||
|
||||
return config;
|
||||
}
|
||||
|
|
|
|||
33
contracts/script/transact/SignUpBsp.s.sol
Normal file
33
contracts/script/transact/SignUpBsp.s.sol
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
import {SignUpOperatorBase} from "./SignUpOperatorBase.s.sol";
|
||||
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
|
||||
|
||||
/**
|
||||
* @title SignUpBsp
|
||||
* @notice Script to sign up a backup storage provider (BSP) for the DataHaven network
|
||||
*/
|
||||
contract SignUpBsp is SignUpOperatorBase {
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorSetId() internal view override returns (uint32) {
|
||||
return serviceManager.BSPS_SET_ID();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _addToAllowlist() internal override {
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.addBspToAllowlist(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorTypeName() internal pure override returns (string memory) {
|
||||
return "BSP";
|
||||
}
|
||||
}
|
||||
33
contracts/script/transact/SignUpMsp.s.sol
Normal file
33
contracts/script/transact/SignUpMsp.s.sol
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
import {SignUpOperatorBase} from "./SignUpOperatorBase.s.sol";
|
||||
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
|
||||
|
||||
/**
|
||||
* @title SignUpMsp
|
||||
* @notice Script to sign up a main storage provider (MSP) for the DataHaven network
|
||||
*/
|
||||
contract SignUpMsp is SignUpOperatorBase {
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorSetId() internal view override returns (uint32) {
|
||||
return serviceManager.MSPS_SET_ID();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _addToAllowlist() internal override {
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.addMspToAllowlist(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorTypeName() internal pure override returns (string memory) {
|
||||
return "MSP";
|
||||
}
|
||||
}
|
||||
164
contracts/script/transact/SignUpOperatorBase.s.sol
Normal file
164
contracts/script/transact/SignUpOperatorBase.s.sol
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
// EigenLayer imports
|
||||
import {IAllocationManagerTypes} from
|
||||
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
import {StrategyBase} from "eigenlayer-contracts/src/contracts/strategies/StrategyBase.sol";
|
||||
|
||||
// OpenZeppelin imports
|
||||
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
// Testing imports
|
||||
import {Script} from "forge-std/Script.sol";
|
||||
import {console} from "forge-std/console.sol";
|
||||
import {Logging} from "../utils/Logging.sol";
|
||||
import {ELScriptStorage} from "../utils/ELScriptStorage.s.sol";
|
||||
import {DHScriptStorage} from "../utils/DHScriptStorage.s.sol";
|
||||
import {Accounts} from "../utils/Accounts.sol";
|
||||
|
||||
/**
|
||||
* @title SignUpOperatorBase
|
||||
* @notice Base contract for signing up different types of operators (Validators, BSPs, MSPs)
|
||||
*/
|
||||
abstract contract SignUpOperatorBase is Script, ELScriptStorage, DHScriptStorage, Accounts {
|
||||
// Progress indicator
|
||||
uint16 public deploymentStep = 0;
|
||||
uint16 public totalSteps = 3; // Total major steps
|
||||
|
||||
function _logProgress() internal {
|
||||
deploymentStep++;
|
||||
Logging.logProgress(deploymentStep, totalSteps);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Abstract method to be implemented by derived contracts to get the operator set ID
|
||||
* @return The operator set ID for the specific type (Validator, BSP, MSP)
|
||||
*/
|
||||
function _getOperatorSetId() internal view virtual returns (uint32);
|
||||
|
||||
/**
|
||||
* @notice Abstract method to be implemented by derived contracts to add operator to allowlist
|
||||
*/
|
||||
function _addToAllowlist() internal virtual;
|
||||
|
||||
/**
|
||||
* @notice Abstract method to get the operator type name (for logging)
|
||||
* @return The name of the operator type
|
||||
*/
|
||||
function _getOperatorTypeName() internal view virtual returns (string memory);
|
||||
|
||||
function run() public {
|
||||
string memory network = vm.envOr("NETWORK", string("anvil"));
|
||||
Logging.logHeader(string.concat("SIGN UP DATAHAVEN ", _getOperatorTypeName()));
|
||||
console.log("| Network: %s", network);
|
||||
console.log("| Timestamp: %s", vm.toString(block.timestamp));
|
||||
Logging.logFooter();
|
||||
|
||||
// Read addresses of latest deployment of EigenLayer contracts, for the given network.
|
||||
_loadELContracts(network);
|
||||
Logging.logInfo(string.concat("Loaded EigenLayer contracts for network: ", network));
|
||||
|
||||
// Read addresses of latest deployment of DataHaven contracts, for the given network.
|
||||
_loadDHContracts(network);
|
||||
Logging.logInfo(string.concat("Loaded DataHaven contracts for network: ", network));
|
||||
|
||||
_logProgress();
|
||||
|
||||
// STEP 1: Stake tokens into strategies
|
||||
Logging.logSection("Staking Tokens into Strategies");
|
||||
|
||||
// Get the deployed strategies and deposit some of the operator's balance into them.
|
||||
for (uint256 i = 0; i < deployedStrategies.length; i++) {
|
||||
IERC20 linkedToken = StrategyBase(deployedStrategies[i]).underlyingToken();
|
||||
|
||||
// Check that the operator has a balance of the linked token.
|
||||
uint256 balance = linkedToken.balanceOf(_operator);
|
||||
Logging.logInfo(
|
||||
string.concat(
|
||||
"Strategy ",
|
||||
vm.toString(i),
|
||||
" underlying token: ",
|
||||
vm.toString(address(linkedToken)),
|
||||
" - Operator balance: ",
|
||||
vm.toString(balance)
|
||||
)
|
||||
);
|
||||
|
||||
require(balance > 0, "Operator does not have a balance of the linked token");
|
||||
|
||||
// Stake some of the operator's balance as stake for the strategy.
|
||||
vm.startBroadcast(_operatorPrivateKey);
|
||||
uint256 balanceToStake = balance / 10;
|
||||
linkedToken.approve(address(strategyManager), balanceToStake);
|
||||
strategyManager.depositIntoStrategy(deployedStrategies[i], linkedToken, balanceToStake);
|
||||
vm.stopBroadcast();
|
||||
|
||||
Logging.logStep(
|
||||
string.concat(
|
||||
"Staked ", vm.toString(balanceToStake), " tokens for strategy ", vm.toString(i)
|
||||
)
|
||||
);
|
||||
}
|
||||
_logProgress();
|
||||
|
||||
// STEP 2: Register as an operator in EigenLayer
|
||||
Logging.logSection("Registering as EigenLayer Operator");
|
||||
|
||||
// Register the operator as an operator.
|
||||
// We don't set a delegation approver, so that there is no need to sign any messages.
|
||||
address initDelegationApprover = address(0);
|
||||
uint32 allocationDelay = 0;
|
||||
string memory metadataURI = "";
|
||||
vm.broadcast(_operatorPrivateKey);
|
||||
delegation.registerAsOperator(initDelegationApprover, allocationDelay, metadataURI);
|
||||
Logging.logStep(
|
||||
string.concat("Registered operator in EigenLayer: ", vm.toString(_operator))
|
||||
);
|
||||
|
||||
// Check the staked balance of the operator.
|
||||
Logging.logSection("Operator Shares Information");
|
||||
for (uint256 i = 0; i < deployedStrategies.length; i++) {
|
||||
uint256 operatorShares = delegation.operatorShares(_operator, deployedStrategies[i]);
|
||||
Logging.logInfo(
|
||||
string.concat(
|
||||
"Operator shares for strategy ",
|
||||
vm.toString(i),
|
||||
": ",
|
||||
vm.toString(operatorShares)
|
||||
)
|
||||
);
|
||||
}
|
||||
_logProgress();
|
||||
|
||||
// STEP 3: Register as a DataHaven operator of specific type
|
||||
Logging.logSection(string.concat("Registering as DataHaven ", _getOperatorTypeName()));
|
||||
|
||||
// Add the operator to the appropriate allowlist of the DataHaven service.
|
||||
_addToAllowlist();
|
||||
Logging.logStep(
|
||||
string.concat(
|
||||
"Added operator to ", _getOperatorTypeName(), " allowlist of DataHaven service"
|
||||
)
|
||||
);
|
||||
|
||||
// Register the operator as operator for the DataHaven service.
|
||||
uint32[] memory operatorSetIds = new uint32[](1);
|
||||
operatorSetIds[0] = _getOperatorSetId();
|
||||
IAllocationManagerTypes.RegisterParams memory registerParams = IAllocationManagerTypes
|
||||
.RegisterParams({avs: address(serviceManager), operatorSetIds: operatorSetIds, data: ""});
|
||||
|
||||
vm.broadcast(_operatorPrivateKey);
|
||||
allocationManager.registerForOperatorSets(_operator, registerParams);
|
||||
Logging.logStep(
|
||||
string.concat("Registered ", _getOperatorTypeName(), " in DataHaven service")
|
||||
);
|
||||
|
||||
Logging.logHeader("OPERATOR SETUP COMPLETE");
|
||||
Logging.logInfo(string.concat(_getOperatorTypeName(), ": ", vm.toString(_operator)));
|
||||
Logging.logInfo(
|
||||
string.concat("Successfully configured ", _getOperatorTypeName(), " for DataHaven")
|
||||
);
|
||||
Logging.logFooter();
|
||||
}
|
||||
}
|
||||
33
contracts/script/transact/SignUpValidator.s.sol
Normal file
33
contracts/script/transact/SignUpValidator.s.sol
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
import {SignUpOperatorBase} from "./SignUpOperatorBase.s.sol";
|
||||
import {DataHavenServiceManager} from "../../src/DataHavenServiceManager.sol";
|
||||
|
||||
/**
|
||||
* @title SignUpValidator
|
||||
* @notice Script to sign up a validator for the DataHaven network
|
||||
*/
|
||||
contract SignUpValidator is SignUpOperatorBase {
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorSetId() internal view override returns (uint32) {
|
||||
return serviceManager.VALIDATORS_SET_ID();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _addToAllowlist() internal override {
|
||||
vm.broadcast(_avsOwnerPrivateKey);
|
||||
serviceManager.addValidatorToAllowlist(_operator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc SignUpOperatorBase
|
||||
*/
|
||||
function _getOperatorTypeName() internal pure override returns (string memory) {
|
||||
return "VALIDATOR";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +1,55 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
import {IRewardsCoordinator} from
|
||||
"eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
|
||||
// EigenLayer imports
|
||||
import {
|
||||
IAllocationManager,
|
||||
IAllocationManagerTypes
|
||||
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
import {IAVSRegistrar} from "eigenlayer-contracts/src/contracts/interfaces/IAVSRegistrar.sol";
|
||||
import {IPermissionController} from
|
||||
"eigenlayer-contracts/src/contracts/interfaces/IPermissionController.sol";
|
||||
import {IAllocationManager} from
|
||||
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
import {IRewardsCoordinator} from
|
||||
"eigenlayer-contracts/src/contracts/interfaces/IRewardsCoordinator.sol";
|
||||
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
|
||||
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
|
||||
|
||||
// Snowbridge imports
|
||||
import {IGatewayV2} from "snowbridge/src/v2/IGateway.sol";
|
||||
import {ScaleCodec} from "snowbridge/src/utils/ScaleCodec.sol";
|
||||
|
||||
// DataHaven imports
|
||||
import {DataHavenSnowbridgeMessages} from "./libraries/DataHavenSnowbridgeMessages.sol";
|
||||
import {IDataHavenServiceManager} from "./interfaces/IDataHavenServiceManager.sol";
|
||||
import {ServiceManagerBase} from "./middleware/ServiceManagerBase.sol";
|
||||
|
||||
/**
|
||||
* @title DataHaven ServiceManager contract.
|
||||
* TODO: For now, it uses the ServiceManagerBase contract as is.
|
||||
* TODO: We should add the DataHaven specific logic here.
|
||||
* @title DataHaven ServiceManager contract
|
||||
* @notice Manages validators, backup storage providers (BSPs), and main storage providers (MSPs)
|
||||
* in the DataHaven network
|
||||
*/
|
||||
contract DataHavenServiceManager is ServiceManagerBase {
|
||||
uint256 public number;
|
||||
contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager {
|
||||
/// @notice The metadata for the DataHaven AVS.
|
||||
string public constant DATAHAVEN_AVS_METADATA = "https://datahaven.network/";
|
||||
|
||||
/// @notice The EigenLayer operator set ID for the Validators securing the DataHaven network.
|
||||
uint32 public constant VALIDATORS_SET_ID = 0;
|
||||
/// @notice The EigenLayer operator set ID for the Backup Storage Providers participating in the DataHaven network.
|
||||
uint32 public constant BSPS_SET_ID = 1;
|
||||
/// @notice The EigenLayer operator set ID for the Main Storage Providers participating in the DataHaven network.
|
||||
uint32 public constant MSPS_SET_ID = 2;
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
mapping(address => bool) public validatorsAllowlist;
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
mapping(address => bool) public bspsAllowlist;
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
mapping(address => bool) public mspsAllowlist;
|
||||
|
||||
IGatewayV2 private _snowbridgeGateway;
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
mapping(address => bytes32) public validatorEthAddressToSolochainAddress;
|
||||
|
||||
/// @notice Sets the (immutable) `_registryCoordinator` address
|
||||
constructor(
|
||||
|
|
@ -25,23 +58,306 @@ contract DataHavenServiceManager is ServiceManagerBase {
|
|||
IAllocationManager __allocationManager
|
||||
) ServiceManagerBase(__rewardsCoordinator, __permissionController, __allocationManager) {}
|
||||
|
||||
function initialize(
|
||||
/// @notice Modifier to ensure the caller is a registered Validator
|
||||
modifier onlyValidator() {
|
||||
OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: VALIDATORS_SET_ID});
|
||||
require(
|
||||
_allocationManager.isMemberOfOperatorSet(msg.sender, operatorSet),
|
||||
CallerIsNotValidator()
|
||||
);
|
||||
_;
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function initialise(
|
||||
address initialOwner,
|
||||
address rewardsInitiator
|
||||
address rewardsInitiator,
|
||||
IStrategy[] memory validatorsStrategies,
|
||||
IStrategy[] memory bspsStrategies,
|
||||
IStrategy[] memory mspsStrategies,
|
||||
address _snowbridgeGatewayAddress
|
||||
) public virtual initializer {
|
||||
__ServiceManagerBase_init(initialOwner, rewardsInitiator);
|
||||
|
||||
// Register the DataHaven service in the AllocationManager.
|
||||
_allocationManager.updateAVSMetadataURI(address(this), DATAHAVEN_AVS_METADATA);
|
||||
|
||||
// Create the operator sets for the DataHaven service.
|
||||
_createDataHavenOperatorSets(validatorsStrategies, bspsStrategies, mspsStrategies);
|
||||
|
||||
// Set the Snowbridge Gateway address.
|
||||
// This is the contract to which messages are sent, to be relayed to the Solochain network.
|
||||
_snowbridgeGateway = IGatewayV2(_snowbridgeGatewayAddress);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function sendNewValidatorSet(
|
||||
uint128 executionFee,
|
||||
uint128 relayerFee
|
||||
) external payable onlyOwner {
|
||||
// Send the new validator set message to the Snowbridge Gateway
|
||||
bytes memory message = buildNewValidatorSetMessage();
|
||||
_snowbridgeGateway.v2_sendMessage{value: msg.value}(
|
||||
message,
|
||||
new bytes[](0), // No assets to send
|
||||
bytes(""), // No claimer
|
||||
executionFee,
|
||||
relayerFee
|
||||
);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function buildNewValidatorSetMessage() public view returns (bytes memory) {
|
||||
// Get the current validator set
|
||||
OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: VALIDATORS_SET_ID});
|
||||
address[] memory currentValidatorSet = _allocationManager.getMembers(operatorSet);
|
||||
|
||||
// Build the new validator set message
|
||||
bytes32[] memory newValidatorSet = new bytes32[](currentValidatorSet.length);
|
||||
for (uint256 i = 0; i < currentValidatorSet.length; i++) {
|
||||
newValidatorSet[i] = validatorEthAddressToSolochainAddress[currentValidatorSet[i]];
|
||||
}
|
||||
DataHavenSnowbridgeMessages.NewValidatorSetPayload memory newValidatorSetPayload =
|
||||
DataHavenSnowbridgeMessages.NewValidatorSetPayload({newValidatorSet: newValidatorSet});
|
||||
DataHavenSnowbridgeMessages.NewValidatorSet memory newValidatorSetMessage =
|
||||
DataHavenSnowbridgeMessages.NewValidatorSet({
|
||||
nonce: 0,
|
||||
topic: bytes32(0),
|
||||
payload: newValidatorSetPayload
|
||||
});
|
||||
|
||||
// Return the encoded message
|
||||
return DataHavenSnowbridgeMessages.scaleEncodeNewValidatorSetMessage(newValidatorSetMessage);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function updateSolochainAddressForValidator(
|
||||
bytes32 solochainAddress
|
||||
) external onlyValidator {
|
||||
// Update the Solochain address for the Validator
|
||||
validatorEthAddressToSolochainAddress[msg.sender] = solochainAddress;
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function setSnowbridgeGateway(
|
||||
address _newSnowbridgeGateway
|
||||
) external onlyOwner {
|
||||
_snowbridgeGateway = IGatewayV2(_newSnowbridgeGateway);
|
||||
emit SnowbridgeGatewaySet(_newSnowbridgeGateway);
|
||||
}
|
||||
|
||||
/// @inheritdoc IAVSRegistrar
|
||||
function registerOperator(
|
||||
address operator,
|
||||
address avs,
|
||||
uint32[] calldata operatorSetIds,
|
||||
bytes calldata data
|
||||
) external override {
|
||||
if (avs != address(this)) {
|
||||
revert IncorrectAVSAddress();
|
||||
}
|
||||
|
||||
if (operatorSetIds.length != 1) {
|
||||
revert CantRegisterToMultipleOperatorSets();
|
||||
}
|
||||
|
||||
// Case: Validator
|
||||
if (operatorSetIds[0] == VALIDATORS_SET_ID) {
|
||||
if (!validatorsAllowlist[operator]) {
|
||||
revert OperatorNotInAllowlist();
|
||||
}
|
||||
|
||||
// In the case of the Validators operator set, expect the data to have the Solochain address of the operator.
|
||||
// TODO: We should have some sort of validation of this address that validators are setting for themselves.
|
||||
validatorEthAddressToSolochainAddress[operator] = bytes32(data);
|
||||
}
|
||||
// Case: BSP
|
||||
else if (operatorSetIds[0] == BSPS_SET_ID) {
|
||||
if (!bspsAllowlist[operator]) {
|
||||
revert OperatorNotInAllowlist();
|
||||
}
|
||||
}
|
||||
// Case: MSP
|
||||
else if (operatorSetIds[0] == MSPS_SET_ID) {
|
||||
if (!mspsAllowlist[operator]) {
|
||||
revert OperatorNotInAllowlist();
|
||||
}
|
||||
}
|
||||
// Case: Invalid operator set ID
|
||||
else {
|
||||
revert InvalidOperatorSetId();
|
||||
}
|
||||
|
||||
emit OperatorRegistered(operator, operatorSetIds[0]);
|
||||
}
|
||||
|
||||
/// @inheritdoc IAVSRegistrar
|
||||
function deregisterOperator(
|
||||
address operator,
|
||||
address avs,
|
||||
uint32[] calldata operatorSetIds
|
||||
) external override {
|
||||
if (avs != address(this)) {
|
||||
revert IncorrectAVSAddress();
|
||||
}
|
||||
|
||||
if (operatorSetIds.length != 1) {
|
||||
revert CantDeregisterFromMultipleOperatorSets();
|
||||
}
|
||||
|
||||
if (
|
||||
operatorSetIds[0] != VALIDATORS_SET_ID && operatorSetIds[0] != BSPS_SET_ID
|
||||
&& operatorSetIds[0] != MSPS_SET_ID
|
||||
) {
|
||||
revert InvalidOperatorSetId();
|
||||
}
|
||||
|
||||
if (operatorSetIds[0] == VALIDATORS_SET_ID) {
|
||||
// Remove validator from the addresses mapping
|
||||
delete validatorEthAddressToSolochainAddress[operator];
|
||||
}
|
||||
|
||||
emit OperatorDeregistered(operator, operatorSetIds[0]);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addValidatorToAllowlist(
|
||||
address validator
|
||||
) external onlyOwner {
|
||||
validatorsAllowlist[validator] = true;
|
||||
emit ValidatorAddedToAllowlist(validator);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addBspToAllowlist(
|
||||
address bsp
|
||||
) external onlyOwner {
|
||||
bspsAllowlist[bsp] = true;
|
||||
emit BspAddedToAllowlist(bsp);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addMspToAllowlist(
|
||||
address msp
|
||||
) external onlyOwner {
|
||||
mspsAllowlist[msp] = true;
|
||||
emit MspAddedToAllowlist(msp);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeValidatorFromAllowlist(
|
||||
address validator
|
||||
) external onlyOwner {
|
||||
validatorsAllowlist[validator] = false;
|
||||
emit ValidatorRemovedFromAllowlist(validator);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeBspFromAllowlist(
|
||||
address bsp
|
||||
) external onlyOwner {
|
||||
bspsAllowlist[bsp] = false;
|
||||
emit BspRemovedFromAllowlist(bsp);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeMspFromAllowlist(
|
||||
address msp
|
||||
) external onlyOwner {
|
||||
mspsAllowlist[msp] = false;
|
||||
emit MspRemovedFromAllowlist(msp);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function validatorsSupportedStrategies() external view returns (IStrategy[] memory) {
|
||||
OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: VALIDATORS_SET_ID});
|
||||
return _allocationManager.getStrategiesInOperatorSet(operatorSet);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeStrategiesFromValidatorsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.removeStrategiesFromOperatorSet(
|
||||
address(this), VALIDATORS_SET_ID, _strategies
|
||||
);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addStrategiesToValidatorsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.addStrategiesToOperatorSet(address(this), VALIDATORS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function bspsSupportedStrategies() external view returns (IStrategy[] memory) {
|
||||
OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: BSPS_SET_ID});
|
||||
return _allocationManager.getStrategiesInOperatorSet(operatorSet);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeStrategiesFromBspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.removeStrategiesFromOperatorSet(address(this), BSPS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addStrategiesToBspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.addStrategiesToOperatorSet(address(this), BSPS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function mspsSupportedStrategies() external view returns (IStrategy[] memory) {
|
||||
OperatorSet memory operatorSet = OperatorSet({avs: address(this), id: MSPS_SET_ID});
|
||||
return _allocationManager.getStrategiesInOperatorSet(operatorSet);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function removeStrategiesFromMspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.removeStrategiesFromOperatorSet(address(this), MSPS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function addStrategiesToMspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external onlyOwner {
|
||||
_allocationManager.addStrategiesToOperatorSet(address(this), MSPS_SET_ID, _strategies);
|
||||
}
|
||||
|
||||
/// @inheritdoc IDataHavenServiceManager
|
||||
function snowbridgeGateway() external view returns (address) {
|
||||
return address(_snowbridgeGateway);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Override the internal _ensureOperatorIsPartOfOperatorSet function to simplify testing
|
||||
* @param operator The operator address
|
||||
* @param operatorSetId The operator set ID
|
||||
* @dev This should be removed once the AllocationManagerMock is updated to be able to handle operator sets
|
||||
* @notice Creates the initial operator sets for DataHaven in the AllocationManager.
|
||||
* @dev This function should be called during initialisation to set up the required operator sets.
|
||||
*/
|
||||
function _ensureOperatorIsPartOfOperatorSet(
|
||||
address operator,
|
||||
uint32 operatorSetId
|
||||
) internal view override {
|
||||
// No-op for testing
|
||||
function _createDataHavenOperatorSets(
|
||||
IStrategy[] memory validatorsStrategies,
|
||||
IStrategy[] memory bspsStrategies,
|
||||
IStrategy[] memory mspsStrategies
|
||||
) internal {
|
||||
IAllocationManagerTypes.CreateSetParams[] memory operatorSets =
|
||||
new IAllocationManagerTypes.CreateSetParams[](3);
|
||||
operatorSets[0] = IAllocationManagerTypes.CreateSetParams({
|
||||
operatorSetId: VALIDATORS_SET_ID,
|
||||
strategies: validatorsStrategies
|
||||
});
|
||||
operatorSets[1] = IAllocationManagerTypes.CreateSetParams({
|
||||
operatorSetId: BSPS_SET_ID,
|
||||
strategies: bspsStrategies
|
||||
});
|
||||
operatorSets[2] = IAllocationManagerTypes.CreateSetParams({
|
||||
operatorSetId: MSPS_SET_ID,
|
||||
strategies: mspsStrategies
|
||||
});
|
||||
_allocationManager.createOperatorSets(address(this), operatorSets);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
282
contracts/src/interfaces/IDataHavenServiceManager.sol
Normal file
282
contracts/src/interfaces/IDataHavenServiceManager.sol
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
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";
|
||||
|
||||
// Snowbridge imports
|
||||
import {IGatewayV2} from "snowbridge/src/v2/IGateway.sol";
|
||||
|
||||
/**
|
||||
* @title DataHaven Service Manager Errors Interface
|
||||
* @notice Contains all error definitions used by the DataHaven Service Manager
|
||||
*/
|
||||
interface IDataHavenServiceManagerErrors {
|
||||
/// @notice Thrown when an operator attempts to register with an incorrect AVS address
|
||||
error IncorrectAVSAddress();
|
||||
/// @notice Thrown when an operator attempts to register to multiple operator sets at once
|
||||
error CantRegisterToMultipleOperatorSets();
|
||||
/// @notice Thrown when an operator attempts to deregister from multiple operator sets at once
|
||||
error CantDeregisterFromMultipleOperatorSets();
|
||||
/// @notice Thrown when an invalid operator set ID is provided
|
||||
error InvalidOperatorSetId();
|
||||
/// @notice Thrown when an operator not in the appropriate allowlist attempts to register
|
||||
error OperatorNotInAllowlist();
|
||||
/// @notice Thrown when the caller is not a Validator in the Validators operator set
|
||||
error CallerIsNotValidator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @title DataHaven Service Manager Events Interface
|
||||
* @notice Contains all event definitions emitted by the DataHaven Service Manager
|
||||
*/
|
||||
interface IDataHavenServiceManagerEvents {
|
||||
/// @notice Emitted when an operator successfully registers to an operator set
|
||||
/// @param operator Address of the operator that registered
|
||||
/// @param operatorSetId ID of the operator set the operator registered to
|
||||
event OperatorRegistered(address indexed operator, uint32 indexed operatorSetId);
|
||||
|
||||
/// @notice Emitted when an operator deregisters from an operator set
|
||||
/// @param operator Address of the operator that deregistered
|
||||
/// @param operatorSetId ID of the operator set the operator deregistered from
|
||||
event OperatorDeregistered(address indexed operator, uint32 indexed operatorSetId);
|
||||
|
||||
/// @notice Emitted when a validator is added to the allowlist
|
||||
/// @param validator Address of the validator added to the allowlist
|
||||
event ValidatorAddedToAllowlist(address indexed validator);
|
||||
|
||||
/// @notice Emitted when a Backup Storage Provider is added to the allowlist
|
||||
/// @param bsp Address of the BSP added to the allowlist
|
||||
event BspAddedToAllowlist(address indexed bsp);
|
||||
|
||||
/// @notice Emitted when a Main Storage Provider is added to the allowlist
|
||||
/// @param msp Address of the MSP added to the allowlist
|
||||
event MspAddedToAllowlist(address indexed msp);
|
||||
|
||||
/// @notice Emitted when a validator is removed from the allowlist
|
||||
/// @param validator Address of the validator removed from the allowlist
|
||||
event ValidatorRemovedFromAllowlist(address indexed validator);
|
||||
|
||||
/// @notice Emitted when a Backup Storage Provider is removed from the allowlist
|
||||
/// @param bsp Address of the BSP removed from the allowlist
|
||||
event BspRemovedFromAllowlist(address indexed bsp);
|
||||
|
||||
/// @notice Emitted when a Main Storage Provider is removed from the allowlist
|
||||
/// @param msp Address of the MSP removed from the allowlist
|
||||
event MspRemovedFromAllowlist(address indexed msp);
|
||||
|
||||
/// @notice Emitted when the Snowbridge Gateway address is set
|
||||
/// @param snowbridgeGateway Address of the Snowbridge Gateway
|
||||
event SnowbridgeGatewaySet(address indexed snowbridgeGateway);
|
||||
}
|
||||
|
||||
/**
|
||||
* @title DataHaven Service Manager Interface
|
||||
* @notice Defines the interface for the DataHaven Service Manager, which manages validators,
|
||||
* backup storage providers (BSPs), and main storage providers (MSPs) in the DataHaven network
|
||||
*/
|
||||
interface IDataHavenServiceManager is
|
||||
IDataHavenServiceManagerErrors,
|
||||
IDataHavenServiceManagerEvents
|
||||
{
|
||||
/// @notice Checks if a validator address is in the allowlist
|
||||
/// @param validator Address to check
|
||||
/// @return True if the validator is in the allowlist, false otherwise
|
||||
function validatorsAllowlist(
|
||||
address validator
|
||||
) external view returns (bool);
|
||||
|
||||
/// @notice Checks if a BSP address is in the allowlist
|
||||
/// @param bsp Address to check
|
||||
/// @return True if the BSP is in the allowlist, false otherwise
|
||||
function bspsAllowlist(
|
||||
address bsp
|
||||
) external view returns (bool);
|
||||
|
||||
/// @notice Checks if an MSP address is in the allowlist
|
||||
/// @param msp Address to check
|
||||
/// @return True if the MSP is in the allowlist, false otherwise
|
||||
function mspsAllowlist(
|
||||
address msp
|
||||
) external view returns (bool);
|
||||
|
||||
/// @notice Returns the Snowbridge Gateway address
|
||||
/// @return The Snowbridge gateway address
|
||||
function snowbridgeGateway() external view returns (address);
|
||||
|
||||
/**
|
||||
* @notice Converts a validator address to the corresponding Solochain address
|
||||
* @param validatorAddress The address of the validator to convert
|
||||
* @return The corresponding Solochain address
|
||||
*/
|
||||
function validatorEthAddressToSolochainAddress(
|
||||
address validatorAddress
|
||||
) external view returns (bytes32);
|
||||
|
||||
/**
|
||||
* @notice Initializes the DataHaven Service Manager
|
||||
* @param initialOwner Address of the initial owner
|
||||
* @param rewardsInitiator Address authorized to initiate rewards
|
||||
* @param validatorsStrategies Array of strategies supported by validators
|
||||
* @param bspsStrategies Array of strategies supported by BSPs
|
||||
* @param mspsStrategies Array of strategies supported by MSPs
|
||||
*/
|
||||
function initialise(
|
||||
address initialOwner,
|
||||
address rewardsInitiator,
|
||||
IStrategy[] memory validatorsStrategies,
|
||||
IStrategy[] memory bspsStrategies,
|
||||
IStrategy[] memory mspsStrategies,
|
||||
address _snowbridgeGatewayAddress
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Sends a new validator set to the Snowbridge Gateway
|
||||
* @dev The new validator set is made up of the Validators currently
|
||||
* registered in the DataHaven Service Manager as operators of
|
||||
* the Validators operator set (operatorSetId = VALIDATORS_SET_ID)
|
||||
* @dev Only callable by the owner
|
||||
* @param executionFee The execution fee for the Snowbridge message
|
||||
* @param relayerFee The relayer fee for the Snowbridge message
|
||||
*/
|
||||
function sendNewValidatorSet(uint128 executionFee, uint128 relayerFee) external payable;
|
||||
|
||||
/**
|
||||
* @notice Builds a new validator set message to be sent to the Snowbridge Gateway
|
||||
* @return The encoded message bytes to be sent to the Snowbridge Gateway
|
||||
*/
|
||||
function buildNewValidatorSetMessage() external view returns (bytes memory);
|
||||
|
||||
/**
|
||||
* @notice Updates the Solochain address for a Validator
|
||||
* @param solochainAddress The new Solochain address for the Validator
|
||||
* @dev The caller must be the registered operator address for the Validator, in EigenLayer,
|
||||
* in the Validators operator set (operatorSetId = VALIDATORS_SET_ID)
|
||||
*/
|
||||
function updateSolochainAddressForValidator(
|
||||
bytes32 solochainAddress
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Sets the Snowbridge Gateway address
|
||||
* @param _snowbridgeGateway The address of the Snowbridge Gateway
|
||||
*/
|
||||
function setSnowbridgeGateway(
|
||||
address _snowbridgeGateway
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds a validator to the allowlist
|
||||
* @param validator Address of the validator to add
|
||||
*/
|
||||
function addValidatorToAllowlist(
|
||||
address validator
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds a BSP to the allowlist
|
||||
* @param bsp Address of the BSP to add
|
||||
*/
|
||||
function addBspToAllowlist(
|
||||
address bsp
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds an MSP to the allowlist
|
||||
* @param msp Address of the MSP to add
|
||||
*/
|
||||
function addMspToAllowlist(
|
||||
address msp
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Removes a validator from the allowlist
|
||||
* @param validator Address of the validator to remove
|
||||
*/
|
||||
function removeValidatorFromAllowlist(
|
||||
address validator
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Removes a BSP from the allowlist
|
||||
* @param bsp Address of the BSP to remove
|
||||
*/
|
||||
function removeBspFromAllowlist(
|
||||
address bsp
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Removes an MSP from the allowlist
|
||||
* @param msp Address of the MSP to remove
|
||||
*/
|
||||
function removeMspFromAllowlist(
|
||||
address msp
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Returns all strategies supported by the DataHaven Validators operator set
|
||||
* @return An array of strategy contracts that validators can delegate to
|
||||
*/
|
||||
function validatorsSupportedStrategies() external view returns (IStrategy[] memory);
|
||||
|
||||
/**
|
||||
* @notice Removes strategies from the list of supported strategies for DataHaven Validators
|
||||
* @param _strategies Array of strategy contracts to remove from validators operator set
|
||||
*/
|
||||
function removeStrategiesFromValidatorsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds strategies to the list of supported strategies for DataHaven Validators
|
||||
* @param _strategies Array of strategy contracts to add to validators operator set
|
||||
*/
|
||||
function addStrategiesToValidatorsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Returns all strategies supported by the Backup Storage Providers (BSPs) operator set
|
||||
* @return An array of strategy contracts that BSPs can delegate to
|
||||
*/
|
||||
function bspsSupportedStrategies() external view returns (IStrategy[] memory);
|
||||
|
||||
/**
|
||||
* @notice Removes strategies from the list of supported strategies for Backup Storage Providers
|
||||
* @param _strategies Array of strategy contracts to remove from BSPs operator set
|
||||
*/
|
||||
function removeStrategiesFromBspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds strategies to the list of supported strategies for Backup Storage Providers
|
||||
* @param _strategies Array of strategy contracts to add to BSPs operator set
|
||||
*/
|
||||
function addStrategiesToBspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Returns all strategies supported by the Main Storage Providers (MSPs) operator set
|
||||
* @return An array of strategy contracts that MSPs can delegate to
|
||||
*/
|
||||
function mspsSupportedStrategies() external view returns (IStrategy[] memory);
|
||||
|
||||
/**
|
||||
* @notice Removes strategies from the list of supported strategies for Main Storage Providers
|
||||
* @param _strategies Array of strategy contracts to remove from MSPs operator set
|
||||
*/
|
||||
function removeStrategiesFromMspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
|
||||
/**
|
||||
* @notice Adds strategies to the list of supported strategies for Main Storage Providers
|
||||
* @param _strategies Array of strategy contracts to add to MSPs operator set
|
||||
*/
|
||||
function addStrategiesToMspsSupportedStrategies(
|
||||
IStrategy[] calldata _strategies
|
||||
) external;
|
||||
}
|
||||
69
contracts/src/libraries/DataHavenSnowbridgeMessages.sol
Normal file
69
contracts/src/libraries/DataHavenSnowbridgeMessages.sol
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
// Snowbridge imports
|
||||
import {ScaleCodec} from "snowbridge/src/utils/ScaleCodec.sol";
|
||||
|
||||
library DataHavenSnowbridgeMessages {
|
||||
/**
|
||||
* @title New Validator Set Snowbridge Message
|
||||
* @notice A struct representing a new validator set to be sent as a message through Snowbridge.
|
||||
* This mimics the message format defined in the Snowbridge inbound pallet of the DataHaven
|
||||
* solochain.
|
||||
* !IMPORTANT: The fields in this struct are placeholder until we have the actual message format
|
||||
* ! defined in the DataHaven solochain.
|
||||
*/
|
||||
struct NewValidatorSet {
|
||||
/// @notice The nonce of the message
|
||||
uint64 nonce;
|
||||
/// @notice The topic of the message
|
||||
bytes32 topic;
|
||||
/// @notice The payload of the message
|
||||
NewValidatorSetPayload payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @title New Validator Set Snowbridge Message Payload
|
||||
* @notice A struct representing the payload of a new validator set message.
|
||||
* !IMPORTANT: The fields in this struct are placeholder until we have the actual message format
|
||||
* ! defined in the DataHaven solochain.
|
||||
*/
|
||||
struct NewValidatorSetPayload {
|
||||
/// @notice The new validator set. This should be interpreted as the list of
|
||||
/// validator addresses in the DataHaven network.
|
||||
bytes32[] newValidatorSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Encodes a new validator set message into a bytes array.
|
||||
* @param message The new validator set message to encode.
|
||||
* @return The encoded message.
|
||||
*/
|
||||
function scaleEncodeNewValidatorSetMessage(
|
||||
NewValidatorSet memory message
|
||||
) public pure returns (bytes memory) {
|
||||
return bytes.concat(
|
||||
ScaleCodec.encodeU64(message.nonce),
|
||||
message.topic,
|
||||
scaleEncodeNewValidatorSetMessagePayload(message.payload)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Encodes a new validator set message payload into a bytes array.
|
||||
* @param payload The new validator set message payload to encode.
|
||||
* @return The encoded payload.
|
||||
*/
|
||||
function scaleEncodeNewValidatorSetMessagePayload(
|
||||
NewValidatorSetPayload memory payload
|
||||
) public pure returns (bytes memory) {
|
||||
// Encode all fields into a buffer.
|
||||
bytes memory accum = hex"";
|
||||
for (uint256 i = 0; i < payload.newValidatorSet.length; i++) {
|
||||
accum = bytes.concat(accum, payload.newValidatorSet[i]);
|
||||
}
|
||||
// Encode number of validator addresses, followed by encoded validator addresses.
|
||||
return
|
||||
bytes.concat(ScaleCodec.checkedEncodeCompactU32(payload.newValidatorSet.length), accum);
|
||||
}
|
||||
}
|
||||
|
|
@ -49,6 +49,7 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage, IAVSRegistrar
|
|||
_disableInitializers();
|
||||
}
|
||||
|
||||
// solhint-disable-next-line func-name-mixedcase
|
||||
function __ServiceManagerBase_init(
|
||||
address initialOwner,
|
||||
address _rewardsInitiator
|
||||
|
|
@ -218,7 +219,7 @@ abstract contract ServiceManagerBase is ServiceManagerBaseStorage, IAVSRegistrar
|
|||
uint32[] calldata // operatorSetIds
|
||||
) external virtual {
|
||||
// Always rejects Operator deregistration.
|
||||
revert("ServiceManagerBase: deregistration not supported");
|
||||
revert("ServiceManagerBase: deregistration not supported, we are evil");
|
||||
}
|
||||
|
||||
/// @inheritdoc IServiceManager
|
||||
|
|
|
|||
|
|
@ -58,5 +58,6 @@ abstract contract ServiceManagerBaseStorage is IServiceManager, OwnableUpgradeab
|
|||
}
|
||||
|
||||
// storage gap for upgradeability
|
||||
// solhint-disable-next-line var-name-mixedcase
|
||||
uint256[49] private __GAP;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ pragma solidity ^0.8.13;
|
|||
import {Test, console, stdError} from "forge-std/Test.sol";
|
||||
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
|
||||
|
||||
import {MockAVSDeployer} from "./utils/MockAVSDeployer.sol";
|
||||
import {AVSDeployer} from "./utils/AVSDeployer.sol";
|
||||
import {RewardsRegistry} from "../src/middleware/RewardsRegistry.sol";
|
||||
import {IRewardsRegistry, IRewardsRegistryErrors} from "../src/interfaces/IRewardsRegistry.sol";
|
||||
|
||||
contract RewardsRegistryTest is MockAVSDeployer {
|
||||
contract RewardsRegistryTest is AVSDeployer {
|
||||
address public nonRewardsAgent;
|
||||
address public operatorAddress;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,15 +15,14 @@ import {
|
|||
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
|
||||
import {ServiceManagerMock} from "./mocks/ServiceManagerMock.sol";
|
||||
import {MockAVSDeployer} from "./utils/MockAVSDeployer.sol";
|
||||
import {AVSDeployer} from "./utils/AVSDeployer.sol";
|
||||
import {IServiceManager} from "../src/interfaces/IServiceManager.sol";
|
||||
import {IServiceManagerUI} from "../src/interfaces/IServiceManagerUI.sol";
|
||||
import {ServiceManagerBase} from "../src/middleware/ServiceManagerBase.sol";
|
||||
|
||||
contract ServiceManagerBaseTest is MockAVSDeployer {
|
||||
contract ServiceManagerBaseTest is AVSDeployer {
|
||||
function setUp() public virtual {
|
||||
_deployMockEigenLayerAndAVS();
|
||||
_setUpDefaultStrategiesAndMultipliers();
|
||||
}
|
||||
|
||||
function beforeTestSetup(
|
||||
|
|
@ -46,17 +45,6 @@ contract ServiceManagerBaseTest is MockAVSDeployer {
|
|||
IServiceManagerUI(address(serviceManager)).updateAVSMetadataURI("https://example.com");
|
||||
}
|
||||
|
||||
function test_createOperatorSetsRevertsIfNoMetadataExists() public {
|
||||
vm.prank(avsOwner);
|
||||
vm.expectRevert(
|
||||
abi.encodeWithSelector(IAllocationManagerErrors.NonexistentAVSMetadata.selector)
|
||||
);
|
||||
|
||||
IAllocationManager.CreateSetParams[] memory emptyParams =
|
||||
new IAllocationManager.CreateSetParams[](0);
|
||||
ServiceManagerBase(address(serviceManager)).createOperatorSets(emptyParams);
|
||||
}
|
||||
|
||||
function test_createOperatorSetsWithEmptyParams() public {
|
||||
vm.prank(avsOwner);
|
||||
IAllocationManager.CreateSetParams[] memory emptyParams =
|
||||
|
|
|
|||
|
|
@ -5,14 +5,16 @@ pragma solidity ^0.8.13;
|
|||
|
||||
import {Test, console, stdError} from "forge-std/Test.sol";
|
||||
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
|
||||
import {IAllocationManager} from
|
||||
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
|
||||
import {MockAVSDeployer} from "./utils/MockAVSDeployer.sol";
|
||||
import {AVSDeployer} from "./utils/AVSDeployer.sol";
|
||||
import {RewardsRegistry} from "../src/middleware/RewardsRegistry.sol";
|
||||
import {IRewardsRegistry, IRewardsRegistryErrors} from "../src/interfaces/IRewardsRegistry.sol";
|
||||
import {ServiceManagerMock} from "./mocks/ServiceManagerMock.sol";
|
||||
import {IServiceManager, IServiceManagerErrors} from "../src/interfaces/IServiceManager.sol";
|
||||
|
||||
contract ServiceManagerRewardsRegistryTest is MockAVSDeployer {
|
||||
contract ServiceManagerRewardsRegistryTest is AVSDeployer {
|
||||
// Test addresses
|
||||
address public operatorAddress;
|
||||
address public nonOperatorAddress;
|
||||
|
|
@ -73,7 +75,7 @@ contract ServiceManagerRewardsRegistryTest is MockAVSDeployer {
|
|||
);
|
||||
|
||||
assertEq(
|
||||
address(serviceManager.getOperatorSetRewardsRegistry(newOperatorSetId)),
|
||||
address(serviceManager.operatorSetToRewardsRegistry(newOperatorSetId)),
|
||||
address(newRewardsRegistry),
|
||||
"Rewards registry should be set correctly"
|
||||
);
|
||||
|
|
@ -95,6 +97,12 @@ contract ServiceManagerRewardsRegistryTest is MockAVSDeployer {
|
|||
function test_claimOperatorRewards() public {
|
||||
uint256 initialBalance = operatorAddress.balance;
|
||||
|
||||
vm.mockCall(
|
||||
address(allocationManager),
|
||||
abi.encodeWithSelector(IAllocationManager.isMemberOfOperatorSet.selector),
|
||||
abi.encode(true)
|
||||
);
|
||||
|
||||
vm.prank(operatorAddress);
|
||||
vm.expectEmit(true, true, true, true);
|
||||
emit RewardsClaimed(operatorAddress, operatorPoints, operatorPoints);
|
||||
|
|
@ -120,6 +128,12 @@ contract ServiceManagerRewardsRegistryTest is MockAVSDeployer {
|
|||
}
|
||||
|
||||
function test_claimOperatorRewards_AlreadyClaimed() public {
|
||||
vm.mockCall(
|
||||
address(allocationManager),
|
||||
abi.encodeWithSelector(IAllocationManager.isMemberOfOperatorSet.selector),
|
||||
abi.encode(true)
|
||||
);
|
||||
|
||||
// First claim
|
||||
vm.prank(operatorAddress);
|
||||
serviceManager.claimOperatorRewards(operatorSetId, operatorPoints, validProof);
|
||||
|
|
@ -166,6 +180,11 @@ contract ServiceManagerRewardsRegistryTest is MockAVSDeployer {
|
|||
|
||||
// Claim from first registry
|
||||
uint256 initialBalance = operatorAddress.balance;
|
||||
vm.mockCall(
|
||||
address(allocationManager),
|
||||
abi.encodeWithSelector(IAllocationManager.isMemberOfOperatorSet.selector),
|
||||
abi.encode(true)
|
||||
);
|
||||
vm.prank(operatorAddress);
|
||||
serviceManager.claimOperatorRewards(operatorSetId, operatorPoints, validProof);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,19 +14,18 @@ import {
|
|||
IAllocationManagerTypes
|
||||
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
|
||||
import {MockAVSDeployer} from "./utils/MockAVSDeployer.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 MockAVSDeployer {
|
||||
contract SlasherBaseTest is AVSDeployer {
|
||||
SlasherMock public slasherContract;
|
||||
address public nonServiceManagerRole;
|
||||
|
||||
function setUp() public virtual {
|
||||
_deployMockEigenLayerAndAVS();
|
||||
_setUpDefaultStrategiesAndMultipliers();
|
||||
|
||||
// Set up roles for testing
|
||||
nonServiceManagerRole = address(0x5678);
|
||||
|
|
|
|||
|
|
@ -5,19 +5,28 @@ pragma solidity ^0.8.13;
|
|||
|
||||
import {InboundMessageV2} from "snowbridge/src/Types.sol";
|
||||
import {CommandV2, CommandKind, IGatewayV2} from "snowbridge/src/Types.sol";
|
||||
import {CallContractParams} from "snowbridge/src/v2/Types.sol";
|
||||
import {
|
||||
CallContractParams,
|
||||
Payload,
|
||||
Message,
|
||||
MessageKind,
|
||||
Asset,
|
||||
AssetKind
|
||||
} from "snowbridge/src/v2/Types.sol";
|
||||
import {BeefyVerification} from "snowbridge/src/BeefyVerification.sol";
|
||||
import {BeefyClient} from "snowbridge/src/BeefyClient.sol";
|
||||
import {IAllocationManager} from
|
||||
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
import {OperatorSet} from "eigenlayer-contracts/src/contracts/libraries/OperatorSetLib.sol";
|
||||
|
||||
import {MerkleUtils} from "../src/libraries/MerkleUtils.sol";
|
||||
import {
|
||||
IRewardsRegistryEvents, IRewardsRegistryErrors
|
||||
} from "../src/interfaces/IRewardsRegistry.sol";
|
||||
import {MockSnowbridgeAndAVSDeployer} from "./utils/MockSnowbridgeAndAVSDeployer.sol";
|
||||
|
||||
import {SnowbridgeAndAVSDeployer} from "./utils/SnowbridgeAndAVSDeployer.sol";
|
||||
import "forge-std/Test.sol";
|
||||
|
||||
contract SnowbridgeIntegrationTest is MockSnowbridgeAndAVSDeployer {
|
||||
contract SnowbridgeIntegrationTest is SnowbridgeAndAVSDeployer {
|
||||
// Storage variables to reduce stack depth
|
||||
uint128[] internal _validatorPoints;
|
||||
address[] internal _validatorAddresses;
|
||||
|
|
@ -27,11 +36,15 @@ contract SnowbridgeIntegrationTest is MockSnowbridgeAndAVSDeployer {
|
|||
_deployMockAllContracts();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Constructor Tests *
|
||||
*
|
||||
*/
|
||||
function beforeTestSetup(
|
||||
bytes4 testSelector
|
||||
) public pure returns (bytes[] memory beforeTestCalldata) {
|
||||
if (testSelector == this.test_sendNewValidatorsSetMessage.selector) {
|
||||
beforeTestCalldata = new bytes[](1);
|
||||
beforeTestCalldata[0] = abi.encodeWithSelector(this.setupValidatorsAsOperators.selector);
|
||||
}
|
||||
}
|
||||
|
||||
function test_constructor() public view {
|
||||
assertEq(
|
||||
rewardsRegistry.rewardsAgent(),
|
||||
|
|
@ -81,6 +94,11 @@ contract SnowbridgeIntegrationTest is MockSnowbridgeAndAVSDeployer {
|
|||
_buildValidatorPointsProof(_validatorAddresses, _validatorPoints, 0);
|
||||
|
||||
// Claim rewards for the first validator.
|
||||
vm.mockCall(
|
||||
address(allocationManager),
|
||||
abi.encodeWithSelector(IAllocationManager.isMemberOfOperatorSet.selector),
|
||||
abi.encode(true)
|
||||
);
|
||||
vm.startPrank(_validatorAddresses[0]);
|
||||
vm.expectEmit(address(rewardsRegistry));
|
||||
emit IRewardsRegistryEvents.RewardsClaimed(
|
||||
|
|
@ -148,6 +166,39 @@ contract SnowbridgeIntegrationTest is MockSnowbridgeAndAVSDeployer {
|
|||
gateway.v2_submit(badUpdateRewardsMessage, messagesProof, beefyProof, rewardAddress);
|
||||
}
|
||||
|
||||
function test_sendNewValidatorsSetMessage() public {
|
||||
// Check that the current validators signed as operators have a registered address for the DataHaven solochain.
|
||||
address[] memory currentValidators = allocationManager.getMembers(
|
||||
OperatorSet({avs: address(serviceManager), id: serviceManager.VALIDATORS_SET_ID()})
|
||||
);
|
||||
for (uint256 i = 0; i < currentValidators.length; i++) {
|
||||
assertEq(
|
||||
serviceManager.validatorEthAddressToSolochainAddress(currentValidators[i]),
|
||||
initialValidators[i],
|
||||
"Validator should have a registered address for the DataHaven solochain"
|
||||
);
|
||||
}
|
||||
|
||||
// Mock balance for the AVS owner
|
||||
vm.deal(avsOwner, 1000000 ether);
|
||||
|
||||
// Send the new validator set message to the Snowbridge Gateway
|
||||
bytes memory message = serviceManager.buildNewValidatorSetMessage();
|
||||
Payload memory payload = Payload({
|
||||
origin: address(serviceManager),
|
||||
assets: new Asset[](0),
|
||||
message: Message({kind: MessageKind.Raw, data: message}),
|
||||
claimer: bytes(""),
|
||||
value: 0,
|
||||
executionFee: 1 ether,
|
||||
relayerFee: 1 ether
|
||||
});
|
||||
cheats.expectEmit();
|
||||
emit IGatewayV2.OutboundMessageAccepted(1, payload);
|
||||
cheats.prank(avsOwner);
|
||||
serviceManager.sendNewValidatorSet{value: 2 ether}(1 ether, 1 ether);
|
||||
}
|
||||
|
||||
function _setupValidatorData() internal {
|
||||
// Build validator points and addresses.
|
||||
_validatorPoints = new uint128[](10);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
IAllocationManagerTypes
|
||||
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
|
||||
import {MockAVSDeployer} from "./utils/MockAVSDeployer.sol";
|
||||
import {AVSDeployer} from "./utils/AVSDeployer.sol";
|
||||
import {IServiceManager} from "../src/interfaces/IServiceManager.sol";
|
||||
import {ISlasher, ISlasherErrors, ISlasherEvents} from "../src/interfaces/ISlasher.sol";
|
||||
import {
|
||||
|
|
@ -26,7 +26,7 @@ import {
|
|||
import {SlasherBase} from "../src/middleware/SlasherBase.sol";
|
||||
import {VetoableSlasher} from "../src/middleware/VetoableSlasher.sol";
|
||||
|
||||
contract VetoableSlasherTest is MockAVSDeployer {
|
||||
contract VetoableSlasherTest is AVSDeployer {
|
||||
address public nonServiceManagerRole;
|
||||
address public nonVetoCommittee;
|
||||
|
||||
|
|
@ -49,7 +49,6 @@ contract VetoableSlasherTest is MockAVSDeployer {
|
|||
|
||||
function setUp() public virtual {
|
||||
_deployMockEigenLayerAndAVS();
|
||||
_setUpDefaultStrategiesAndMultipliers();
|
||||
|
||||
// Set up roles for testing
|
||||
nonServiceManagerRole = address(0x5678);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ contract ServiceManagerMock is ServiceManagerBase {
|
|||
IAllocationManager __allocationManager
|
||||
) ServiceManagerBase(__rewardsCoordinator, __permissionController, __allocationManager) {}
|
||||
|
||||
function initialize(
|
||||
function initialise(
|
||||
address initialOwner,
|
||||
address rewardsInitiator
|
||||
) public virtual initializer {
|
||||
|
|
|
|||
|
|
@ -28,18 +28,18 @@ 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
|
||||
import {StrategyManagerMock} from "eigenlayer-contracts/src/test/mocks/StrategyManagerMock.sol";
|
||||
import {StrategyManager} from "eigenlayer-contracts/src/contracts/core/StrategyManager.sol";
|
||||
import {RewardsCoordinatorMock} from "../mocks/RewardsCoordinatorMock.sol";
|
||||
import {PermissionControllerMock} from "../mocks/PermissionControllerMock.sol";
|
||||
import {EigenPodManagerMock} from "../mocks/EigenPodManagerMock.sol";
|
||||
import {AllocationManagerMock} from "../mocks/AllocationManagerMock.sol";
|
||||
import {DelegationMock} from "../mocks/DelegationMock.sol";
|
||||
import {ServiceManagerMock} from "../mocks/ServiceManagerMock.sol";
|
||||
import {DelegationManager} from "eigenlayer-contracts/src/contracts/core/DelegationManager.sol";
|
||||
|
||||
import "forge-std/Test.sol";
|
||||
|
||||
contract MockAVSDeployer is Test {
|
||||
contract AVSDeployer is Test {
|
||||
Vm public cheats = Vm(VM_ADDRESS);
|
||||
|
||||
ProxyAdmin public proxyAdmin;
|
||||
|
|
@ -48,8 +48,8 @@ contract MockAVSDeployer is Test {
|
|||
EmptyContract public emptyContract;
|
||||
|
||||
// AVS contracts
|
||||
ServiceManagerMock public serviceManager;
|
||||
ServiceManagerMock public serviceManagerImplementation;
|
||||
DataHavenServiceManager public serviceManager;
|
||||
DataHavenServiceManager public serviceManagerImplementation;
|
||||
VetoableSlasher public vetoableSlasher;
|
||||
RewardsRegistry public rewardsRegistry;
|
||||
|
||||
|
|
@ -61,12 +61,13 @@ contract MockAVSDeployer is Test {
|
|||
address public mockRewardsAgent = address(uint160(uint256(keccak256("rewardsAgent"))));
|
||||
|
||||
// EigenLayer contracts
|
||||
StrategyManagerMock public strategyManagerMock;
|
||||
DelegationMock public delegationMock;
|
||||
StrategyManager public strategyManager;
|
||||
StrategyManager public strategyManagerImplementation;
|
||||
DelegationManager public delegationManager;
|
||||
DelegationManager public delegationManagerImplementation;
|
||||
EigenPodManagerMock public eigenPodManagerMock;
|
||||
AllocationManager public allocationManager;
|
||||
AllocationManager public allocationManagerImplementation;
|
||||
AllocationManagerMock public allocationManagerMock;
|
||||
RewardsCoordinator public rewardsCoordinator;
|
||||
RewardsCoordinator public rewardsCoordinatorImplementation;
|
||||
RewardsCoordinatorMock public rewardsCoordinatorMock;
|
||||
|
|
@ -115,19 +116,14 @@ contract MockAVSDeployer is Test {
|
|||
address[] memory pausers = new address[](1);
|
||||
pausers[0] = pauser;
|
||||
pauserRegistry = new PauserRegistry(pausers, unpauser);
|
||||
delegationMock = new DelegationMock();
|
||||
eigenPodManagerMock = new EigenPodManagerMock(pauserRegistry);
|
||||
allocationManagerMock = new AllocationManagerMock();
|
||||
permissionControllerMock = new PermissionControllerMock();
|
||||
rewardsCoordinatorMock = new RewardsCoordinatorMock();
|
||||
cheats.stopPrank();
|
||||
|
||||
cheats.prank(strategyOwner);
|
||||
strategyManagerMock = new StrategyManagerMock(delegationMock);
|
||||
console.log("Mock EigenLayer contracts deployed");
|
||||
|
||||
console.log("EigenLayer contracts deployed");
|
||||
|
||||
// Deploying proxy contracts for ServiceManager, and AllocationManager.
|
||||
// Deploying proxy contracts for AllocationManager and StrategyManager.
|
||||
// The `proxyAdmin` contract is set as the admin of the proxy contracts,
|
||||
// which will be later upgraded to the actual implementation.
|
||||
cheats.prank(regularDeployer);
|
||||
|
|
@ -136,13 +132,37 @@ contract MockAVSDeployer is Test {
|
|||
new TransparentUpgradeableProxy(address(emptyContract), address(proxyAdmin), "")
|
||||
)
|
||||
);
|
||||
strategyManager = StrategyManager(
|
||||
address(
|
||||
new TransparentUpgradeableProxy(address(emptyContract), address(proxyAdmin), "")
|
||||
)
|
||||
);
|
||||
|
||||
console.log("Proxy contracts deployed");
|
||||
console.log("AllocationManager and StrategyManager proxy contracts deployed");
|
||||
|
||||
// Deploying DelegationManager implementation and its proxy.
|
||||
cheats.prank(regularDeployer);
|
||||
delegationManagerImplementation = new DelegationManager(
|
||||
strategyManager,
|
||||
eigenPodManagerMock,
|
||||
allocationManager,
|
||||
pauserRegistry,
|
||||
permissionControllerMock,
|
||||
uint32(10), // MIN_WITHDRAWAL_DELAY_BLOCKS
|
||||
"v-mock"
|
||||
);
|
||||
cheats.prank(regularDeployer);
|
||||
delegationManager = DelegationManager(
|
||||
address(
|
||||
new TransparentUpgradeableProxy(
|
||||
address(delegationManagerImplementation), address(proxyAdmin), ""
|
||||
)
|
||||
)
|
||||
);
|
||||
// Deploying AllocationManager implementation and upgrading the proxy.
|
||||
cheats.prank(regularDeployer);
|
||||
allocationManagerImplementation = new AllocationManager(
|
||||
delegationMock,
|
||||
delegationManager,
|
||||
pauserRegistry,
|
||||
permissionControllerMock,
|
||||
uint32(7 days), // DEALLOCATION_DELAY
|
||||
|
|
@ -157,14 +177,30 @@ contract MockAVSDeployer is Test {
|
|||
|
||||
console.log("AllocationManager implementation deployed");
|
||||
|
||||
// Deploying StrategyManager implementation and its proxy.
|
||||
cheats.prank(regularDeployer);
|
||||
strategyManagerImplementation =
|
||||
new StrategyManager(delegationManager, pauserRegistry, "v-mock");
|
||||
cheats.prank(proxyAdminOwner);
|
||||
uint256 allUnpaused = 0;
|
||||
proxyAdmin.upgradeAndCall(
|
||||
ITransparentUpgradeableProxy(address(strategyManager)),
|
||||
address(strategyManagerImplementation),
|
||||
abi.encodeWithSelector(
|
||||
StrategyManager.initialize.selector, strategyOwner, strategyOwner, allUnpaused
|
||||
)
|
||||
);
|
||||
|
||||
console.log("StrategyManager implementation deployed");
|
||||
|
||||
// Deploying RewardsCoordinator implementation and its proxy.
|
||||
// When the proxy is deployed, the `initialize` function is called.
|
||||
cheats.startPrank(regularDeployer);
|
||||
IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams memory params =
|
||||
IRewardsCoordinatorTypes.RewardsCoordinatorConstructorParams({
|
||||
delegationManager: delegationMock,
|
||||
strategyManager: IStrategyManager(address(strategyManagerMock)),
|
||||
allocationManager: allocationManagerMock,
|
||||
delegationManager: delegationManager,
|
||||
strategyManager: IStrategyManager(address(strategyManager)),
|
||||
allocationManager: allocationManager,
|
||||
pauserRegistry: pauserRegistry,
|
||||
permissionController: permissionControllerMock,
|
||||
CALCULATION_INTERVAL_SECONDS: CALCULATION_INTERVAL_SECONDS,
|
||||
|
|
@ -195,18 +231,41 @@ contract MockAVSDeployer is Test {
|
|||
|
||||
console.log("RewardsCoordinator implementation deployed");
|
||||
|
||||
// Set up strategies before deploying the ServiceManager
|
||||
_setUpDefaultStrategiesAndMultipliers();
|
||||
|
||||
// Deploying ServiceManager implementation and its proxy.
|
||||
// When the proxy is deployed, the `initialize` function is called.
|
||||
cheats.startPrank(regularDeployer);
|
||||
serviceManagerImplementation =
|
||||
new ServiceManagerMock(rewardsCoordinator, permissionControllerMock, allocationManager);
|
||||
serviceManager = ServiceManagerMock(
|
||||
serviceManagerImplementation = new DataHavenServiceManager(
|
||||
rewardsCoordinator, permissionControllerMock, allocationManager
|
||||
);
|
||||
|
||||
// Create arrays for the three sets of strategies required by DataHavenServiceManager
|
||||
IStrategy[] memory validatorsStrategies = new IStrategy[](deployedStrategies.length);
|
||||
IStrategy[] memory bspsStrategies = new IStrategy[](deployedStrategies.length);
|
||||
IStrategy[] memory mspsStrategies = new IStrategy[](deployedStrategies.length);
|
||||
|
||||
// For testing purposes, we'll use the same strategies for all three sets
|
||||
for (uint256 i = 0; i < deployedStrategies.length; i++) {
|
||||
validatorsStrategies[i] = deployedStrategies[i];
|
||||
bspsStrategies[i] = deployedStrategies[i];
|
||||
mspsStrategies[i] = deployedStrategies[i];
|
||||
}
|
||||
|
||||
serviceManager = DataHavenServiceManager(
|
||||
address(
|
||||
new TransparentUpgradeableProxy(
|
||||
address(serviceManagerImplementation),
|
||||
address(proxyAdmin),
|
||||
abi.encodeWithSelector(
|
||||
ServiceManagerMock.initialize.selector, avsOwner, rewardsInitiator
|
||||
DataHavenServiceManager.initialise.selector,
|
||||
avsOwner,
|
||||
rewardsInitiator,
|
||||
validatorsStrategies,
|
||||
bspsStrategies,
|
||||
mspsStrategies,
|
||||
address(0) // This deployment does not use Snowbridge
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -239,7 +298,7 @@ contract MockAVSDeployer is Test {
|
|||
|
||||
function _setUpDefaultStrategiesAndMultipliers() internal virtual {
|
||||
// Deploy mock tokens to be used for strategies.
|
||||
vm.startPrank(strategyOwner);
|
||||
cheats.startPrank(strategyOwner);
|
||||
IERC20 token1 =
|
||||
new ERC20FixedSupply("dog wif hat", "MOCK1", mockTokenInitialSupply, address(this));
|
||||
IERC20 token2 =
|
||||
|
|
@ -248,9 +307,8 @@ contract MockAVSDeployer is Test {
|
|||
new ERC20FixedSupply("pepe wif avs", "MOCK3", mockTokenInitialSupply, address(this));
|
||||
|
||||
// Deploy mock strategies.
|
||||
strategyImplementation = new StrategyBase(
|
||||
IStrategyManager(address(strategyManagerMock)), pauserRegistry, "v-mock"
|
||||
);
|
||||
strategyImplementation =
|
||||
new StrategyBase(IStrategyManager(address(strategyManager)), pauserRegistry, "v-mock");
|
||||
deployedStrategies.push(
|
||||
StrategyBase(
|
||||
address(
|
||||
|
|
@ -290,15 +348,13 @@ contract MockAVSDeployer is Test {
|
|||
)
|
||||
)
|
||||
);
|
||||
vm.stopPrank();
|
||||
cheats.stopPrank();
|
||||
|
||||
deployedStrategies = _sortArrayAsc(deployedStrategies);
|
||||
|
||||
vm.startPrank(strategyOwner);
|
||||
strategyManagerMock.setStrategyWhitelist(deployedStrategies[0], true);
|
||||
strategyManagerMock.setStrategyWhitelist(deployedStrategies[1], true);
|
||||
strategyManagerMock.setStrategyWhitelist(deployedStrategies[2], true);
|
||||
vm.stopPrank();
|
||||
cheats.startPrank(strategyOwner);
|
||||
strategyManager.addStrategiesToDepositWhitelist(deployedStrategies);
|
||||
cheats.stopPrank();
|
||||
|
||||
defaultStrategyAndMultipliers.push(
|
||||
IRewardsCoordinatorTypes.StrategyAndMultiplier(
|
||||
|
|
@ -318,19 +374,18 @@ contract MockAVSDeployer is Test {
|
|||
}
|
||||
|
||||
function _labelContracts() internal {
|
||||
vm.label(address(emptyContract), "EmptyContract");
|
||||
vm.label(address(proxyAdmin), "ProxyAdmin");
|
||||
vm.label(address(pauserRegistry), "PauserRegistry");
|
||||
vm.label(address(delegationMock), "DelegationMock");
|
||||
vm.label(address(eigenPodManagerMock), "EigenPodManagerMock");
|
||||
vm.label(address(strategyManagerMock), "StrategyManagerMock");
|
||||
vm.label(address(allocationManagerMock), "AllocationManagerMock");
|
||||
vm.label(address(rewardsCoordinatorMock), "RewardsCoordinatorMock");
|
||||
vm.label(address(allocationManager), "AllocationManager");
|
||||
vm.label(address(allocationManagerImplementation), "AllocationManagerImplementation");
|
||||
vm.label(address(serviceManager), "ServiceManager");
|
||||
vm.label(address(serviceManagerImplementation), "ServiceManagerImplementation");
|
||||
vm.label(address(vetoableSlasher), "VetoableSlasher");
|
||||
cheats.label(address(emptyContract), "EmptyContract");
|
||||
cheats.label(address(proxyAdmin), "ProxyAdmin");
|
||||
cheats.label(address(pauserRegistry), "PauserRegistry");
|
||||
cheats.label(address(delegationManager), "DelegationManager");
|
||||
cheats.label(address(eigenPodManagerMock), "EigenPodManagerMock");
|
||||
cheats.label(address(strategyManager), "StrategyManager");
|
||||
cheats.label(address(rewardsCoordinatorMock), "RewardsCoordinatorMock");
|
||||
cheats.label(address(allocationManager), "AllocationManager");
|
||||
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
|
||||
|
|
@ -357,4 +412,10 @@ contract MockAVSDeployer is Test {
|
|||
function _incrementBytes32(bytes32 start, uint256 inc) internal pure returns (bytes32) {
|
||||
return bytes32(uint256(start) + inc);
|
||||
}
|
||||
|
||||
function _setERC20Balance(address token, address user, uint256 amount) internal {
|
||||
// Assumes balanceOf is in slot 0 (standard in OpenZeppelin ERC20)
|
||||
bytes32 slot = keccak256(abi.encode(user, uint256(0)));
|
||||
cheats.store(token, slot, bytes32(amount));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.27;
|
||||
|
||||
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import {Gateway} from "snowbridge/src/Gateway.sol";
|
||||
import {IGatewayV2} from "snowbridge/src/v2/IGateway.sol";
|
||||
import {GatewayProxy} from "snowbridge/src/GatewayProxy.sol";
|
||||
|
|
@ -10,7 +11,7 @@ import {Initializer} from "snowbridge/src/Initializer.sol";
|
|||
import {OperatingMode} from "snowbridge/src/types/Common.sol";
|
||||
import {ud60x18} from "snowbridge/lib/prb-math/src/UD60x18.sol";
|
||||
import {BeefyClient} from "snowbridge/src/BeefyClient.sol";
|
||||
import {MockAVSDeployer} from "./MockAVSDeployer.sol";
|
||||
import {AVSDeployer} from "./AVSDeployer.sol";
|
||||
import {MerkleUtils} from "../../src/libraries/MerkleUtils.sol";
|
||||
import {IAllocationManagerTypes} from
|
||||
"eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
|
||||
|
|
@ -18,7 +19,7 @@ import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy
|
|||
|
||||
import "forge-std/Test.sol";
|
||||
|
||||
contract MockSnowbridgeAndAVSDeployer is MockAVSDeployer {
|
||||
contract SnowbridgeAndAVSDeployer is AVSDeployer {
|
||||
// Snowbridge contracts
|
||||
BeefyClient public beefyClient;
|
||||
IGatewayV2 public gateway;
|
||||
|
|
@ -27,7 +28,26 @@ contract MockSnowbridgeAndAVSDeployer is MockAVSDeployer {
|
|||
Agent public rewardsAgent;
|
||||
Agent public wrongAgent;
|
||||
|
||||
// The addresses of the validators that are allowed to register to the DataHaven service.
|
||||
address[] public validatorsAllowlist = [
|
||||
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, // First pre-funded address in anvil
|
||||
0x70997970C51812dc3A010C7d01b50e0d17dc79C8, // Second pre-funded address in anvil
|
||||
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC, // Third pre-funded address in anvil
|
||||
0x90F79bf6EB2c4f870365E785982E1f101E93b906, // Fourth pre-funded address in anvil
|
||||
0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65, // Fifth pre-funded address in anvil
|
||||
0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc, // Sixth pre-funded address in anvil
|
||||
0x976EA74026E726554dB657fA54763abd0C3a0aa9, // Seventh pre-funded address in anvil
|
||||
0x14dC79964da2C08b23698B3D3cc7Ca32193d9955, // Eighth pre-funded address in anvil
|
||||
0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f, // Ninth pre-funded address in anvil
|
||||
0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 // Tenth pre-funded address in anvil
|
||||
];
|
||||
// The addresses of the Backup Storage Providers that are allowed to register to the DataHaven service.
|
||||
address[] public bspsAllowlist;
|
||||
// The addresses of the Main Storage Providers that are allowed to register to the DataHaven service.
|
||||
address[] public mspsAllowlist;
|
||||
|
||||
// Snowbridge contracts params
|
||||
// The addresses of the initial (current) Validators in the DataHaven solochain.
|
||||
bytes32[] public initialValidators = [
|
||||
keccak256(abi.encodePacked("validator1")),
|
||||
keccak256(abi.encodePacked("validator2")),
|
||||
|
|
@ -40,6 +60,7 @@ contract MockSnowbridgeAndAVSDeployer is MockAVSDeployer {
|
|||
keccak256(abi.encodePacked("validator9")),
|
||||
keccak256(abi.encodePacked("validator10"))
|
||||
];
|
||||
// The addresses of the next Validators in the DataHaven solochain.
|
||||
bytes32[] public nextValidators = [
|
||||
keccak256(abi.encodePacked("validator11")),
|
||||
keccak256(abi.encodePacked("validator12")),
|
||||
|
|
@ -141,7 +162,7 @@ contract MockSnowbridgeAndAVSDeployer is MockAVSDeployer {
|
|||
cheats.prank(regularDeployer);
|
||||
gateway.v2_createAgent(REWARDS_MESSAGE_ORIGIN);
|
||||
|
||||
// Get the agent address after creation
|
||||
// Get the agent address after creation.
|
||||
address payable agentAddress = payable(gateway.agentOf(REWARDS_MESSAGE_ORIGIN));
|
||||
rewardsAgent = Agent(agentAddress);
|
||||
|
||||
|
|
@ -155,11 +176,66 @@ contract MockSnowbridgeAndAVSDeployer is MockAVSDeployer {
|
|||
cheats.prank(regularDeployer);
|
||||
gateway.v2_createAgent(WRONG_MESSAGE_ORIGIN);
|
||||
|
||||
// Get the agent address after creation
|
||||
// Get the agent address after creation.
|
||||
address payable wrongAgentAddress = payable(gateway.agentOf(WRONG_MESSAGE_ORIGIN));
|
||||
wrongAgent = Agent(wrongAgentAddress);
|
||||
|
||||
console.log("Wrong agent deployed at", address(wrongAgent));
|
||||
|
||||
// Set the Snowbridge Gateway address in the DataHaven service.
|
||||
cheats.prank(avsOwner);
|
||||
serviceManager.setSnowbridgeGateway(address(gateway));
|
||||
}
|
||||
|
||||
function setupValidatorsAsOperators() public {
|
||||
for (uint256 i = 0; i < validatorsAllowlist.length; i++) {
|
||||
console.log("Setting up validator %s as operator", validatorsAllowlist[i]);
|
||||
|
||||
// Whitelist the validator in the DataHaven service.
|
||||
cheats.prank(avsOwner);
|
||||
serviceManager.addValidatorToAllowlist(validatorsAllowlist[i]);
|
||||
|
||||
cheats.startPrank(validatorsAllowlist[i]);
|
||||
for (uint256 j = 0; j < deployedStrategies.length; j++) {
|
||||
console.log(
|
||||
"Depositing tokens from validator %s into strategy %s",
|
||||
validatorsAllowlist[i],
|
||||
address(deployedStrategies[j])
|
||||
);
|
||||
|
||||
// Give the validator some balance in the strategy's linked token.
|
||||
IERC20 linkedToken = deployedStrategies[j].underlyingToken();
|
||||
_setERC20Balance(address(linkedToken), validatorsAllowlist[i], 1000 ether);
|
||||
|
||||
// Stake some of the validator's balance as stake for the strategy.
|
||||
linkedToken.approve(address(strategyManager), 1000 ether);
|
||||
strategyManager.depositIntoStrategy(deployedStrategies[j], linkedToken, 1000 ether);
|
||||
|
||||
console.log(
|
||||
"Staked %s tokens from validator %s into strategy %s",
|
||||
1000 ether,
|
||||
validatorsAllowlist[i],
|
||||
address(deployedStrategies[j])
|
||||
);
|
||||
}
|
||||
|
||||
// Register the validator as an operator in EigenLayer.
|
||||
delegationManager.registerAsOperator(address(0), 0, "");
|
||||
|
||||
// Register the validator as an operator for the DataHaven service.
|
||||
uint32[] memory operatorSetIds = new uint32[](1);
|
||||
operatorSetIds[0] = serviceManager.VALIDATORS_SET_ID();
|
||||
IAllocationManagerTypes.RegisterParams memory registerParams = IAllocationManagerTypes
|
||||
.RegisterParams({
|
||||
avs: address(serviceManager),
|
||||
operatorSetIds: operatorSetIds,
|
||||
data: abi.encodePacked(initialValidators[i])
|
||||
});
|
||||
allocationManager.registerForOperatorSets(validatorsAllowlist[i], registerParams);
|
||||
cheats.stopPrank();
|
||||
|
||||
console.log("Validator %s setup as operator", validatorsAllowlist[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function _buildValidatorSet(
|
||||
Loading…
Reference in a new issue