Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions contracts/contract/megapool/RocketMegapoolManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
32 changes: 32 additions & 0 deletions test/megapool/megapool-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down