diff --git a/contracts/contracts/strategies/NativeStaking/ValidatorRegistrator.sol b/contracts/contracts/strategies/NativeStaking/ValidatorRegistrator.sol index 1289adfc3a..5b8eaec184 100644 --- a/contracts/contracts/strategies/NativeStaking/ValidatorRegistrator.sol +++ b/contracts/contracts/strategies/NativeStaking/ValidatorRegistrator.sol @@ -51,7 +51,6 @@ abstract contract ValidatorRegistrator is Governable, Pausable { /// @notice Amount of ETH that has been staked since the `stakingMonitor` last called `resetStakeETHTally`. /// This can not go above `stakeETHThreshold`. uint256 public stakeETHTally; - // For future use uint256[47] private __gap; @@ -231,6 +230,7 @@ abstract contract ValidatorRegistrator is Governable, Pausable { /// @param sharesData The shares data for each validator /// @param ssvAmount The amount of SSV tokens to be deposited to the SSV cluster /// @param cluster The SSV cluster details including the validator count and SSV balance + // slither-disable-start reentrancy-no-eth function registerSsvValidators( bytes[] calldata publicKeys, uint64[] calldata operatorIds, @@ -267,86 +267,66 @@ abstract contract ValidatorRegistrator is Governable, Pausable { ); } - /// @notice Exit validators from the Beacon chain. + // slither-disable-end reentrancy-no-eth + + /// @notice Exit a validator from the Beacon chain. /// The staked ETH will eventually swept to this native staking strategy. /// Only the registrator can call this function. - /// @param publicKeys List of SSV validator public keys + /// @param publicKey The public key of the validator /// @param operatorIds The operator IDs of the SSV Cluster - function exitSsvValidators( - bytes[] calldata publicKeys, + // slither-disable-start reentrancy-no-eth + function exitSsvValidator( + bytes calldata publicKey, uint64[] calldata operatorIds - ) external onlyRegistrator whenNotPaused nonReentrant { - ISSVNetwork(SSV_NETWORK).bulkExitValidator(publicKeys, operatorIds); - - bytes32 pubKeyHash; - VALIDATOR_STATE currentState; - for (uint256 i = 0; i < publicKeys.length; ++i) { - pubKeyHash = keccak256(publicKeys[i]); - currentState = validatorsStates[pubKeyHash]; + ) external onlyRegistrator whenNotPaused { + bytes32 pubKeyHash = keccak256(publicKey); + VALIDATOR_STATE currentState = validatorsStates[pubKeyHash]; + require(currentState == VALIDATOR_STATE.STAKED, "Validator not staked"); - // Check each validator has not already been staked. - // This would normally be done before the external call but is after - // so only one for loop of the validators is needed. - require( - currentState == VALIDATOR_STATE.STAKED, - "Validator not staked" - ); + ISSVNetwork(SSV_NETWORK).exitValidator(publicKey, operatorIds); - // Store the new validator state - validatorsStates[pubKeyHash] = VALIDATOR_STATE.EXITING; + validatorsStates[pubKeyHash] = VALIDATOR_STATE.EXITING; - emit SSVValidatorExitInitiated( - pubKeyHash, - publicKeys[i], - operatorIds - ); - } + emit SSVValidatorExitInitiated(pubKeyHash, publicKey, operatorIds); } - /// @notice Remove validators from the SSV Cluster. + // slither-disable-end reentrancy-no-eth + + /// @notice Remove a validator from the SSV Cluster. /// Make sure `exitSsvValidator` is called before and the validate has exited the Beacon chain. /// If removed before the validator has exited the beacon chain will result in the validator being slashed. /// Only the registrator can call this function. - /// @param publicKeys List of SSV validator public keys + /// @param publicKey The public key of the validator /// @param operatorIds The operator IDs of the SSV Cluster /// @param cluster The SSV cluster details including the validator count and SSV balance - function removeSsvValidators( - bytes[] calldata publicKeys, + // slither-disable-start reentrancy-no-eth + function removeSsvValidator( + bytes calldata publicKey, uint64[] calldata operatorIds, Cluster calldata cluster - ) external onlyRegistrator whenNotPaused nonReentrant { - ISSVNetwork(SSV_NETWORK).bulkRemoveValidator( - publicKeys, + ) external onlyRegistrator whenNotPaused { + bytes32 pubKeyHash = keccak256(publicKey); + VALIDATOR_STATE currentState = validatorsStates[pubKeyHash]; + // Can remove SSV validators that were incorrectly registered and can not be deposited to. + require( + currentState == VALIDATOR_STATE.EXITING || + currentState == VALIDATOR_STATE.REGISTERED, + "Validator not regd or exiting" + ); + + ISSVNetwork(SSV_NETWORK).removeValidator( + publicKey, operatorIds, cluster ); - bytes32 pubKeyHash; - VALIDATOR_STATE currentState; - for (uint256 i = 0; i < publicKeys.length; ++i) { - pubKeyHash = keccak256(publicKeys[i]); - currentState = validatorsStates[pubKeyHash]; - - // Check each validator is either registered or exited. - // This would normally be done before the external call but is after - // so only one for loop of the validators is needed. - require( - currentState == VALIDATOR_STATE.EXITING || - currentState == VALIDATOR_STATE.REGISTERED, - "Validator not regd or exiting" - ); - - // Store the new validator state - validatorsStates[pubKeyHash] = VALIDATOR_STATE.EXIT_COMPLETE; + validatorsStates[pubKeyHash] = VALIDATOR_STATE.EXIT_COMPLETE; - emit SSVValidatorExitCompleted( - pubKeyHash, - publicKeys[i], - operatorIds - ); - } + emit SSVValidatorExitCompleted(pubKeyHash, publicKey, operatorIds); } + // slither-disable-end reentrancy-no-eth + /// @notice Deposits more SSV Tokens to the SSV Network contract which is used to pay the SSV Operators. /// @dev A SSV cluster is defined by the SSVOwnerAddress and the set of operatorIds. /// uses "onlyStrategist" modifier so continuous front-running can't DOS our maintenance service diff --git a/contracts/deploy/mainnet/153_upgrade_native_staking.js b/contracts/deploy/mainnet/153_upgrade_native_staking.js index 6d27b9950b..f6eda1dd2a 100644 --- a/contracts/deploy/mainnet/153_upgrade_native_staking.js +++ b/contracts/deploy/mainnet/153_upgrade_native_staking.js @@ -11,7 +11,7 @@ module.exports = deploymentWithGovernanceProposal( deployerIsProposer: false, // proposalId: "", }, - async ({ deployWithConfirmation, ethers }) => { + async ({ ethers }) => { // Current contracts const cVaultProxy = await ethers.getContract("OETHVaultProxy"); const cVaultAdmin = await ethers.getContractAt( @@ -21,91 +21,28 @@ module.exports = deploymentWithGovernanceProposal( // Deployer Actions // ---------------- - // 1. Fetch the Native Strategy proxies - const cNativeStakingStrategyProxy_2 = await ethers.getContract( - "NativeStakingSSVStrategy2Proxy" - ); - const cNativeStakingStrategyProxy_3 = await ethers.getContract( - "NativeStakingSSVStrategy3Proxy" - ); - - // 2. Fetch the Fee Accumulator proxies - const cFeeAccumulatorProxy_2 = await ethers.getContract( - "NativeStakingFeeAccumulator2Proxy" - ); - const cFeeAccumulatorProxy_3 = await ethers.getContract( - "NativeStakingFeeAccumulator3Proxy" - ); - - // 3. Deploy the new Native Staking Strategy implementation - const dNativeStakingStrategyImpl_2 = await deployWithConfirmation( - "NativeStakingSSVStrategy", - [ - [addresses.zero, cVaultProxy.address], //_baseConfig - addresses.mainnet.WETH, // wethAddress - addresses.mainnet.SSV, // ssvToken - addresses.mainnet.SSVNetwork, // ssvNetwork - 500, // maxValidators - cFeeAccumulatorProxy_2.address, // feeAccumulator - addresses.mainnet.beaconChainDepositContract, // beacon chain deposit contract - ] - ); - console.log( - `Deployed 2nd NativeStakingSSVStrategy ${dNativeStakingStrategyImpl_2.address}` - ); - - const dNativeStakingStrategyImpl_3 = await deployWithConfirmation( - "NativeStakingSSVStrategy", - [ - [addresses.zero, cVaultProxy.address], //_baseConfig - addresses.mainnet.WETH, // wethAddress - addresses.mainnet.SSV, // ssvToken - addresses.mainnet.SSVNetwork, // ssvNetwork - 500, // maxValidators - cFeeAccumulatorProxy_3.address, // feeAccumulator - addresses.mainnet.beaconChainDepositContract, // beacon chain deposit contract - ], - undefined, - true // skipUpgradeSafety - ); - console.log( - `Deployed 3rd NativeStakingSSVStrategy ${dNativeStakingStrategyImpl_3.address}` - ); - - // 4. Deploy the new Compounding Staking Strategy contracts + // 1. Deploy the new Compounding Staking Strategy contracts const cCompoundingStakingStrategy = await deployCompoundingStakingSSVStrategy(); // Governance Actions // ---------------- return { - name: `Upgrade the existing Native Staking Strategies and deploy new Compounding Staking Strategy`, + name: `Deploy new Compounding Staking Strategy that uses compounding validators`, actions: [ - // 1. Upgrade the second Native Staking Strategy - { - contract: cNativeStakingStrategyProxy_2, - signature: "upgradeTo(address)", - args: [dNativeStakingStrategyImpl_2.address], - }, - // 2. Upgrade the third Native Staking Strategy - { - contract: cNativeStakingStrategyProxy_3, - signature: "upgradeTo(address)", - args: [dNativeStakingStrategyImpl_3.address], - }, - // 3. Add new strategy to vault + // 1. Add new strategy to vault { contract: cVaultAdmin, signature: "approveStrategy(address)", args: [cCompoundingStakingStrategy.address], }, - // 4. set harvester to the Defender Relayer + // 2. set harvester to the Defender Relayer { contract: cCompoundingStakingStrategy, signature: "setHarvesterAddress(address)", args: [addresses.mainnet.validatorRegistrator], }, - // 5. set validator registrator to the Defender Relayer + // 3. set validator registrator to the Defender Relayer { contract: cCompoundingStakingStrategy, signature: "setRegistrator(address)", diff --git a/contracts/tasks/ssv.js b/contracts/tasks/ssv.js index 6282844ae6..688a9c1c95 100644 --- a/contracts/tasks/ssv.js +++ b/contracts/tasks/ssv.js @@ -1,4 +1,4 @@ -const { parseUnits, formatUnits, hexlify } = require("ethers/lib/utils"); +const { parseUnits, formatUnits } = require("ethers/lib/utils"); const addresses = require("../utils/addresses"); const { resolveContract } = require("../utils/resolvers"); @@ -10,11 +10,11 @@ const { resolveNativeStakingStrategyProxy } = require("./validator"); const log = require("../utils/logger")("task:ssv"); -async function removeValidators({ index, pubkeys, operatorids }) { +async function removeValidator({ index, pubkey, operatorids }) { const signer = await getSigner(); log(`Splitting operator IDs ${operatorids}`); - const operatorIds = await sortOperatorIds(operatorids); + const operatorIds = operatorids.split(",").map((id) => parseInt(id)); const strategy = await resolveNativeStakingStrategyProxy(index); @@ -28,14 +28,11 @@ async function removeValidators({ index, pubkeys, operatorids }) { ownerAddress: strategy.address, }); - log(`Splitting public keys ${pubkeys}`); - const pubKeys = pubkeys.split(",").map((pubkey) => hexlify(pubkey)); - - log(`About to remove validators: ${pubKeys}`); + log(`About to remove validator: ${pubkey}`); const tx = await strategy .connect(signer) - .removeSsvValidators(pubKeys, operatorIds, cluster); - await logTxDetails(tx, "removeSsvValidators"); + .removeSsvValidator(pubkey, operatorIds, cluster); + await logTxDetails(tx, "removeSsvValidator"); } const printClusterInfo = async (options) => { @@ -121,5 +118,5 @@ module.exports = { printClusterInfo, depositSSV, withdrawSSV, - removeValidators, + removeValidator, }; diff --git a/contracts/tasks/tasks.js b/contracts/tasks/tasks.js index 5854e417b1..b9eb69a901 100644 --- a/contracts/tasks/tasks.js +++ b/contracts/tasks/tasks.js @@ -70,7 +70,7 @@ const { depositSSV, withdrawSSV, printClusterInfo, - removeValidators, + removeValidator: removeOldValidator, } = require("./ssv"); const { amoStrategyTask, @@ -92,7 +92,7 @@ const { } = require("./strategy"); const { validatorOperationsConfig, - exitValidators, + exitValidator, doAccounting, manuallyFixAccounting, resetStakeETHTally, @@ -123,6 +123,7 @@ const { const { registerValidators, stakeValidators } = require("../utils/validator"); const { harvestAndSwap } = require("./harvest"); const { deployForceEtherSender, forceSend } = require("./simulation"); +const { sleep } = require("../utils/time"); const { lzBridgeToken, lzSetConfig } = require("./layerzero"); const { requestValidatorWithdraw, @@ -1215,10 +1216,10 @@ task("stakeValidators").setAction(async (_, __, runSuper) => { return runSuper(); }); -subtask("exitValidators", "Starts the exit process from validators") +subtask("exitValidator", "Starts the exit process from a validator") .addParam( - "pubkeys", - "Comma separated validator public keys", + "pubkey", + "Public key of the validator to exit", undefined, types.string ) @@ -1236,25 +1237,62 @@ subtask("exitValidators", "Starts the exit process from validators") ) .setAction(async (taskArgs) => { const signer = await getSigner(); - await exitValidators({ ...taskArgs, signer }); + await exitValidator({ ...taskArgs, signer }); }); -task("exitValidators").setAction(async (_, __, runSuper) => { +task("exitValidator").setAction(async (_, __, runSuper) => { return runSuper(); }); -subtask( - "removeValidators", - "Removes validators from the SSV cluster after they have exited the beacon chain" -) +subtask("exitValidators", "Starts the exit process from a list of validators") + .addParam( + "pubkeys", + "Comma separated list of validator public keys", + undefined, + types.string + ) + .addParam( + "operatorids", + "Comma separated operator ids. E.g. 342,343,344,345", + undefined, + types.string + ) .addOptionalParam( "index", "The number of the Native Staking Contract deployed.", undefined, types.int ) + .addOptionalParam( + "sleep", + "Seconds between each tx so the SSV API can be updated before getting the cluster data.", + 30, + types.int + ) + .setAction(async (taskArgs) => { + const signer = await getSigner(); + + // Split the comma separated list of public keys + const pubKeys = taskArgs.pubkeys.split(","); + // For each public key + for (const pubkey of pubKeys) { + log(`About to exit validator with pubkey: ${pubkey}`); + await exitValidator({ ...taskArgs, pubkey, signer }); + + // wait for the SSV API can be updated + await sleep(taskArgs.sleep * 1000); + } + }); +task("exitValidators").setAction(async (_, __, runSuper) => { + return runSuper(); +}); + +subtask( + "removeValidators", + "Removes validators from the SSV cluster after they have exited the beacon chain" +) .addParam( "pubkeys", - "Comma separated validator public keys", + "Comma separated list of validator public keys", undefined, types.string ) @@ -1264,9 +1302,31 @@ subtask( undefined, types.string ) + .addOptionalParam( + "index", + "The number of the Native Staking Contract deployed.", + undefined, + types.int + ) + .addOptionalParam( + "sleep", + "Seconds between each tx so the SSV API can be updated before getting the cluster data.", + 30, + types.int + ) .setAction(async (taskArgs) => { const signer = await getSigner(); - await removeValidators({ ...taskArgs, signer }); + + // Split the comma separated list of public keys + const pubKeys = taskArgs.pubkeys.split(","); + // For each public key + for (const pubkey of pubKeys) { + log(`About to remove validator with pubkey: ${pubkey}`); + await removeOldValidator({ ...taskArgs, pubkey, signer }); + + // wait for the SSV API can be updated + await sleep(taskArgs.sleep * 1000); + } }); task("removeValidators").setAction(async (_, __, runSuper) => { return runSuper(); diff --git a/contracts/tasks/validator.js b/contracts/tasks/validator.js index e2e4912304..1dfd270a56 100644 --- a/contracts/tasks/validator.js +++ b/contracts/tasks/validator.js @@ -1,4 +1,4 @@ -const { formatUnits, hexlify, parseEther } = require("ethers").utils; +const { formatUnits, parseEther } = require("ethers").utils; const { KeyValueStoreClient, } = require("@openzeppelin/defender-kvstore-client"); @@ -92,26 +92,27 @@ const validatorOperationsConfig = async (taskArgs) => { // @dev check validator is eligible for exit - // has been active for at least 256 epochs -async function verifyMinActivationTimes({ pubkeys }) { +async function verifyMinActivationTime({ pubkey }) { const latestEpoch = await getEpoch("latest"); + const validator = await getValidator(pubkey); - log(`Splitting public keys ${pubkeys}`); - const pubKeys = pubkeys.split(",").map((id) => hexlify(id)); + const epochDiff = latestEpoch.epoch - validator.activationepoch; - for (const pubkey of pubKeys) { - const validator = await getValidator(pubkey); - - const epochDiff = latestEpoch.epoch - validator.activationepoch; - - if (epochDiff < 256) { - throw new Error( - `Can not exit validator. Validator needs to be ` + - `active for 256 epoch. ${pubkey} has only been active for ${epochDiff}` - ); - } + if (epochDiff < 256) { + throw new Error( + `Can not exit validator. Validator needs to be ` + + `active for 256 epoch. Current one active for ${epochDiff}` + ); } } +const checkPubkeyFormat = (pubkey) => { + if (!pubkey.startsWith("0x")) { + pubkey = `0x${pubkey}`; + } + return pubkey; +}; + async function getValidatorBalances({ pubkeys }) { const validator = await getValidators(pubkeys); @@ -143,21 +144,21 @@ async function snapValidators({ pubkeys }) { } } -async function exitValidators({ index, pubkeys, operatorids, signer }) { - await verifyMinActivationTimes({ pubkeys }); +async function exitValidator({ index, pubkey, operatorids, signer }) { + await verifyMinActivationTime({ pubkey }); log(`Splitting operator IDs ${operatorids}`); const operatorIds = operatorids.split(",").map((id) => parseInt(id)); const strategy = await resolveNativeStakingStrategyProxy(index); - const pubKeys = pubkeys.split(",").map((pubkey) => hexlify(pubkey)); + pubkey = checkPubkeyFormat(pubkey); - log(`About to exit validators: ${pubKeys}`); + log(`About to exit validator ${pubkey}`); const tx = await strategy .connect(signer) - .exitSsvValidators(pubKeys, operatorIds); - await logTxDetails(tx, "exitSsvValidators"); + .exitSsvValidator(pubkey, operatorIds); + await logTxDetails(tx, "exitSsvValidator"); } async function doAccounting({ signer, nativeStakingStrategy }) { @@ -357,7 +358,7 @@ const resolveFeeAccumulatorProxy = async (index) => { module.exports = { validatorOperationsConfig, - exitValidators, + exitValidator, doAccounting, resetStakeETHTally, setStakeETHThreshold, diff --git a/contracts/test/behaviour/ssvStrategy.js b/contracts/test/behaviour/ssvStrategy.js index 09b3f6a1cd..534e8e148d 100644 --- a/contracts/test/behaviour/ssvStrategy.js +++ b/contracts/test/behaviour/ssvStrategy.js @@ -41,14 +41,6 @@ const { setERC20TokenBalance } = require("../_fund"); depositDataRoot: "0x3f327f69bb527386ff4c2f820e6e375fcc632b1b7ee826bd53d4d2807cfd6769", }, - activeValidators: { - publicKeys: [ - "0x80555037820e8afe44a45ed6d43fd4184f14f2ebcac2beaad382ed7e3dac52f87241d5ed8683a8101d8f49b0dbb6bc0e", - "0xb9588334499ee49ac5a1472424e968fe589362b419d9ed09a172f635727466780e11553fbfef1166de3438e9495d7257", - "0xaff707ce005f75d9c8b6b20a170c314219f6596e2fa043c99de0a50565d79155c4ce1ecf98742cd3fdbb878c3762e78b", - ], - operatorIds: [752, 753, 754, 755], - }, })); */ @@ -162,7 +154,7 @@ const shouldBehaveLikeAnSsvStrategy = (context) => { }); }); - describe("Validator register and stake operations", function () { + describe("Validator operations", function () { const stakeAmount = oethUnits("32"); const depositToStrategy = async (amount) => { const { weth, domen, nativeStakingSSVStrategy, oethVault } = @@ -396,7 +388,7 @@ const shouldBehaveLikeAnSsvStrategy = (context) => { await registerAndStakeEth(); }); - it("Should remove registered validator by validator registrator", async () => { + it("Should exit and remove validator by validator registrator", async () => { const { ssv, nativeStakingSSVStrategy, @@ -441,10 +433,32 @@ const shouldBehaveLikeAnSsvStrategy = (context) => { ); const { cluster: newCluster } = ValidatorAddedEvent.args; + // Stake 32 ETH to the new validator + await nativeStakingSSVStrategy.connect(validatorRegistrator).stakeEth([ + { + pubkey: testValidator.publicKey, + signature: testValidator.signature, + depositDataRoot: testValidator.depositDataRoot, + }, + ]); + + // exit validator from SSV network + const exitTx = await nativeStakingSSVStrategy + .connect(validatorRegistrator) + .exitSsvValidator(testValidator.publicKey, testValidator.operatorIds); + + await expect(exitTx) + .to.emit(nativeStakingSSVStrategy, "SSVValidatorExitInitiated") + .withArgs( + keccak256(testValidator.publicKey), + testValidator.publicKey, + testValidator.operatorIds + ); + const removeTx = await nativeStakingSSVStrategy .connect(validatorRegistrator) - .removeSsvValidators( - [testValidator.publicKey], + .removeSsvValidator( + testValidator.publicKey, testValidator.operatorIds, newCluster ); @@ -457,54 +471,66 @@ const shouldBehaveLikeAnSsvStrategy = (context) => { testValidator.operatorIds ); }); - }); - describe("Validator exit and remove operations", function () { - it("Should exit and remove validator by validator registrator", async () => { + it("Should remove registered validator by validator registrator", async () => { const { + ssv, nativeStakingSSVStrategy, + ssvNetwork, validatorRegistrator, addresses, - activeValidators, + testValidator, } = await context(); + await depositToStrategy(oethUnits("32")); const { cluster } = await getClusterInfo({ ownerAddress: nativeStakingSSVStrategy.address, - operatorids: activeValidators.operatorIds, + operatorids: testValidator.operatorIds, chainId: hre.network.config.chainId, ssvNetwork: addresses.SSVNetwork, }); - // exit validator from SSV network - const exitTx = await nativeStakingSSVStrategy - .connect(validatorRegistrator) - .exitSsvValidators( - activeValidators.publicKeys, - activeValidators.operatorIds - ); + await setERC20TokenBalance( + nativeStakingSSVStrategy.address, + ssv, + "1000", + hre + ); - await expect(exitTx) - .to.emit(nativeStakingSSVStrategy, "SSVValidatorExitInitiated") - .withArgs( - keccak256(activeValidators.publicKeys[0]), - activeValidators.publicKeys[0], - activeValidators.operatorIds + // Register a new validator with the SSV network + const ssvAmount = oethUnits("4"); + const regTx = await nativeStakingSSVStrategy + .connect(validatorRegistrator) + .registerSsvValidators( + [testValidator.publicKey], + testValidator.operatorIds, + [testValidator.sharesData], + ssvAmount, + cluster ); + const regReceipt = await regTx.wait(); + const ValidatorAddedRawEvent = regReceipt.events.find( + (e) => e.address.toLowerCase() == ssvNetwork.address.toLowerCase() + ); + const ValidatorAddedEvent = ssvNetwork.interface.parseLog( + ValidatorAddedRawEvent + ); + const { cluster: newCluster } = ValidatorAddedEvent.args; const removeTx = await nativeStakingSSVStrategy .connect(validatorRegistrator) - .removeSsvValidators( - activeValidators.publicKeys, - activeValidators.operatorIds, - cluster + .removeSsvValidator( + testValidator.publicKey, + testValidator.operatorIds, + newCluster ); await expect(removeTx) .to.emit(nativeStakingSSVStrategy, "SSVValidatorExitCompleted") .withArgs( - keccak256(activeValidators.publicKeys[0]), - activeValidators.publicKeys[0], - activeValidators.operatorIds + keccak256(testValidator.publicKey), + testValidator.publicKey, + testValidator.operatorIds ); }); }); @@ -648,7 +674,7 @@ const shouldBehaveLikeAnSsvStrategy = (context) => { weth, validatorRegistrator, } = await context(); - const vaultWethBefore = await weth.balanceOf(oethVault.address); + const dripperWethBefore = await weth.balanceOf(oethVault.address); const strategyBalanceBefore = await nativeStakingSSVStrategy.checkBalance( weth.address ); @@ -693,7 +719,7 @@ const shouldBehaveLikeAnSsvStrategy = (context) => { ).to.equal(strategyBalanceBefore, "checkBalance should not increase"); expect(await weth.balanceOf(oethVault.address)).to.equal( - vaultWethBefore.add(executionRewards).add(consensusRewards), + dripperWethBefore.add(executionRewards).add(consensusRewards), "Vault WETH balance should increase" ); }); diff --git a/contracts/test/strategies/nativeSsvStaking.mainnet.fork-test.js b/contracts/test/strategies/nativeSsvStaking.mainnet.fork-test.js index c0935adfdf..07addc1e97 100644 --- a/contracts/test/strategies/nativeSsvStaking.mainnet.fork-test.js +++ b/contracts/test/strategies/nativeSsvStaking.mainnet.fork-test.js @@ -84,14 +84,6 @@ describe("ForkTest: Second Native SSV Staking Strategy", function () { depositDataRoot: "0x6f9cc503009ceb0960637bbf2482b19a62153144ab091f0b9f66d5800f02cc2c", }, - activeValidators: { - publicKeys: [ - "0x80555037820e8afe44a45ed6d43fd4184f14f2ebcac2beaad382ed7e3dac52f87241d5ed8683a8101d8f49b0dbb6bc0e", - "0xb9588334499ee49ac5a1472424e968fe589362b419d9ed09a172f635727466780e11553fbfef1166de3438e9495d7257", - "0xaff707ce005f75d9c8b6b20a170c314219f6596e2fa043c99de0a50565d79155c4ce1ecf98742cd3fdbb878c3762e78b", - ], - operatorIds: [752, 753, 754, 755], - }, }; }); }); @@ -133,14 +125,6 @@ describe("ForkTest: Third Native SSV Staking Strategy", function () { depositDataRoot: "0x3b8409ac7e028e595ac84735da6c19cdbc50931e5d6f910338614ea9660b5c86", }, - activeValidators: { - publicKeys: [ - "0x81ff6c3dab37f0dd49856687bad2ca5406229223e2ac7efcf409aff7b8b55e0f21563adf6a6c23bbe3a8afe8c599ad23", - "0x8b7bdc261a7cbf96cbdfedd0250cef5de212ec497b7100a9a95ca030791e2080bf639ed6e1c8ebed152b17d101fe20cf", - "0xb8ee2f3a4520d9f96988ea57f216b16dd87ecf6e49a8ceb8d0b21a82fb420928c9e3a4b06e73f3ab55a50d61acc39906", - ], - operatorIds: [338, 339, 340, 341], - }, }; }); }); diff --git a/contracts/utils/beacon.js b/contracts/utils/beacon.js index 43a36c84fd..7ae55b64ef 100644 --- a/contracts/utils/beacon.js +++ b/contracts/utils/beacon.js @@ -237,7 +237,7 @@ const beaconchainRequest = async (endpoint, overrideProvider) => { log(`Call to Beacon API failed: ${url}`); log(`response: `, response); throw new Error( - `Call to Beacon API failed. Error: ${JSON.stringify(response.status)}` + `Call to Beacon API failed. Error: ${JSON.stringify(response.error)}` ); } else { log(`GET request to Beacon API succeeded. Response: `, response);