diff --git a/contracts/contracts/strategies/NativeStaking/NativeStakingSSVStrategy.sol b/contracts/contracts/strategies/NativeStaking/NativeStakingSSVStrategy.sol index a26b110f29..f209fd36c1 100644 --- a/contracts/contracts/strategies/NativeStaking/NativeStakingSSVStrategy.sol +++ b/contracts/contracts/strategies/NativeStaking/NativeStakingSSVStrategy.sol @@ -74,6 +74,7 @@ contract NativeStakingSSVStrategy is /// @param _wethAddress Address of the Erc20 WETH Token contract /// @param _ssvToken Address of the Erc20 SSV Token contract /// @param _ssvNetwork Address of the SSV Network contract + /// @param _maxValidators Maximum number of validators that can be registered in the strategy /// @param _feeAccumulator Address of the fee accumulator receiving execution layer validator rewards /// @param _beaconChainDepositContract Address of the beacon chain deposit contract constructor( @@ -81,6 +82,7 @@ contract NativeStakingSSVStrategy is address _wethAddress, address _ssvToken, address _ssvNetwork, + uint256 _maxValidators, address _feeAccumulator, address _beaconChainDepositContract ) @@ -89,7 +91,8 @@ contract NativeStakingSSVStrategy is _wethAddress, _baseConfig.vaultAddress, _beaconChainDepositContract, - _ssvNetwork + _ssvNetwork, + _maxValidators ) { SSV_TOKEN_ADDRESS = _ssvToken; diff --git a/contracts/contracts/strategies/NativeStaking/ValidatorAccountant.sol b/contracts/contracts/strategies/NativeStaking/ValidatorAccountant.sol index 441d046ad2..b5afc86798 100644 --- a/contracts/contracts/strategies/NativeStaking/ValidatorAccountant.sol +++ b/contracts/contracts/strategies/NativeStaking/ValidatorAccountant.sol @@ -50,17 +50,20 @@ abstract contract ValidatorAccountant is ValidatorRegistrator { /// @param _vaultAddress Address of the Vault /// @param _beaconChainDepositContract Address of the beacon chain deposit contract /// @param _ssvNetwork Address of the SSV Network contract + /// @param _maxValidators Maximum number of validators that can be registered in the strategy constructor( address _wethAddress, address _vaultAddress, address _beaconChainDepositContract, - address _ssvNetwork + address _ssvNetwork, + uint256 _maxValidators ) ValidatorRegistrator( _wethAddress, _vaultAddress, _beaconChainDepositContract, - _ssvNetwork + _ssvNetwork, + _maxValidators ) {} diff --git a/contracts/contracts/strategies/NativeStaking/ValidatorRegistrator.sol b/contracts/contracts/strategies/NativeStaking/ValidatorRegistrator.sol index 2dc590f69f..1ef7acf4db 100644 --- a/contracts/contracts/strategies/NativeStaking/ValidatorRegistrator.sol +++ b/contracts/contracts/strategies/NativeStaking/ValidatorRegistrator.sol @@ -28,6 +28,8 @@ abstract contract ValidatorRegistrator is Governable, Pausable { address public immutable SSV_NETWORK_ADDRESS; /// @notice Address of the OETH Vault proxy contract address public immutable VAULT_ADDRESS; + /// @notice Maximum number of validators that can be registered in this strategy + uint256 public immutable MAX_VALIDATORS; /// @notice Address of the registrator - allowed to register, exit and remove validators address public validatorRegistrator; @@ -109,16 +111,19 @@ abstract contract ValidatorRegistrator is Governable, Pausable { /// @param _vaultAddress Address of the Vault /// @param _beaconChainDepositContract Address of the beacon chain deposit contract /// @param _ssvNetwork Address of the SSV Network contract + /// @param _maxValidators Maximum number of validators that can be registered in the strategy constructor( address _wethAddress, address _vaultAddress, address _beaconChainDepositContract, - address _ssvNetwork + address _ssvNetwork, + uint256 _maxValidators ) { WETH_TOKEN_ADDRESS = _wethAddress; BEACON_CHAIN_DEPOSIT_CONTRACT = _beaconChainDepositContract; SSV_NETWORK_ADDRESS = _ssvNetwork; VAULT_ADDRESS = _vaultAddress; + MAX_VALIDATORS = _maxValidators; } /// @notice Set the address of the registrator which can register, exit and remove validators @@ -163,6 +168,10 @@ abstract contract ValidatorRegistrator is Governable, Pausable { requiredETH <= IWETH9(WETH_TOKEN_ADDRESS).balanceOf(address(this)), "insufficient WETH" ); + require( + activeDepositedValidators + validators.length <= MAX_VALIDATORS, + "Max validators reached" + ); require( stakeETHTally + requiredETH <= stakeETHThreshold, diff --git a/contracts/deploy/deployActions.js b/contracts/deploy/deployActions.js index 7cb1faead7..63b7c9c8fd 100644 --- a/contracts/deploy/deployActions.js +++ b/contracts/deploy/deployActions.js @@ -854,6 +854,7 @@ const upgradeNativeStakingSSVStrategy = async () => { assetAddresses.WETH, // wethAddress assetAddresses.SSV, // ssvToken assetAddresses.SSVNetwork, // ssvNetwork + 600, // maxValidators cFeeAccumulatorProxy.address, // feeAccumulator assetAddresses.beaconChainDepositContract, // depositContractMock ] @@ -900,6 +901,7 @@ const deployNativeStakingSSVStrategy = async () => { assetAddresses.WETH, // wethAddress assetAddresses.SSV, // ssvToken assetAddresses.SSVNetwork, // ssvNetwork + 600, // maxValidators dFeeAccumulatorProxy.address, // feeAccumulator assetAddresses.beaconChainDepositContract, // depositContractMock ] diff --git a/contracts/deploy/holesky/012_upgrade_strategy.js b/contracts/deploy/holesky/012_upgrade_strategy.js new file mode 100644 index 0000000000..36d68e1e65 --- /dev/null +++ b/contracts/deploy/holesky/012_upgrade_strategy.js @@ -0,0 +1,18 @@ +const { upgradeNativeStakingSSVStrategy } = require("../deployActions"); + +const mainExport = async () => { + console.log("Running 012 deployment on Holesky..."); + + console.log("Upgrading native staking strategy"); + await upgradeNativeStakingSSVStrategy(); + + console.log("Running 012 deployment done"); + return true; +}; + +mainExport.id = "012_upgrade_strategy"; +mainExport.tags = []; +mainExport.dependencies = []; +mainExport.skip = () => false; + +module.exports = mainExport; diff --git a/contracts/deploy/mainnet/097_native_ssv_staking.js b/contracts/deploy/mainnet/097_native_ssv_staking.js index 64fa655a42..e00636c4aa 100644 --- a/contracts/deploy/mainnet/097_native_ssv_staking.js +++ b/contracts/deploy/mainnet/097_native_ssv_staking.js @@ -54,6 +54,7 @@ module.exports = deploymentWithGovernanceProposal( addresses.mainnet.WETH, // wethAddress addresses.mainnet.SSV, // ssvToken addresses.mainnet.SSVNetwork, // ssvNetwork + 600, // maxValidators dFeeAccumulatorProxy.address, // feeAccumulator addresses.mainnet.beaconChainDepositContract, // beacon chain deposit contract ]