datahaven/contracts/test/utils/SnowbridgeAndAVSDeployer.sol

227 lines
10 KiB
Solidity
Raw Permalink Normal View History

// 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";
import {AgentExecutor} from "snowbridge/src/AgentExecutor.sol";
import {Agent} from "snowbridge/src/Agent.sol";
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 {AVSDeployer} from "./AVSDeployer.sol";
Fix: 🏗️ Message encoding / decoding (#113) ## Summary of changes - We decided to remove the topics and nonce from the massage encoding since we don't use them (original commit: https://github.com/Moonsong-Labs/datahaven/commit/ee2a3f2fd432e0f8623a9798730ce697bfc52d34). - Besides, we already have a nonce at the Snowbridge message level https://github.com/Moonsong-Labs/datahaven/blob/f4ab5c2b2e93c775555ab4b8d0b2babaf5bc15b7/operator/primitives/snowbridge/inbound-queue/src/v2/message.rs#L105 - I had to recreate the static test for _encoding_ (happens in [DataHavenSnowbridgeMessages.sol](https://github.com/Moonsong-Labs/datahaven/blob/d12d40634f16eb9642b5b94cbc364b6679339393/contracts/src/libraries/DataHavenSnowbridgeMessages.sol) ) / _decoding_ (happens in [operator/primitives/bridge/src/lib.rs)](https://github.com/Moonsong-Labs/datahaven/blob/f9f9cc65fe33c86ac91f2097adbcb945b1746277/operator/primitives/bridge/src/lib.rs). Now it matches the current structure. The idea is that now we can test that we don't break the decoding in followup refactoring. - Fixes a problem with EigenLayer validator addresses. In all our contracts we were using `bytes32` to refer to a Solochain validator address. But on our Substrate change we actually expect AccountId20, so only 20 bytes. This was causing the decoding to fail. - I opted for the minimal change that would be to take the right-most 20 bytes to send that to our chain. But we might want aswell to limit our EigenLayer contracts to be only 20 bytes long. @ahmadkaouk showcase this [here](https://github.com/Moonsong-Labs/datahaven/commit/92a34c273ca439341bd8b61ff3592cef45ba4727) - Adds a bash script to run the static test. The test will compile the contracts, run the encoding test, compile the operator, and run the decoding test. This saves a huge amount of time since we don't need to run the full e2e setup. The way of running it is the following: ```bash cd operator/test/scripts ./test_message_encoding.sh ``` - As a consequence of this PR, the execution relayer now works properly. EDIT: > [!IMPORTANT] **We decided to use 20-byte addresses in our contracts**. So what is stated above is not valid anymore. The change implies that the mapping from Ethereum addresses to bytes32 addresses now it's a mapping as follows: https://github.com/Moonsong-Labs/datahaven/blob/dd3ba99ac0553a33448dc77efbbea08cacd278e6/contracts/src/DataHavenServiceManager.sol#L51-L52 I've updated helper functions, tests, etc to be compliant with this change. The execution relayer and beefy relayer look stable now. --------- Co-authored-by: Ahmad Kaouk <ahmadkaouk.93@gmail.com> Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
2025-07-16 07:38:58 +00:00
import {TestUtils} from "./TestUtils.sol";
fix: Resolve Foundry build errors and apply code formatting (#241) ## Summary Fixes the CI build failure in the `task-ts-build` workflow caused by Foundry v1.4.2's Solar linter not being able to resolve Snowbridge's context-specific import remappings. ## Problem The Snowbridge submodule uses context-specific remappings (prefixed with `:`) for its dependencies: - `lib/snowbridge/contracts/:openzeppelin/` → OpenZeppelin contracts - `lib/snowbridge/contracts/:prb/math/` → PRB Math library Foundry v1.4.2's Solar linter doesn't understand these context-specific remappings and fails with errors like: ``` error: file openzeppelin/utils/cryptography/MerkleProof.sol not found error: file prb/math/src/UD60x18.sol not found ``` ## Solution Added global remappings that the linter can understand: ```toml "openzeppelin/=lib/snowbridge/contracts/lib/openzeppelin-contracts/contracts/", "prb/math/=lib/snowbridge/contracts/lib/prb-math/", ``` ### Why This Works - The linter can now resolve `openzeppelin/` and `prb/math/` imports globally - These global remappings take **lower precedence** than context-specific ones during compilation - The compiler still uses the context-specific remappings (with `:`) when compiling Snowbridge contracts - The linter uses the global remappings when checking all files ## Changes ### Commit 1: Add global remappings - `contracts/foundry.toml`: Added 2 global remapping entries ### Commit 2: Apply forge fmt - Applied automatic formatting via `forge fmt` to ensure code style consistency - Multi-line formatting for long import statements and function signatures - No functional changes - purely formatting updates ## Testing ✅ Local build succeeds with `forge build` ✅ No Snowbridge import resolution errors ✅ `forge fmt --check` passes with no formatting issues ✅ Only linting notes/warnings remain (not errors) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
2025-10-20 08:20:59 +00:00
import {
IAllocationManagerTypes
} from "eigenlayer-contracts/src/contracts/interfaces/IAllocationManager.sol";
import {IStrategy} from "eigenlayer-contracts/src/contracts/interfaces/IStrategy.sol";
import {ValidatorsUtils} from "../../script/utils/ValidatorsUtils.sol";
import "forge-std/Test.sol";
contract SnowbridgeAndAVSDeployer is AVSDeployer {
// Snowbridge contracts
BeefyClient public beefyClient;
IGatewayV2 public gateway;
Gateway public gatewayImplementation;
AgentExecutor public agentExecutor;
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
Fix: 🏗️ Message encoding / decoding (#113) ## Summary of changes - We decided to remove the topics and nonce from the massage encoding since we don't use them (original commit: https://github.com/Moonsong-Labs/datahaven/commit/ee2a3f2fd432e0f8623a9798730ce697bfc52d34). - Besides, we already have a nonce at the Snowbridge message level https://github.com/Moonsong-Labs/datahaven/blob/f4ab5c2b2e93c775555ab4b8d0b2babaf5bc15b7/operator/primitives/snowbridge/inbound-queue/src/v2/message.rs#L105 - I had to recreate the static test for _encoding_ (happens in [DataHavenSnowbridgeMessages.sol](https://github.com/Moonsong-Labs/datahaven/blob/d12d40634f16eb9642b5b94cbc364b6679339393/contracts/src/libraries/DataHavenSnowbridgeMessages.sol) ) / _decoding_ (happens in [operator/primitives/bridge/src/lib.rs)](https://github.com/Moonsong-Labs/datahaven/blob/f9f9cc65fe33c86ac91f2097adbcb945b1746277/operator/primitives/bridge/src/lib.rs). Now it matches the current structure. The idea is that now we can test that we don't break the decoding in followup refactoring. - Fixes a problem with EigenLayer validator addresses. In all our contracts we were using `bytes32` to refer to a Solochain validator address. But on our Substrate change we actually expect AccountId20, so only 20 bytes. This was causing the decoding to fail. - I opted for the minimal change that would be to take the right-most 20 bytes to send that to our chain. But we might want aswell to limit our EigenLayer contracts to be only 20 bytes long. @ahmadkaouk showcase this [here](https://github.com/Moonsong-Labs/datahaven/commit/92a34c273ca439341bd8b61ff3592cef45ba4727) - Adds a bash script to run the static test. The test will compile the contracts, run the encoding test, compile the operator, and run the decoding test. This saves a huge amount of time since we don't need to run the full e2e setup. The way of running it is the following: ```bash cd operator/test/scripts ./test_message_encoding.sh ``` - As a consequence of this PR, the execution relayer now works properly. EDIT: > [!IMPORTANT] **We decided to use 20-byte addresses in our contracts**. So what is stated above is not valid anymore. The change implies that the mapping from Ethereum addresses to bytes32 addresses now it's a mapping as follows: https://github.com/Moonsong-Labs/datahaven/blob/dd3ba99ac0553a33448dc77efbbea08cacd278e6/contracts/src/DataHavenServiceManager.sol#L51-L52 I've updated helper functions, tests, etc to be compliant with this change. The execution relayer and beefy relayer look stable now. --------- Co-authored-by: Ahmad Kaouk <ahmadkaouk.93@gmail.com> Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
2025-07-16 07:38:58 +00:00
// The hashes of the initial (current) Validators in the DataHaven solochain.
bytes32[] public initialValidatorHashes;
// The hashes of the next Validators in the DataHaven solochain.
bytes32[] public nextValidatorHashes;
// In reality this should be set to MAX_SEED_LOOKAHEAD (4 epochs = 128 blocks/slots)
// https://eth2book.info/capella/part3/config/preset/#time-parameters
uint256 public constant RANDAO_COMMIT_DELAY = 4;
// In reality this is set to 24 blocks https://etherscan.io/address/0x6eD05bAa904df3DE117EcFa638d4CB84e1B8A00C#readContract#F10
uint256 public constant RANDAO_COMMIT_EXPIRATION = 24;
// In reality this is set to 17 https://etherscan.io/address/0x6eD05bAa904df3DE117EcFa638d4CB84e1B8A00C#readContract#F7
uint256 public constant MIN_NUM_REQUIRED_SIGNATURES = 2;
uint64 public constant START_BLOCK = 1;
bytes32 public constant REWARDS_MESSAGE_ORIGIN = bytes32(0);
bytes32 public constant WRONG_MESSAGE_ORIGIN = bytes32("wrong origin");
function _deployMockAllContracts() internal {
_deployMockSnowbridge();
_deployMockEigenLayerAndAVS();
_connectSnowbridgeToAVS();
}
function _setupValidatorsAsOperators() internal {
// Register the DataHaven service in the AllocationManager
cheats.prank(avsOwner);
serviceManager.updateAVSMetadataURI("");
// 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});
cheats.prank(avsOwner);
serviceManager.createOperatorSets(operatorSetParams);
// TODO: Implement the rest
}
function _deployMockSnowbridge() internal {
Fix: 🏗️ Message encoding / decoding (#113) ## Summary of changes - We decided to remove the topics and nonce from the massage encoding since we don't use them (original commit: https://github.com/Moonsong-Labs/datahaven/commit/ee2a3f2fd432e0f8623a9798730ce697bfc52d34). - Besides, we already have a nonce at the Snowbridge message level https://github.com/Moonsong-Labs/datahaven/blob/f4ab5c2b2e93c775555ab4b8d0b2babaf5bc15b7/operator/primitives/snowbridge/inbound-queue/src/v2/message.rs#L105 - I had to recreate the static test for _encoding_ (happens in [DataHavenSnowbridgeMessages.sol](https://github.com/Moonsong-Labs/datahaven/blob/d12d40634f16eb9642b5b94cbc364b6679339393/contracts/src/libraries/DataHavenSnowbridgeMessages.sol) ) / _decoding_ (happens in [operator/primitives/bridge/src/lib.rs)](https://github.com/Moonsong-Labs/datahaven/blob/f9f9cc65fe33c86ac91f2097adbcb945b1746277/operator/primitives/bridge/src/lib.rs). Now it matches the current structure. The idea is that now we can test that we don't break the decoding in followup refactoring. - Fixes a problem with EigenLayer validator addresses. In all our contracts we were using `bytes32` to refer to a Solochain validator address. But on our Substrate change we actually expect AccountId20, so only 20 bytes. This was causing the decoding to fail. - I opted for the minimal change that would be to take the right-most 20 bytes to send that to our chain. But we might want aswell to limit our EigenLayer contracts to be only 20 bytes long. @ahmadkaouk showcase this [here](https://github.com/Moonsong-Labs/datahaven/commit/92a34c273ca439341bd8b61ff3592cef45ba4727) - Adds a bash script to run the static test. The test will compile the contracts, run the encoding test, compile the operator, and run the decoding test. This saves a huge amount of time since we don't need to run the full e2e setup. The way of running it is the following: ```bash cd operator/test/scripts ./test_message_encoding.sh ``` - As a consequence of this PR, the execution relayer now works properly. EDIT: > [!IMPORTANT] **We decided to use 20-byte addresses in our contracts**. So what is stated above is not valid anymore. The change implies that the mapping from Ethereum addresses to bytes32 addresses now it's a mapping as follows: https://github.com/Moonsong-Labs/datahaven/blob/dd3ba99ac0553a33448dc77efbbea08cacd278e6/contracts/src/DataHavenServiceManager.sol#L51-L52 I've updated helper functions, tests, etc to be compliant with this change. The execution relayer and beefy relayer look stable now. --------- Co-authored-by: Ahmad Kaouk <ahmadkaouk.93@gmail.com> Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
2025-07-16 07:38:58 +00:00
// Generate validator arrays using the generator functions
initialValidatorHashes = TestUtils.generateMockValidators(10);
nextValidatorHashes = TestUtils.generateMockValidators(10, 10);
BeefyClient.ValidatorSet memory validatorSet =
ValidatorsUtils._buildValidatorSet(0, initialValidatorHashes);
Fix: 🏗️ Message encoding / decoding (#113) ## Summary of changes - We decided to remove the topics and nonce from the massage encoding since we don't use them (original commit: https://github.com/Moonsong-Labs/datahaven/commit/ee2a3f2fd432e0f8623a9798730ce697bfc52d34). - Besides, we already have a nonce at the Snowbridge message level https://github.com/Moonsong-Labs/datahaven/blob/f4ab5c2b2e93c775555ab4b8d0b2babaf5bc15b7/operator/primitives/snowbridge/inbound-queue/src/v2/message.rs#L105 - I had to recreate the static test for _encoding_ (happens in [DataHavenSnowbridgeMessages.sol](https://github.com/Moonsong-Labs/datahaven/blob/d12d40634f16eb9642b5b94cbc364b6679339393/contracts/src/libraries/DataHavenSnowbridgeMessages.sol) ) / _decoding_ (happens in [operator/primitives/bridge/src/lib.rs)](https://github.com/Moonsong-Labs/datahaven/blob/f9f9cc65fe33c86ac91f2097adbcb945b1746277/operator/primitives/bridge/src/lib.rs). Now it matches the current structure. The idea is that now we can test that we don't break the decoding in followup refactoring. - Fixes a problem with EigenLayer validator addresses. In all our contracts we were using `bytes32` to refer to a Solochain validator address. But on our Substrate change we actually expect AccountId20, so only 20 bytes. This was causing the decoding to fail. - I opted for the minimal change that would be to take the right-most 20 bytes to send that to our chain. But we might want aswell to limit our EigenLayer contracts to be only 20 bytes long. @ahmadkaouk showcase this [here](https://github.com/Moonsong-Labs/datahaven/commit/92a34c273ca439341bd8b61ff3592cef45ba4727) - Adds a bash script to run the static test. The test will compile the contracts, run the encoding test, compile the operator, and run the decoding test. This saves a huge amount of time since we don't need to run the full e2e setup. The way of running it is the following: ```bash cd operator/test/scripts ./test_message_encoding.sh ``` - As a consequence of this PR, the execution relayer now works properly. EDIT: > [!IMPORTANT] **We decided to use 20-byte addresses in our contracts**. So what is stated above is not valid anymore. The change implies that the mapping from Ethereum addresses to bytes32 addresses now it's a mapping as follows: https://github.com/Moonsong-Labs/datahaven/blob/dd3ba99ac0553a33448dc77efbbea08cacd278e6/contracts/src/DataHavenServiceManager.sol#L51-L52 I've updated helper functions, tests, etc to be compliant with this change. The execution relayer and beefy relayer look stable now. --------- Co-authored-by: Ahmad Kaouk <ahmadkaouk.93@gmail.com> Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com>
2025-07-16 07:38:58 +00:00
BeefyClient.ValidatorSet memory nextValidatorSet =
ValidatorsUtils._buildValidatorSet(1, nextValidatorHashes);
cheats.prank(regularDeployer);
beefyClient = new BeefyClient(
RANDAO_COMMIT_DELAY,
RANDAO_COMMIT_EXPIRATION,
MIN_NUM_REQUIRED_SIGNATURES,
START_BLOCK,
validatorSet,
nextValidatorSet
);
console.log("BeefyClient deployed at", address(beefyClient));
cheats.prank(regularDeployer);
agentExecutor = new AgentExecutor();
console.log("AgentExecutor deployed at", address(agentExecutor));
cheats.prank(regularDeployer);
gatewayImplementation = new Gateway(address(beefyClient), address(agentExecutor));
console.log("GatewayImplementation deployed at", address(gatewayImplementation));
OperatingMode defaultOperatingMode = OperatingMode.Normal;
Initializer.Config memory config = Initializer.Config({
mode: defaultOperatingMode,
deliveryCost: 1, // This is for v1, we don't really care about this
registerTokenFee: 1, // This is for v1, we don't really care about this
assetHubCreateAssetFee: 1, // This is for v1, we don't really care about this
assetHubReserveTransferFee: 1, // This is for v1, we don't really care about this
exchangeRate: ud60x18(1), // This is for v1, we don't really care about this
multiplier: ud60x18(1), // This is for v1, we don't really care about this
foreignTokenDecimals: 18, // This is for v1, we don't really care about this
maxDestinationFee: 1 // This is for v1, we don't really care about this
});
cheats.prank(regularDeployer);
gateway = IGatewayV2(
address(new GatewayProxy(address(gatewayImplementation), abi.encode(config)))
);
console.log("Gateway deployed at", address(gateway));
}
function _connectSnowbridgeToAVS() internal {
cheats.prank(regularDeployer);
gateway.v2_createAgent(REWARDS_MESSAGE_ORIGIN);
// Get the agent address after creation.
address payable agentAddress = payable(gateway.agentOf(REWARDS_MESSAGE_ORIGIN));
rewardsAgent = Agent(agentAddress);
console.log("Rewards agent deployed at", address(rewardsAgent));
cheats.prank(avsOwner);
serviceManager.setRewardsAgent(0, address(rewardsAgent));
console.log("Rewards agent set for operator set 0");
cheats.prank(regularDeployer);
gateway.v2_createAgent(WRONG_MESSAGE_ORIGIN);
// 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();
fix: Resolve Foundry build errors and apply code formatting (#241) ## Summary Fixes the CI build failure in the `task-ts-build` workflow caused by Foundry v1.4.2's Solar linter not being able to resolve Snowbridge's context-specific import remappings. ## Problem The Snowbridge submodule uses context-specific remappings (prefixed with `:`) for its dependencies: - `lib/snowbridge/contracts/:openzeppelin/` → OpenZeppelin contracts - `lib/snowbridge/contracts/:prb/math/` → PRB Math library Foundry v1.4.2's Solar linter doesn't understand these context-specific remappings and fails with errors like: ``` error: file openzeppelin/utils/cryptography/MerkleProof.sol not found error: file prb/math/src/UD60x18.sol not found ``` ## Solution Added global remappings that the linter can understand: ```toml "openzeppelin/=lib/snowbridge/contracts/lib/openzeppelin-contracts/contracts/", "prb/math/=lib/snowbridge/contracts/lib/prb-math/", ``` ### Why This Works - The linter can now resolve `openzeppelin/` and `prb/math/` imports globally - These global remappings take **lower precedence** than context-specific ones during compilation - The compiler still uses the context-specific remappings (with `:`) when compiling Snowbridge contracts - The linter uses the global remappings when checking all files ## Changes ### Commit 1: Add global remappings - `contracts/foundry.toml`: Added 2 global remapping entries ### Commit 2: Apply forge fmt - Applied automatic formatting via `forge fmt` to ensure code style consistency - Multi-line formatting for long import statements and function signatures - No functional changes - purely formatting updates ## Testing ✅ Local build succeeds with `forge build` ✅ No Snowbridge import resolution errors ✅ `forge fmt --check` passes with no formatting issues ✅ Only linting notes/warnings remain (not errors) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <noreply@anthropic.com>
2025-10-20 08:20:59 +00:00
IAllocationManagerTypes.RegisterParams memory registerParams =
IAllocationManagerTypes.RegisterParams({
avs: address(serviceManager),
operatorSetIds: operatorSetIds,
data: abi.encodePacked(address(uint160(uint256(initialValidatorHashes[i]))))
});
allocationManager.registerForOperatorSets(validatorsAllowlist[i], registerParams);
cheats.stopPrank();
console.log("Validator %s setup as operator", validatorsAllowlist[i]);
}
}
}