diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 88f5cb61..c42dcab1 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -10,7 +10,7 @@ #### Added **SSVNetwork** -- `function setOperatosWhitelists(uint64[] calldata operatorIds, address[] calldata whitelistAddresses)` +- `function setOperatorsWhitelists(uint64[] calldata operatorIds, address[] calldata whitelistAddresses)` - `function removeOperatorsWhitelists(uint64[] calldata operatorIds, address[] calldata whitelistAddresses)` - `function setOperatorsWhitelistingContract(uint64[] calldata operatorIds, ISSVWhitelistingContract whitelistingContract)` - `function setOperatorsPrivateUnchecked(uint64[] calldata operatorIds)` diff --git a/contracts/SSVNetwork.sol b/contracts/SSVNetwork.sol index cb95e9a1..469c4aef 100644 --- a/contracts/SSVNetwork.sol +++ b/contracts/SSVNetwork.sol @@ -121,7 +121,11 @@ contract SSVNetwork is /* Operator External Functions */ /*******************************/ - function registerOperator(bytes calldata publicKey, uint256 fee, bool setPrivate) external override returns (uint64 id) { + function registerOperator( + bytes calldata publicKey, + uint256 fee, + bool setPrivate + ) external override returns (uint64 id) { _delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS]); } @@ -129,7 +133,7 @@ contract SSVNetwork is _delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS]); } - function setOperatosWhitelists( + function setOperatorsWhitelists( uint64[] calldata operatorIds, address[] calldata whitelistAddresses ) external override { diff --git a/contracts/interfaces/ISSVOperatorsWhitelist.sol b/contracts/interfaces/ISSVOperatorsWhitelist.sol index 3d0b26d1..5cf4ec76 100644 --- a/contracts/interfaces/ISSVOperatorsWhitelist.sol +++ b/contracts/interfaces/ISSVOperatorsWhitelist.sol @@ -6,9 +6,11 @@ import {ISSVWhitelistingContract} from "./external/ISSVWhitelistingContract.sol" interface ISSVOperatorsWhitelist is ISSVNetworkCore { /// @notice Sets a list of whitelisted addresses (EOAs or generic contracts) for a list of operators + /// @notice Changes to an operator's whitelist will not impact existing validators registered with that operator + /// @notice Only new validator registrations will adhere to the updated whitelist rules /// @param operatorIds The operator IDs to set the whitelists for /// @param whitelistAddresses The list of addresses to be whitelisted - function setOperatosWhitelists(uint64[] calldata operatorIds, address[] calldata whitelistAddresses) external; + function setOperatorsWhitelists(uint64[] calldata operatorIds, address[] calldata whitelistAddresses) external; /// @notice Removes a list of whitelisted addresses (EOAs or generic contracts) for a list of operators /// @param operatorIds Operator IDs for which whitelists are removed diff --git a/contracts/libraries/OperatorLib.sol b/contracts/libraries/OperatorLib.sol index 871135de..83167778 100644 --- a/contracts/libraries/OperatorLib.sol +++ b/contracts/libraries/OperatorLib.sol @@ -142,23 +142,25 @@ library OperatorLib { checkOperatorsLength(operatorIds); // create the max number of masks that will be updated - uint256[] memory masks = generateBlockMasks(operatorIds, true, s); + (uint256[] memory masks, uint256 startBlockIndex) = generateBlockMasks(operatorIds, true, s); + uint256 endBlockIndex = startBlockIndex + masks.length; for (uint256 i; i < addressesLength; ++i) { address whitelistAddress = whitelistAddresses[i]; checkZeroAddress(whitelistAddress); - // If whitelistAddress is a custom contract, revert also when removing - if (isWhitelistingContract(whitelistAddress)) + // If whitelistAddress is a custom contract, reverts only when registering addresses + if (registerAddresses && isWhitelistingContract(whitelistAddress)) revert ISSVNetworkCore.AddressIsWhitelistingContract(whitelistAddress); - for (uint256 blockIndex; blockIndex < masks.length; ++blockIndex) { + for (uint256 blockIndex = startBlockIndex; blockIndex < endBlockIndex; ++blockIndex) { // only update storage for updated masks - if (masks[blockIndex] != 0) { + uint256 mask = masks[blockIndex - startBlockIndex]; + if (mask != 0) { if (registerAddresses) { - s.addressWhitelistedForOperators[whitelistAddress][blockIndex] |= masks[blockIndex]; + s.addressWhitelistedForOperators[whitelistAddress][blockIndex] |= mask; } else { - s.addressWhitelistedForOperators[whitelistAddress][blockIndex] &= ~masks[blockIndex]; + s.addressWhitelistedForOperators[whitelistAddress][blockIndex] &= ~mask; } } } @@ -169,15 +171,15 @@ library OperatorLib { uint64[] calldata operatorIds, bool checkOperatorsOwnership, StorageData storage s - ) internal view returns (uint256[] memory masks) { - uint256 blockIndex; - uint256 bitPosition; - uint64 currentOperatorId; - + ) internal view returns (uint256[] memory masks, uint256 startBlockIndex) { uint256 operatorsLength = operatorIds.length; + startBlockIndex = operatorIds[0] >> 8; - // create the max number of masks that will be updated - masks = new uint256[]((operatorIds[operatorsLength - 1] >> 8) + 1); + // Create the masks array from startBlockIndex to the last block index + masks = new uint256[]((operatorIds[operatorsLength - 1] >> 8) - startBlockIndex + 1); + + uint64 currentOperatorId; + uint64 prevOperatorId; for (uint256 i; i < operatorsLength; ++i) { currentOperatorId = operatorIds[i]; @@ -186,16 +188,17 @@ library OperatorLib { checkOwner(s.operators[currentOperatorId]); } - if (i > 0 && currentOperatorId <= operatorIds[i - 1]) { - if (currentOperatorId == operatorIds[i - 1]) { + if (i > 0 && currentOperatorId <= prevOperatorId) { + if (currentOperatorId == prevOperatorId) { revert ISSVNetworkCore.OperatorsListNotUnique(); } revert ISSVNetworkCore.UnsortedOperatorsList(); } - (blockIndex, bitPosition) = getBitmapIndexes(currentOperatorId); + (uint256 blockIndex, uint256 bitPosition) = getBitmapIndexes(currentOperatorId); - masks[blockIndex] |= (1 << bitPosition); + masks[blockIndex - startBlockIndex] |= (1 << bitPosition); + prevOperatorId = currentOperatorId; } } diff --git a/contracts/modules/SSVOperatorsWhitelist.sol b/contracts/modules/SSVOperatorsWhitelist.sol index db1881eb..93eba09b 100644 --- a/contracts/modules/SSVOperatorsWhitelist.sol +++ b/contracts/modules/SSVOperatorsWhitelist.sol @@ -16,7 +16,7 @@ contract SSVOperatorsWhitelist is ISSVOperatorsWhitelist { /* Operator External Functions */ /*******************************/ - function setOperatosWhitelists( + function setOperatorsWhitelists( uint64[] calldata operatorIds, address[] calldata whitelistAddresses ) external override { @@ -55,8 +55,9 @@ contract SSVOperatorsWhitelist is ISSVOperatorsWhitelist { // operator already whitelisted? // if EOA or generic contract, move it to SSV whitelisting module - if (!OperatorLib.isWhitelistingContract(currentWhitelisted)) { + if (currentWhitelisted != address(0) && !OperatorLib.isWhitelistingContract(currentWhitelisted)) { (uint256 blockIndex, uint256 bitPosition) = OperatorLib.getBitmapIndexes(operatorId); + s.addressWhitelistedForOperators[currentWhitelisted][blockIndex] |= (1 << bitPosition); } diff --git a/contracts/modules/SSVViews.sol b/contracts/modules/SSVViews.sol index 3f530f7f..1d50b89c 100644 --- a/contracts/modules/SSVViews.sol +++ b/contracts/modules/SSVViews.sol @@ -87,20 +87,19 @@ contract SSVViews is ISSVViews { uint256 internalCount; // Check whitelisting address for each operator using the internal SSV whitelisting module - uint256 whitelistedMask; - uint256 matchedMask; - - uint256[] memory masks = OperatorLib.generateBlockMasks(operatorIds, false, s); + (uint256[] memory masks, uint256 startBlockIndex) = OperatorLib.generateBlockMasks(operatorIds, false, s); uint64[] memory internalWhitelistedOperatorIds = new uint64[](operatorsLength); + uint256 endBlockIndex = startBlockIndex + masks.length; // Check whitelisting status for each mask - for (uint256 blockIndex; blockIndex < masks.length; ++blockIndex) { + for (uint256 blockIndex = startBlockIndex; blockIndex < endBlockIndex; ++blockIndex) { + uint256 mask = masks[blockIndex - startBlockIndex]; // Only check blocks that have operator IDs - if (masks[blockIndex] != 0) { - whitelistedMask = s.addressWhitelistedForOperators[addressToCheck][blockIndex]; + if (mask != 0) { + uint256 whitelistedMask = s.addressWhitelistedForOperators[addressToCheck][blockIndex]; // This will give the matching whitelisted operators - matchedMask = whitelistedMask & masks[blockIndex]; + uint256 matchedMask = whitelistedMask & mask; // Now we need to extract operator IDs from matchedMask uint256 blockPointer = blockIndex << 8; @@ -122,11 +121,10 @@ contract SSVViews is ISSVViews { // Check if pending operators use an external whitelisting contract and check whitelistedAddress using it whitelistedOperatorIds = new uint64[](operatorsLength); - uint256 operatorIndex; uint256 internalWhitelistIndex; uint256 count; - while (operatorIndex < operatorsLength) { + for (uint256 operatorIndex; operatorIndex < operatorsLength; ++operatorIndex) { uint64 operatorId = operatorIds[operatorIndex]; // Check if operatorId is already in internalWhitelistedOperatorIds @@ -148,7 +146,6 @@ contract SSVViews is ISSVViews { whitelistedOperatorIds[count++] = operatorId; } } - ++operatorIndex; } // Resize whitelistedOperatorIds to the actual number of whitelisted operators diff --git a/docs/operators.md b/docs/operators.md index eeb9ad27..7acb41d6 100644 --- a/docs/operators.md +++ b/docs/operators.md @@ -21,7 +21,7 @@ The restriction is only effective when the operator owner sets the privacy statu To manage the whitelisted addresses, these 2 data structures are used: `mapping(uint64 => address) operatorsWhitelist`: Keeps the relation between an operator and a whitelisting contract. -`mapping(address => mapping(uint256 => uint256)) addressWhitelistedForOperators`: Links an address (EOA/generic contract) ot a list of operators identified by its `operatorId` using bitmaps. +`mapping(address => mapping(uint256 => uint256)) addressWhitelistedForOperators`: Links an address (EOA/generic contract) to a list of operators identified by its `operatorId` using bitmaps. ### What is a Whitelisting Contract? The operators can choose to whitelist an external contract with custom logic to manage authorized addresses externally. To be used in SSV contracts, it needs to implement the [ISSVWhitelistingContract](../contracts/interfaces/external/ISSVWhitelistingContract.sol) interface, that requires to implement the `isWhitelisted(address account, uint256 operatorId)` function. This function is called in the register validator process, that must return `true/false` to indicate if the caller (`msg.sender`) is whitelisted for the operator. @@ -35,11 +35,11 @@ To check if an account is whitelisted in a whitelisting contract, use the functi ### Legacy whitelisted addresses transition process Up until v1.1.1, operators use the `operatorsWhitelist` mapping to save EOAs and generic contracts. Now in v1.2.0, those type of addresses are stored in `addressWhitelistedForOperators`, leaving `operatorsWhitelist` to save only whitelisting contracts. When whitelisting a new whitelisting contract, the current address stored in `operatorsWhitelist` will be moved to `addressWhitelistedForOperators`, and the new address stored in `operatorsWhitelist`. -When whitelising a new EOA/generic contract, it will be saved in `addressWhitelistedForOperators`, leaving the previous address in `operatorsWhitelist` intact. +When whitelisting a new EOA/generic contract, it will be saved in `addressWhitelistedForOperators`, leaving the previous address in `operatorsWhitelist` intact. ### Operator whitelist states The following table shows all possible combinations of whitelisted addresses for a given operator. -| Use legacy EOA/generic contract | Use whitelising contract | Use EOAs/generic contracts | +| Use legacy EOA/generic contract | Use whitelisting contract | Use EOAs/generic contracts | |---|---|---| | Y | | | | Y | | Y | @@ -57,7 +57,7 @@ Functions related to whitelisting contracts: - Remove: `SSVNetwork.removeOperatorsWhitelistingContract(uint64[] calldata operatorIds)` Functions related to EOAs/generic contracts: -- Register multiple addresses to multiple operators: `SSVNetwork.setOperatosWhitelists(uint64[] calldata operatorIds, address[] calldata whitelistAddresses)` +- Register multiple addresses to multiple operators: `SSVNetwork.setOperatorsWhitelists(uint64[] calldata operatorIds, address[] calldata whitelistAddresses)` - Remove multiple addresses for multiple operators: `SSVNetwork.removeOperatorsWhitelists(uint64[] calldata operatorIds, address[] calldata whitelistAddresses)` ### Registering validators using whitelisted operators @@ -69,4 +69,7 @@ When registering validators using `SSVNetwork.registerValidator` or `SSVNetwork. If the caller is not authorized for any of the whitelisted operators, the transaction will revert with the `CallerNotWhitelistedWithData()` error. +**Important**: Changes to an operator's whitelist will not impact existing validators registered with that operator. Only new validator registrations will adhere to the updated whitelist rules. + + diff --git a/docs/roles.md b/docs/roles.md index be88a195..8cf1da08 100644 --- a/docs/roles.md +++ b/docs/roles.md @@ -27,7 +27,7 @@ The contract owner can perform operational actions over the contract and protoco Only the owner of an operator can execute these functions: - `SSVNetwork.removeOperator` - Removes an existing operator -- `SSVNetwork.setOperatosWhitelists` - Sets a list of whitelisted addresses (EOAs or generic contracts) for a list of operators +- `SSVNetwork.setOperatorsWhitelists` - Sets a list of whitelisted addresses (EOAs or generic contracts) for a list of operators - `SSVNetwork.removeOperatorsWhitelists` - Removes a list of whitelisted addresses (EOAs or generic contracts) for a list of operators - `SSVNetwork.setOperatorsWhitelistingContract` - Sets a whitelisting contract for a list of operators - `SSVNetwork.removeOperatorsWhitelistingContract` - Removes the whitelisting contract set for a list of operators diff --git a/test-forked/operators-whitelist.ts b/test-forked/operators-whitelist.ts index 290d4edf..45d45e0b 100644 --- a/test-forked/operators-whitelist.ts +++ b/test-forked/operators-whitelist.ts @@ -181,7 +181,7 @@ describe('Whitelisting Tests (fork) - Pre-upgrade SSV Core Contracts Tests', () // get the current whitelisted address const prevWhitelistedAddress = (await ssvViews.read.getOperatorById([314]))[3]; - await ssvNetwork.write.setOperatosWhitelists([[315, 316, 317], [owners[2].account.address]], { + await ssvNetwork.write.setOperatorsWhitelists([[315, 316, 317], [owners[2].account.address]], { account: { address: '0xB4084F25DfCb2c1bf6636b420b59eda807953769' }, }); @@ -302,7 +302,7 @@ describe('Whitelisting Tests (fork) - Ongoing SSV Core Contracts upgrade Tests', await upgradeAllContracts(); // whitelist a different operator using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[315n], ['0xB4084F25DfCb2c1bf6636b420b59eda807953769']], { + await ssvNetwork.write.setOperatorsWhitelists([[315n], ['0xB4084F25DfCb2c1bf6636b420b59eda807953769']], { account: { address: '0xB4084F25DfCb2c1bf6636b420b59eda807953769' }, }); diff --git a/test/helpers/gas-usage.ts b/test/helpers/gas-usage.ts index adae4eb6..ddbbfcdb 100644 --- a/test/helpers/gas-usage.ts +++ b/test/helpers/gas-usage.ts @@ -98,13 +98,13 @@ const MAX_GAS_PER_GROUP: any = { [GasGroup.REGISTER_OPERATOR]: 137000, [GasGroup.REMOVE_OPERATOR]: 70500, [GasGroup.REMOVE_OPERATOR_WITH_WITHDRAW]: 70500, - [GasGroup.SET_OPERATOR_WHITELISTING_CONTRACT]: 95500, + [GasGroup.SET_OPERATOR_WHITELISTING_CONTRACT]: 70000, [GasGroup.UPDATE_OPERATOR_WHITELISTING_CONTRACT]: 70000, [GasGroup.SET_OPERATOR_WHITELISTING_CONTRACT_10]: 375000, [GasGroup.REMOVE_OPERATOR_WHITELISTING_CONTRACT]: 43000, [GasGroup.REMOVE_OPERATOR_WHITELISTING_CONTRACT_10]: 130000, - [GasGroup.SET_MULTIPLE_OPERATOR_WHITELIST_10_10]: 382000, - [GasGroup.REMOVE_MULTIPLE_OPERATOR_WHITELIST_10_10]: 169000, + [GasGroup.SET_MULTIPLE_OPERATOR_WHITELIST_10_10]: 381000, + [GasGroup.REMOVE_MULTIPLE_OPERATOR_WHITELIST_10_10]: 168000, [GasGroup.SET_OPERATORS_PRIVATE_10]: 313000, [GasGroup.SET_OPERATORS_PUBLIC_10]: 114000, diff --git a/test/operators/remove.ts b/test/operators/remove.ts index ea9cd709..2648621d 100644 --- a/test/operators/remove.ts +++ b/test/operators/remove.ts @@ -50,7 +50,7 @@ describe('Remove Operator Tests', () => { ); const { operatorId } = result.eventsByName.OperatorAdded[0].args; - await ssvNetwork.write.setOperatosWhitelists([[operatorId], [owners[2].account.address]]); + await ssvNetwork.write.setOperatorsWhitelists([[operatorId], [owners[2].account.address]]); await assertEvent(ssvNetwork.write.removeOperator([operatorId]), [ { diff --git a/test/operators/whitelist.ts b/test/operators/whitelist.ts index 9b8bfea2..5a06c663 100644 --- a/test/operators/whitelist.ts +++ b/test/operators/whitelist.ts @@ -112,7 +112,7 @@ describe('Whitelisting Operator Tests', () => { const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); await trackGas( - ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }), [GasGroup.SET_MULTIPLE_OPERATOR_WHITELIST_10_10], @@ -123,7 +123,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); - await ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + await ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }); @@ -208,7 +208,7 @@ describe('Whitelisting Operator Tests', () => { const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); await assertEvent( - ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }), [ @@ -226,7 +226,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); - await ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + await ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }); @@ -283,7 +283,7 @@ describe('Whitelisting Operator Tests', () => { /* REVERTS */ it('Set operator whitelisted address (EOA) in non-existing operator reverts "OperatorDoesNotExist"', async () => { - await expect(ssvNetwork.write.setOperatosWhitelists([[1], [owners[2].account.address]])).to.be.rejectedWith( + await expect(ssvNetwork.write.setOperatorsWhitelists([[1], [owners[2].account.address]])).to.be.rejectedWith( 'OperatorDoesNotExist', ); }); @@ -292,7 +292,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); await expect( - ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, [ethers.ZeroAddress]], { + ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, [ethers.ZeroAddress]], { account: owners[1].account, }), ).to.be.rejectedWith('ZeroAddressNotAllowed'); @@ -304,7 +304,7 @@ describe('Whitelisting Operator Tests', () => { const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); await expect( - ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[2].account, }), ).to.be.rejectedWith('CallerNotOwnerWithData'); @@ -313,13 +313,13 @@ describe('Whitelisting Operator Tests', () => { it('Set multiple operator whitelisted addresses (EOA) with empty operator IDs reverts "InvalidOperatorIdsLength"', async () => { const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); - await expect(ssvNetwork.write.setOperatosWhitelists([[], whitelistAddresses])).to.be.rejectedWith( + await expect(ssvNetwork.write.setOperatorsWhitelists([[], whitelistAddresses])).to.be.rejectedWith( 'InvalidOperatorIdsLength', ); }); it('Set multiple operator whitelisted addresses (EOA) with empty addresses IDs reverts "InvalidWhitelistAddressesLength"', async () => { - await expect(ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, []])).to.be.rejectedWith( + await expect(ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, []])).to.be.rejectedWith( 'InvalidWhitelistAddressesLength', ); }); @@ -331,7 +331,7 @@ describe('Whitelisting Operator Tests', () => { const unsortedOperatorIds = [1, 3, 2, 4, 5]; await expect( - ssvNetwork.write.setOperatosWhitelists([unsortedOperatorIds, whitelistAddresses], { + ssvNetwork.write.setOperatorsWhitelists([unsortedOperatorIds, whitelistAddresses], { account: owners[1].account, }), ).to.be.rejectedWith('UnsortedOperatorsList'); @@ -344,7 +344,7 @@ describe('Whitelisting Operator Tests', () => { whitelistAddresses.push(mockWhitelistingContractAddress); await expect( - ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }), ).to.be.rejectedWith('AddressIsWhitelistingContract', mockWhitelistingContractAddress); @@ -355,7 +355,7 @@ describe('Whitelisting Operator Tests', () => { const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); - await ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + await ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }); @@ -404,7 +404,7 @@ describe('Whitelisting Operator Tests', () => { ssvNetwork.write.removeOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }), - ).to.be.rejectedWith('AddressIsWhitelistingContract', mockWhitelistingContractAddress); + ).to.not.be.rejectedWith('AddressIsWhitelistingContract', mockWhitelistingContractAddress); }); it('Set operator whitelisting contract with an EOA reverts "InvalidWhitelistingContract"', async () => { @@ -484,7 +484,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); await expect( - ssvNetwork.write.setOperatosWhitelists( + ssvNetwork.write.setOperatorsWhitelists( [ [2, 2, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 8, 8, 8, 8], [owners[4].account.address, owners[5].account.address], @@ -500,7 +500,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); - await ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + await ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }); @@ -530,7 +530,7 @@ describe('Whitelisting Operator Tests', () => { // Register 1000 operators to have 4 bitmap blocks await registerOperators(1, 1000, CONFIG.minimalOperatorFee); - await ssvNetwork.write.setOperatosWhitelists([[100, 200, 300, 400, 500, 600, 700, 800], [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([[100, 200, 300, 400, 500, 600, 700, 800], [whitelistAddress]], { account: owners[1].account, }); @@ -586,7 +586,7 @@ describe('Whitelisting Operator Tests', () => { await mockWhitelistingContract.write.setWhitelistedAddress([whitelistAddress]); // Whitelist using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[200, 300, 500, 600], [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([[200, 300, 500, 600], [whitelistAddress]], { account: owners[1].account, }); @@ -615,7 +615,7 @@ describe('Whitelisting Operator Tests', () => { await mockWhitelistingContract.write.setWhitelistedAddress([whitelistAddress]); // Whitelist using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[1], [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([[1], [whitelistAddress]], { account: owners[1].account, }); @@ -636,7 +636,7 @@ describe('Whitelisting Operator Tests', () => { await mockWhitelistingContract.write.setWhitelistedAddress([whitelistAddress]); // Whitelist using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[2, 3, 4], [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([[2, 3, 4], [whitelistAddress]], { account: owners[1].account, }); @@ -652,7 +652,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); // Whitelist using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[2, 4, 6], [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([[2, 4, 6], [whitelistAddress]], { account: owners[1].account, }); @@ -668,7 +668,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); // Whitelist using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[2, 4, 6], [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([[2, 4, 6], [whitelistAddress]], { account: owners[1].account, }); @@ -683,11 +683,11 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); // Whitelist using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[2, 4, 6], [whitelistAddress1]], { + await ssvNetwork.write.setOperatorsWhitelists([[2, 4, 6], [whitelistAddress1]], { account: owners[1].account, }); - await ssvNetwork.write.setOperatosWhitelists([[3, 5, 7], [whitelistAddress2]], { + await ssvNetwork.write.setOperatorsWhitelists([[3, 5, 7], [whitelistAddress2]], { account: owners[1].account, }); @@ -706,7 +706,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); // Whitelist using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[2, 4, 6], [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([[2, 4, 6], [whitelistAddress]], { account: owners[1].account, }); @@ -722,7 +722,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); // Whitelist using SSV whitelisting module - await ssvNetwork.write.setOperatosWhitelists([[2, 4, 6], [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([[2, 4, 6], [whitelistAddress]], { account: owners[1].account, }); @@ -745,7 +745,7 @@ describe('Whitelisting Operator Tests', () => { operatorIds.push(i); } - await ssvNetwork.write.setOperatosWhitelists([operatorIds, [whitelistAddress]], { + await ssvNetwork.write.setOperatorsWhitelists([operatorIds, [whitelistAddress]], { account: owners[1].account, }); @@ -892,7 +892,7 @@ describe('Whitelisting Operator Tests', () => { const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); await assertEvent( - ssvNetwork.write.setOperatosWhitelists([[1], whitelistAddresses], { + ssvNetwork.write.setOperatorsWhitelists([[1], whitelistAddresses], { account: owners[1].account, }), [ @@ -922,7 +922,7 @@ describe('Whitelisting Operator Tests', () => { const whitelistAddresses = owners.slice(0, 10).map(owner => owner.account.address); await assertEvent( - ssvNetwork.write.setOperatosWhitelists([OPERATOR_IDS_10, whitelistAddresses], { + ssvNetwork.write.setOperatorsWhitelists([OPERATOR_IDS_10, whitelistAddresses], { account: owners[1].account, }), [ @@ -947,7 +947,7 @@ describe('Whitelisting Operator Tests', () => { await registerOperators(1, 10, CONFIG.minimalOperatorFee); await assertEvent( - ssvNetwork.write.setOperatosWhitelists([[2], [owners[3].account.address]], { + ssvNetwork.write.setOperatorsWhitelists([[2], [owners[3].account.address]], { account: owners[1].account, }), [ diff --git a/test/validators/whitelist-register.ts b/test/validators/whitelist-register.ts index 27c21ad0..f8d9908c 100644 --- a/test/validators/whitelist-register.ts +++ b/test/validators/whitelist-register.ts @@ -45,7 +45,7 @@ describe('Register Validator Tests', () => { it('Register whitelisted validator in 1 operator with 4 operators emits "ValidatorAdded"/gas limits/logic', async () => { const operatorId = await registerOperators(1, 1, CONFIG.minimalOperatorFee); - await ssvNetwork.write.setOperatosWhitelists([[operatorId], [owners[3].account.address]], { + await ssvNetwork.write.setOperatorsWhitelists([[operatorId], [owners[3].account.address]], { account: owners[1].account, }); await ssvNetwork.write.setOperatorsPrivateUnchecked([[operatorId]], { @@ -93,7 +93,7 @@ describe('Register Validator Tests', () => { }); it('Register whitelisted validator in 4 operators in 4 operators cluster gas limits/logic', async () => { - await ssvNetwork.write.setOperatosWhitelists([DEFAULT_OPERATOR_IDS[4], [owners[3].account.address]], { + await ssvNetwork.write.setOperatorsWhitelists([DEFAULT_OPERATOR_IDS[4], [owners[3].account.address]], { account: owners[0].account, }); @@ -127,7 +127,7 @@ describe('Register Validator Tests', () => { }); it('Register non-whitelisted validator in 1 public operator with 4 operators emits "ValidatorAdded"/logic', async () => { - await ssvNetwork.write.setOperatosWhitelists([[5], [owners[3].account.address]]); + await ssvNetwork.write.setOperatorsWhitelists([[5], [owners[3].account.address]]); await ssvNetwork.write.setOperatorsPublicUnchecked([[5]]); @@ -183,7 +183,7 @@ describe('Register Validator Tests', () => { const args = eventsByName.ValidatorAdded[0].args; - await ssvNetwork.write.setOperatosWhitelists([DEFAULT_OPERATOR_IDS[4], [owners[3].account.address]]); + await ssvNetwork.write.setOperatorsWhitelists([DEFAULT_OPERATOR_IDS[4], [owners[3].account.address]]); await ssvToken.write.approve([ssvNetwork.address, minDepositAmount], { account: owners[3].account }); await trackGas( @@ -202,7 +202,7 @@ describe('Register Validator Tests', () => { }); it('Register using non-authorized account for 1 operator with 4 operators cluster reverts "CallerNotWhitelistedWithData"', async () => { - await ssvNetwork.write.setOperatosWhitelists([[3], [owners[3].account.address]], { + await ssvNetwork.write.setOperatorsWhitelists([[3], [owners[3].account.address]], { account: owners[0].account, }); @@ -461,7 +461,7 @@ describe('Register Validator Tests', () => { // Account C = owners[4] // Account A whitelists account B on SSV whitelisting module (operator 5) - await ssvNetwork.write.setOperatosWhitelists([[5], [owners[3].account.address]]); + await ssvNetwork.write.setOperatorsWhitelists([[5], [owners[3].account.address]]); // Account A adds account C to that whitelist contract const whitelistingContract = await hre.viem.deployContract( @@ -684,7 +684,7 @@ describe('Register Validator Tests', () => { it('Register using whitelisting contract for 1 operator & EOA for 1 operator in 4 operators cluster', async () => { await ssvToken.write.approve([ssvNetwork.address, minDepositAmount], { account: owners[3].account }); - await ssvNetwork.write.setOperatosWhitelists([[6], [owners[3].account.address]]); + await ssvNetwork.write.setOperatorsWhitelists([[6], [owners[3].account.address]]); await ssvNetwork.write.setOperatorsPrivateUnchecked([[6]]); @@ -799,7 +799,7 @@ describe('Register Validator Tests', () => { const operatorIds = [2, 258, 514, 770, 1026, 1282, 1538, 1794, 2050, 2306, 2562, 2818, 3074]; - await ssvNetwork.write.setOperatosWhitelists([operatorIds, [owners[3].account.address]], { + await ssvNetwork.write.setOperatorsWhitelists([operatorIds, [owners[3].account.address]], { account: owners[2].account, }); @@ -870,7 +870,7 @@ describe('Register Validator Tests', () => { clusterData = clusterData.eventsByName.ValidatorAdded[0].args; // Step 2 - await ssvNetwork.write.setOperatosWhitelists([[2], [owners[3].account.address]], { + await ssvNetwork.write.setOperatorsWhitelists([[2], [owners[3].account.address]], { account: owners[1].account, }); await ssvNetwork.write.setOperatorsPrivateUnchecked([[2]], {