generated from BreadchainCoop/avs-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 2
204 Separate Script to Deposit and Register #212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Supeeerpower
merged 5 commits into
dev
from
204-separate-script-to-deposit-and-register
Jul 29, 2025
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
7da8964
script: separate deposit and register
Supeeerpower 3dda293
shell: bls register update
Supeeerpower 84b7ca1
chore: cli md update
Supeeerpower 55ab7c0
ci: bls register cli
Supeeerpower c427ff6
fix: waiting blocks in testnet
Supeeerpower File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
contracts/script/eigenlayer/bls/WavsDepositIntoStrategy.s.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| // SPDX-License-Identifier: UNLICENSED | ||
| pragma solidity ^0.8.27; | ||
|
|
||
| import {Script} from "forge-std/Script.sol"; | ||
|
|
||
| import {ReadCoreLib} from "./utils/ReadCoreLib.sol"; | ||
| import {WavsDepositIntoStrategyLib} from "./utils/WavsDepositIntoStrategyLib.sol"; | ||
|
|
||
| /** | ||
| * @title WavsDepositIntoStrategy | ||
| * @author Lay3rLabs | ||
| * @notice This script deposits into a WAVS strategy. | ||
| * @dev This script is used to deposit into a WAVS strategy. | ||
| */ | ||
| contract WavsDepositIntoStrategy is Script { | ||
| /// @notice The environment variable for the LST contract address. | ||
| string public constant ENV_LST_CONTRACT = "LST_CONTRACT_ADDRESS"; | ||
| /// @notice The environment variable for the LST strategy address. | ||
| string public constant ENV_LST_STRATEGY = "LST_STRATEGY_ADDRESS"; | ||
| /// @notice The environment variable for the amount to delegate. | ||
| string public constant ENV_AMOUNT = "WAVS_DELEGATE_AMOUNT"; | ||
|
|
||
| address private _strategyManager; | ||
| address private _delegationManager; | ||
| address private _lstContractAddress; | ||
| address private _lstStrategyAddress; | ||
| uint256 private _stakeAmount; | ||
|
|
||
| /// @notice The setup function for the script. | ||
| function setUp() public virtual { | ||
| ReadCoreLib.DeploymentData memory coreDeployment = | ||
| ReadCoreLib.readDeploymentJson("deployments/eigenlayer-core/", block.chainid); | ||
|
|
||
| _strategyManager = coreDeployment.strategyManager; | ||
| _delegationManager = coreDeployment.delegationManager; | ||
|
|
||
| // Get the configuration from environment | ||
| _lstContractAddress = vm.envAddress(ENV_LST_CONTRACT); | ||
| _lstStrategyAddress = vm.envAddress(ENV_LST_STRATEGY); | ||
| _stakeAmount = vm.envUint(ENV_AMOUNT); | ||
| } | ||
|
|
||
| /// @notice The run function for the script. | ||
| function run() external { | ||
| vm.startBroadcast(); | ||
|
|
||
| (, address operatorAddr,) = vm.readCallers(); | ||
|
|
||
| WavsDepositIntoStrategyLib.depositIntoStrategy( | ||
| _strategyManager, | ||
| _delegationManager, | ||
| _lstContractAddress, | ||
| _lstStrategyAddress, | ||
| operatorAddr, | ||
| _stakeAmount | ||
| ); | ||
|
|
||
| vm.stopBroadcast(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
119 changes: 119 additions & 0 deletions
119
contracts/script/eigenlayer/bls/utils/WavsDepositIntoStrategyLib.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| // SPDX-License-Identifier: MIT | ||
| pragma solidity ^0.8.27; | ||
|
|
||
| import {console2} from "forge-std/console2.sol"; | ||
| import {IStrategyManager} from "@eigenlayer/contracts/interfaces/IStrategyManager.sol"; | ||
| import {IDelegationManager} from "@eigenlayer/contracts/interfaces/IDelegationManager.sol"; | ||
| import {IStrategy} from "@eigenlayer/contracts/interfaces/IStrategy.sol"; | ||
| import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
| import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; | ||
|
|
||
| /** | ||
| * @title WavsDepositIntoStrategyLib | ||
| * @author Lay3rLabs | ||
| * @notice This library is used to deposit into a WAVS strategy. | ||
| * @dev This library is used to deposit into a WAVS strategy. | ||
| */ | ||
| library WavsDepositIntoStrategyLib { | ||
| using Strings for *; | ||
|
|
||
| /// @notice The error for the failed to approve LST tokens. | ||
| error WavsDepositIntoStrategy__FailedToApproveLSTTokens(); | ||
| /// @notice The error for the failed to mint LST tokens. | ||
| error WavsDepositIntoStrategy__FailedToMintLSTTokens(); | ||
|
|
||
| /** | ||
| * @notice The function to deposit into a strategy. | ||
| * @param _strategyManagerAddress The address of the strategy manager. | ||
| * @param _delegationManagerAddress The address of the delegation manager. | ||
| * @param _lstContractAddress The address of the LST contract. | ||
| * @param _lstStrategyAddress The address of the LST strategy. | ||
| * @param _operatorAddr The address of the operator. | ||
| * @param _stakeAmount The amount of LST to stake. | ||
| */ | ||
| function depositIntoStrategy( | ||
| address _strategyManagerAddress, | ||
| address _delegationManagerAddress, | ||
| address _lstContractAddress, | ||
| address _lstStrategyAddress, | ||
| address _operatorAddr, | ||
| uint256 _stakeAmount | ||
| ) internal { | ||
| IStrategyManager strategyManager = IStrategyManager(_strategyManagerAddress); | ||
| uint256 numDeposit = strategyManager.stakerStrategyListLength(_operatorAddr); | ||
| if (numDeposit == 0) { | ||
| // Check if operator already has LST balance | ||
| IERC20 lstToken = IERC20(_lstContractAddress); | ||
| uint256 lstBalance = lstToken.balanceOf(_operatorAddr); | ||
|
|
||
| // Only mint LSTs if operator has no balance | ||
| if (lstBalance < _stakeAmount) { | ||
| console2.log("Operator has insufficient LST balance, minting new tokens"); | ||
|
|
||
| uint256 amountToMint = _stakeAmount - lstBalance; | ||
|
|
||
| // Call the submit function on the LST contract with the operator as the referral | ||
| (bool success,) = _lstContractAddress.call{value: amountToMint}( | ||
| abi.encodeWithSignature("submit(address)", _operatorAddr) | ||
| ); | ||
| if (!success) { | ||
| revert WavsDepositIntoStrategy__FailedToMintLSTTokens(); | ||
| } | ||
|
|
||
| // Update the LST balance after minting | ||
| lstBalance = lstToken.balanceOf(_operatorAddr); | ||
| console2.log( | ||
| string.concat( | ||
| "Minted ", Strings.toString(lstBalance), " LST tokens for operator" | ||
| ) | ||
| ); | ||
| } else { | ||
| console2.log( | ||
| string.concat( | ||
| "Operator already has LST balance of ", Strings.toString(lstBalance) | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| // Approve the strategy manager to spend the LST tokens | ||
| bool approved = lstToken.approve(_strategyManagerAddress, _stakeAmount); | ||
| if (!approved) { | ||
| revert WavsDepositIntoStrategy__FailedToApproveLSTTokens(); | ||
| } | ||
| console2.log( | ||
| string.concat( | ||
| "Approved ", Strings.toString(_stakeAmount), " LST tokens for StrategyManager" | ||
| ) | ||
| ); | ||
|
|
||
| // Create a new deposit with the LSTs | ||
| console2.log( | ||
| string.concat( | ||
| "Creating new deposit for operator ", | ||
| Strings.toHexString(uint160(_operatorAddr), 20) | ||
| ) | ||
| ); | ||
| uint256 shares = strategyManager.depositIntoStrategy( | ||
| IStrategy(_lstStrategyAddress), lstToken, _stakeAmount | ||
| ); | ||
| console2.log( | ||
| string.concat("Created deposit with ", Strings.toString(shares), " shares") | ||
| ); | ||
| } else { | ||
| console2.log( | ||
| string.concat( | ||
| "Operator ", | ||
| Strings.toHexString(uint160(_operatorAddr), 20), | ||
| " already has deposits, skipping LST operations" | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| IDelegationManager delegationManager = IDelegationManager(_delegationManagerAddress); | ||
| if (!delegationManager.isDelegated(_operatorAddr)) { | ||
| // TODO: allow to override foo.bar with env variable? | ||
| delegationManager.registerAsOperator(address(0), 0, "foo.bar"); | ||
| console2.log("Registered operator as operator"); | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,19 +4,15 @@ pragma solidity ^0.8.27; | |
| import {console2} from "forge-std/Test.sol"; | ||
| import {Vm} from "forge-std/Vm.sol"; | ||
| import {stdJson} from "forge-std/StdJson.sol"; | ||
| import {IStrategyManager} from "@eigenlayer/contracts/interfaces/IStrategyManager.sol"; | ||
| import {IDelegationManager} from "@eigenlayer/contracts/interfaces/IDelegationManager.sol"; | ||
| import {IStrategy} from "@eigenlayer-middleware/src/interfaces/IECDSAStakeRegistry.sol"; | ||
| import { | ||
| IAllocationManagerTypes, | ||
| IAllocationManager | ||
| } from "@eigenlayer/contracts/interfaces/IAllocationManager.sol"; | ||
| import {OperatorSet} from "@eigenlayer/contracts/libraries/OperatorSetLib.sol"; | ||
| import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; | ||
| import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
|
|
||
| import {UpgradeableProxyLib} from "./UpgradeableProxyLib.sol"; | ||
| import {ReadCoreLib} from "./ReadCoreLib.sol"; | ||
| import {BLSKeyGenerator} from "./BLSKeyGenerator.sol"; | ||
|
|
||
| import { | ||
|
|
@@ -40,105 +36,9 @@ library WavsRegisterOperatorLib { | |
|
|
||
| Vm internal constant VM = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); | ||
|
|
||
| /// @notice The error for the failed to mint LST tokens. | ||
| error WavsRegisterOperatorLib__FailedToMintLSTTokens(); | ||
| /// @notice The error for the failed to approve LST tokens. | ||
| error WavsRegisterOperatorLib__FailedToApproveLSTTokens(); | ||
| /// @notice The error for the failed to get allocation configuration delay. | ||
| error WavsRegisterOperatorLib__FailedToGetAllocationConfigurationDelay(); | ||
|
|
||
| /** | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Taken from here? |
||
| * @notice The setup operator function. | ||
| * @param coreDeployment The core deployment data. | ||
| * @param lstContractAddress The LST contract address. | ||
| * @param lstStrategyAddress The LST strategy address. | ||
| * @param stakeAmount The stake amount. | ||
| */ | ||
| function setupOperator( | ||
| ReadCoreLib.DeploymentData memory coreDeployment, | ||
| address lstContractAddress, | ||
| address lstStrategyAddress, | ||
| uint256 stakeAmount | ||
| ) internal { | ||
| // This is the address for private key forge is running the script as. | ||
| // Calculated from the --private-key argument | ||
| (, address operatorAddr,) = VM.readCallers(); | ||
|
|
||
| IStrategyManager strategyManager = IStrategyManager(coreDeployment.strategyManager); | ||
| uint256 numDeposit = strategyManager.stakerStrategyListLength(operatorAddr); | ||
| if (numDeposit == 0) { | ||
| // Check if operator already has LST balance | ||
| IERC20 lstToken = IERC20(lstContractAddress); | ||
| uint256 lstBalance = lstToken.balanceOf(operatorAddr); | ||
|
|
||
| // Only mint LSTs if operator has no balance | ||
| if (lstBalance == 0) { | ||
| console2.log("Operator has no LST balance, minting new tokens"); | ||
|
|
||
| // Call the submit function on the LST contract with the operator as the referral | ||
| (bool success,) = lstContractAddress.call{value: stakeAmount}( | ||
| abi.encodeWithSignature("submit(address)", operatorAddr) | ||
| ); | ||
| if (!success) { | ||
| revert WavsRegisterOperatorLib__FailedToMintLSTTokens(); | ||
| } | ||
|
|
||
| // Update the LST balance after minting | ||
| lstBalance = lstToken.balanceOf(operatorAddr); | ||
| console2.log( | ||
| string.concat( | ||
| "Minted ", Strings.toString(lstBalance), " LST tokens for operator" | ||
| ) | ||
| ); | ||
| } else { | ||
| console2.log( | ||
| string.concat( | ||
| "Operator already has LST balance of ", Strings.toString(lstBalance) | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| // Approve the strategy manager to spend the LST tokens | ||
| bool approved = lstToken.approve(coreDeployment.strategyManager, stakeAmount); | ||
| if (!approved) { | ||
| revert WavsRegisterOperatorLib__FailedToApproveLSTTokens(); | ||
| } | ||
| console2.log( | ||
| string.concat( | ||
| "Approved ", Strings.toString(stakeAmount), " LST tokens for StrategyManager" | ||
| ) | ||
| ); | ||
|
|
||
| // Create a new deposit with the LSTs | ||
| console2.log( | ||
| string.concat( | ||
| "Creating new deposit for operator ", | ||
| Strings.toHexString(uint160(operatorAddr), 20) | ||
| ) | ||
| ); | ||
| uint256 shares = strategyManager.depositIntoStrategy( | ||
| IStrategy(lstStrategyAddress), lstToken, stakeAmount | ||
| ); | ||
| console2.log( | ||
| string.concat("Created deposit with ", Strings.toString(shares), " shares") | ||
| ); | ||
| } else { | ||
| console2.log( | ||
| string.concat( | ||
| "Operator ", | ||
| Strings.toHexString(uint160(operatorAddr), 20), | ||
| " already has deposits, skipping LST operations" | ||
| ) | ||
| ); | ||
| } | ||
|
|
||
| IDelegationManager delegationManager = IDelegationManager(coreDeployment.delegationManager); | ||
| if (!delegationManager.isDelegated(operatorAddr)) { | ||
| // TODO: allow to override foo.bar with env variable? | ||
| delegationManager.registerAsOperator(address(0), 0, "foo.bar"); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @notice The register to AVS function. | ||
| * @param operatorKey The operator key. | ||
|
|
@@ -160,14 +60,6 @@ library WavsRegisterOperatorLib { | |
| IAllocationManager allocationManager = IAllocationManager(allocationManagerAddress); | ||
| OperatorSet memory opSetQuery = OperatorSet({avs: serviceManagerAddress, id: 0}); | ||
| if (!allocationManager.isMemberOfOperatorSet(operatorAddr, opSetQuery)) { | ||
| (bool success, bytes memory result) = address(allocationManager).staticcall( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And the ugly workaround gone 😄 |
||
| abi.encodeWithSignature("ALLOCATION_CONFIGURATION_DELAY()") | ||
| ); | ||
| if (!success) { | ||
| revert WavsRegisterOperatorLib__FailedToGetAllocationConfigurationDelay(); | ||
| } | ||
| uint32 allocationConfigurationDelay = abi.decode(result, (uint32)); | ||
| VM.roll(block.number + allocationConfigurationDelay + 1); // Workaround for testnet, txs can't be in the same block | ||
| IStrategy[] memory strategies = new IStrategy[](1); | ||
| strategies[0] = IStrategy(lstStrategyAddress); | ||
| uint64[] memory newMagnitudes = new uint64[](1); | ||
|
|
||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay this is the code that was pulled out from the register lib, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes