datahaven/contracts/script/transact/SignUpOperatorBase.s.sol

173 lines
6.8 KiB
Solidity
Raw Permalink Normal View History

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.27;
// EigenLayer imports
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 {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 validators
*/
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++) {
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
IERC20 linkedToken = StrategyBase(deployedStrategies[i].strategy).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);
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
strategyManager.depositIntoStrategy(
deployedStrategies[i].strategy, 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++) {
feat(contracts): ✨ add set up validator script and execute it when starting integration tests (#47) This PR adds the `setup-validators` Typescript script that, given an already started up network, sets up a new validator set and sends it through Snowbridge's Gateway to the solochain. To accomplish that purpose, this PR: - Modifies the `DeployLocal` script to save in the `anvil.json` file not only the deployed strategies' addresses but also the owner of each strategy's underlying token. This owner is used as the source of funds to transfer tokens to other validators so they can register under that strategy. - Adds an `OPERATOR_SOLOCHAIN_ADDRESS` to the `Accounts` utility script contract. This address is the one used as the Solochain address when registering a new Operator. - Updates the `SignUpOperator` (which I believe is now deprecated since we have multiple Operator Sets) and `SignUpOperatorBase` scripts to adapt to both aforementioned changes. - Updates the `ELScriptStorage` script to save the new extra information of each deployed strategy (the creator of the underlying token) in storage. - Adds a `validator-set.json` file which contains the validators that should be registered in the AVS and sent to the Solochain network through the Snowbridge Gateway when starting any integration test. This is currently hardcoded but could be generated in any other way, giving us flexibility for testing. - Adds both a Markdown file and a Excalidraw diagram showcasing both how the setup of integration tests work and possible integration tests that will be added in a future PR. This list is not exahustive as there are many more scenarios we will want to test using integration tests. - Updates the `e2e-cli.ts` script to execute the validator setup when bootstrapping the network used for integration testing. --------- Co-authored-by: Facundo Farall <37149322+ffarall@users.noreply.github.com>
2025-04-22 19:49:51 +00:00
uint256 operatorShares =
delegation.operatorShares(_operator, deployedStrategies[i].strategy);
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();
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(_operatorSolochainAddress)
});
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();
}
}