diff --git a/contracts/contract/megapool/RocketMegapoolManager.sol b/contracts/contract/megapool/RocketMegapoolManager.sol index 9e2ca689..73bc0bf2 100644 --- a/contracts/contract/megapool/RocketMegapoolManager.sol +++ b/contracts/contract/megapool/RocketMegapoolManager.sol @@ -40,8 +40,8 @@ contract RocketMegapoolManager is RocketBase, RocketMegapoolManagerInterface { setUint(setCountKey, index + 1); uint256 encoded = (uint256(uint160(_megapoolAddress)) << 96) | _validatorId; setUint(keccak256(abi.encodePacked("megapool.validator.set", index)), encoded); - // Add pubkey => megapool mapping and ensure uniqueness - bytes32 key = keccak256(abi.encodePacked("validator.megapool", _megapoolAddress, _pubkey)); + // Add pubkey => megapool mapping and ensure uniqueness across all megapools + bytes32 key = keccak256(abi.encodePacked("validator.megapool", _pubkey)); require(getAddress(key) == address(0x0), "Pubkey in use"); setAddress(key, _megapoolAddress); } diff --git a/test/megapool/megapool-tests.js b/test/megapool/megapool-tests.js index ef2f0e0e..c5115f95 100644 --- a/test/megapool/megapool-tests.js +++ b/test/megapool/megapool-tests.js @@ -409,6 +409,38 @@ export default function() { ); }); + it(printTitle('node', 'can not reuse pubkey across megapools'), async () => { + const rocketNodeDeposit = await RocketNodeDeposit.deployed(); + const pubkey = getValidatorPubkey(); + const signature = getValidatorSignature(); + + const withdrawalCredentials1 = await getMegapoolWithdrawalCredentials(node.address); + const depositData1 = { + pubkey, + withdrawalCredentials: Buffer.from(withdrawalCredentials1.substr(2), 'hex'), + amount: BigInt(1000000000), // gwei + signature, + }; + const depositDataRoot1 = getDepositDataRoot(depositData1); + + await rocketNodeDeposit.connect(node).deposit('4'.ether, false, pubkey, signature, depositDataRoot1, { value: '4'.ether }); + + const withdrawalCredentials2 = await getMegapoolWithdrawalCredentials(node2.address); + const depositData2 = { + pubkey, + withdrawalCredentials: Buffer.from(withdrawalCredentials2.substr(2), 'hex'), + amount: BigInt(1000000000), // gwei + signature, + }; + const depositDataRoot2 = getDepositDataRoot(depositData2); + + await shouldRevert( + rocketNodeDeposit.connect(node2).deposit('4'.ether, false, pubkey, signature, depositDataRoot2, { value: '4'.ether }), + 'Was able to reuse existing pubkey across megapools', + 'Pubkey in use', + ); + }); + it(printTitle('node', 'can deposit using ETH credit'), async () => { // Enter and exit queue to receive a 4 ETH credit await nodeDeposit(node, '4'.ether);