Skip to content

Commit f74c429

Browse files
committed
support for ERC165
1 parent 34d6a5f commit f74c429

12 files changed

+140
-180
lines changed

contracts/SSVNetwork.sol

+7-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import "./interfaces/ISSVNetwork.sol";
55

66
import "./interfaces/ISSVClusters.sol";
77
import "./interfaces/ISSVOperators.sol";
8+
import "./interfaces/ISSVOperatorsWhitelist.sol";
89
import "./interfaces/ISSVDAO.sol";
910
import "./interfaces/ISSVViews.sol";
1011

@@ -26,6 +27,7 @@ contract SSVNetwork is
2627
Ownable2StepUpgradeable,
2728
ISSVNetwork,
2829
ISSVOperators,
30+
ISSVOperatorsWhitelist,
2931
ISSVClusters,
3032
ISSVDAO,
3133
SSVProxy
@@ -126,28 +128,28 @@ contract SSVNetwork is
126128
}
127129

128130
function setOperatorWhitelist(uint64 operatorId, address whitelisted) external override {
129-
_delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS]);
131+
_delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS_WHITELIST]);
130132
}
131133

132134
function setOperatorMultipleWhitelists(
133135
uint64[] calldata operatorIds,
134136
address[] calldata whitelistAddresses
135137
) external override {
136-
_delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS]);
138+
_delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS_WHITELIST]);
137139
}
138140

139141
function setOperatorsWhitelistingContract(
140142
uint64[] calldata operatorIds,
141-
address whitelistingContract
143+
ISSVWhitelistingContract whitelistingContract
142144
) external override {
143-
_delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS]);
145+
_delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS_WHITELIST]);
144146
}
145147

146148
function removeOperatorMultipleWhitelists(
147149
uint64[] calldata operatorIds,
148150
address[] calldata whitelistAddresses
149151
) external override {
150-
_delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS]);
152+
_delegate(SSVStorage.load().ssvContracts[SSVModules.SSV_OPERATORS_WHITELIST]);
151153
}
152154

153155
function declareOperatorFee(uint64 operatorId, uint256 fee) external override {

contracts/interfaces/ISSVNetworkCore.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ interface ISSVNetworkCore {
9191
error ValidatorAlreadyExistsWithData(bytes publicKey); // 0x388e7999
9292
error EmptyPublicKeysList(); // df83e679
9393
error InvalidContractAddress(); // 0xa710429d
94-
error AddressIsContract(); // 0x9166b12d
94+
error AddressIsWhitelistingContract(address contractAddress); // 0x71cadba7
9595
error InvalidWhitelistAddressesLength(); // 0xcbb362dc
9696

9797
// legacy errors

contracts/interfaces/ISSVOperators.sol

-40
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,6 @@ interface ISSVOperators is ISSVNetworkCore {
1313
/// @param operatorId The ID of the operator to be removed
1414
function removeOperator(uint64 operatorId) external;
1515

16-
/// @notice Sets the whitelist for an operator
17-
/// @param operatorId The ID of the operator
18-
/// @param whitelistAddress The address to be whitelisted
19-
function setOperatorWhitelist(uint64 operatorId, address whitelistAddress) external;
20-
21-
/// @notice Sets a list of whitelisted addresses (EOAs or generic contracts) for a list of operators
22-
/// @param operatorIds The operator IDs to set the whitelists for
23-
/// @param whitelistAddresses The list of addresses to be whitelisted
24-
function setOperatorMultipleWhitelists(
25-
uint64[] calldata operatorIds,
26-
address[] calldata whitelistAddresses
27-
) external;
28-
29-
/// @notice Removes a list of whitelisted addresses (EOAs or generic contracts) for a list of operators
30-
/// @param operatorIds Operator IDs for which whitelists are removed
31-
/// @param whitelistAddresses List of addresses to be removed from the whitelist
32-
function removeOperatorMultipleWhitelists(
33-
uint64[] calldata operatorIds,
34-
address[] calldata whitelistAddresses
35-
) external;
36-
37-
/// @notice Sets a whitelisting contract for a list of operators
38-
/// @param operatorIds The operator IDs to set the whitelisting contract for
39-
/// @param whitelistingContract The address of a whitelisting contract
40-
function setOperatorsWhitelistingContract(uint64[] calldata operatorIds, address whitelistingContract) external;
41-
4216
/// @notice Declares the operator's fee
4317
/// @param operatorId The ID of the operator
4418
/// @param fee The fee to be declared (SSV)
@@ -81,20 +55,6 @@ interface ISSVOperators is ISSVNetworkCore {
8155
*/
8256
event OperatorRemoved(uint64 indexed operatorId);
8357

84-
/**
85-
* @dev Emitted when the whitelist of an operator is updated.
86-
* @param operatorId operator's ID.
87-
* @param whitelisted operator's new whitelisted address.
88-
*/
89-
event OperatorWhitelistUpdated(uint64 indexed operatorId, address whitelisted);
90-
91-
/**
92-
* @dev Emitted when the whitelisting contract of an operator is updated.
93-
* @param operatorIds operators' IDs.
94-
* @param whitelistingContract operators' new whitelisting contract address.
95-
*/
96-
event OperatorWhitelistingContractUpdated(uint64[] indexed operatorIds, address whitelistingContract);
97-
9858
event OperatorFeeDeclared(address indexed owner, uint64 indexed operatorId, uint256 blockNumber, uint256 fee);
9959

10060
event OperatorFeeDeclarationCancelled(address indexed owner, uint64 indexed operatorId);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
pragma solidity 0.8.18;
3+
4+
import "./ISSVNetworkCore.sol";
5+
import "./external/ISSVWhitelistingContract.sol";
6+
7+
interface ISSVOperatorsWhitelist is ISSVNetworkCore {
8+
/// @notice Sets the whitelist for an operator
9+
/// @param operatorId The ID of the operator
10+
/// @param whitelistAddress The address to be whitelisted
11+
function setOperatorWhitelist(uint64 operatorId, address whitelistAddress) external;
12+
13+
/// @notice Sets a list of whitelisted addresses (EOAs or generic contracts) for a list of operators
14+
/// @param operatorIds The operator IDs to set the whitelists for
15+
/// @param whitelistAddresses The list of addresses to be whitelisted
16+
function setOperatorMultipleWhitelists(
17+
uint64[] calldata operatorIds,
18+
address[] calldata whitelistAddresses
19+
) external;
20+
21+
/// @notice Removes a list of whitelisted addresses (EOAs or generic contracts) for a list of operators
22+
/// @param operatorIds Operator IDs for which whitelists are removed
23+
/// @param whitelistAddresses List of addresses to be removed from the whitelist
24+
function removeOperatorMultipleWhitelists(
25+
uint64[] calldata operatorIds,
26+
address[] calldata whitelistAddresses
27+
) external;
28+
29+
/// @notice Sets a whitelisting contract for a list of operators
30+
/// @param operatorIds The operator IDs to set the whitelisting contract for
31+
/// @param whitelistingContract The address of a whitelisting contract
32+
function setOperatorsWhitelistingContract(uint64[] calldata operatorIds, ISSVWhitelistingContract whitelistingContract) external;
33+
34+
/**
35+
* @dev Emitted when the whitelist of an operator is updated.
36+
* @param operatorId operator's ID.
37+
* @param whitelisted operator's new whitelisted address.
38+
*/
39+
event OperatorWhitelistUpdated(uint64 indexed operatorId, address whitelisted);
40+
41+
/**
42+
* @dev Emitted when the whitelisting contract of an operator is updated.
43+
* @param operatorIds operators' IDs.
44+
* @param whitelistingContract operators' new whitelisting contract address.
45+
*/
46+
event OperatorWhitelistingContractUpdated(uint64[] indexed operatorIds, address whitelistingContract);
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
pragma solidity 0.8.18;
3+
4+
interface ISSVWhitelistingContract {
5+
/// @notice Checks if the caller is whitelisted
6+
/// @param account The account that is being checked for whitelisting
7+
/// @param operatorId The SSV Operator Id which is being checked
8+
function isWhitelisted(address account, uint64 operatorId) external view returns (bool);
9+
}

contracts/libraries/CoreLib.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ library CoreLib {
77
event ModuleUpgraded(SSVModules indexed moduleId, address moduleAddress);
88

99
function getVersion() internal pure returns (string memory) {
10-
return "v1.1.0";
10+
return "v1.2.0";
1111
}
1212

1313
function transferBalance(address to, uint256 amount) internal {

contracts/libraries/OperatorLib.sol

+7-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pragma solidity 0.8.18;
33

44
import "../interfaces/ISSVNetworkCore.sol";
5+
import "../interfaces/external/ISSVWhitelistingContract.sol";
56
import "./CoreLib.sol";
67
import "./SSVStorage.sol";
78
import "./SSVStorageProtocol.sol";
@@ -10,9 +11,6 @@ import "./Types.sol";
1011
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
1112

1213
library OperatorLib {
13-
// isWhitelisted(address,uint64)
14-
bytes4 private constant IS_WHITELISTED_INTERFACE = 0xbe7a1ee7;
15-
1614
using Types64 for uint64;
1715

1816
function updateSnapshot(ISSVNetworkCore.Operator memory operator) internal view {
@@ -149,7 +147,7 @@ library OperatorLib {
149147
for (uint256 i = 0; i < addressesLength; ++i) {
150148
address addr = whitelistAddresses[i];
151149

152-
if (isWhitelistingContract(addr)) revert ISSVNetworkCore.AddressIsContract();
150+
if (isWhitelistingContract(addr)) revert ISSVNetworkCore.AddressIsWhitelistingContract(addr);
153151

154152
for (blockIndex = 0; blockIndex < masks.length; ++blockIndex) {
155153
// only update storage for updated masks
@@ -166,13 +164,11 @@ library OperatorLib {
166164

167165
function updateWhitelistingContract(
168166
uint64 operatorId,
169-
address whitelistingContract,
167+
ISSVWhitelistingContract whitelistingContract,
170168
StorageData storage s
171169
) internal {
172170
checkOwner(s.operators[operatorId]);
173-
174-
if (!isWhitelistingContract(whitelistingContract)) revert ISSVNetworkCore.InvalidContractAddress();
175-
171+
176172
address currentWhitelisted = s.operatorsWhitelist[operatorId];
177173

178174
// operator already whitelisted? EOA or generic contract
@@ -182,12 +178,12 @@ library OperatorLib {
182178
s.addressWhitelistedForOperators[currentWhitelisted][blockIndex] |= (1 << bitPosition);
183179
}
184180

185-
s.operatorsWhitelist[operatorId] = whitelistingContract;
181+
s.operatorsWhitelist[operatorId] = address(whitelistingContract);
186182
if (!s.operators[operatorId].whitelisted) s.operators[operatorId].whitelisted = true;
187183
}
188184

189185
function isWhitelistingContract(address whitelistingContract) internal view returns (bool) {
190-
// TODO create type for whitelisting contracts
191-
return ERC165Checker.supportsInterface(whitelistingContract, IS_WHITELISTED_INTERFACE);
186+
// TODO create type for whitelisting contracts?
187+
return ERC165Checker.supportsInterface(whitelistingContract, type(ISSVWhitelistingContract).interfaceId);
192188
}
193189
}

contracts/libraries/SSVStorage.sol

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ enum SSVModules {
99
SSV_OPERATORS,
1010
SSV_CLUSTERS,
1111
SSV_DAO,
12-
SSV_VIEWS
12+
SSV_VIEWS,
13+
SSV_OPERATORS_WHITELIST
1314
}
1415

1516
/// @title SSV Network Storage Data

contracts/modules/SSVOperators.sol

-41
Original file line numberDiff line numberDiff line change
@@ -73,47 +73,6 @@ contract SSVOperators is ISSVOperators {
7373
emit OperatorRemoved(operatorId);
7474
}
7575

76-
function setOperatorWhitelist(uint64 operatorId, address whitelistAddress) external override {
77-
StorageData storage s = SSVStorage.load();
78-
s.operators[operatorId].checkOwner();
79-
80-
if (OperatorLib.isWhitelistingContract(whitelistAddress)) revert AddressIsContract();
81-
82-
// Set the bit at bitPosition for the operatorId in the corresponding uint256 blockIndex
83-
(uint256 blockIndex, uint256 bitPosition) = OperatorLib.getBitmapIndexes(operatorId);
84-
85-
s.addressWhitelistedForOperators[whitelistAddress][blockIndex] |= (1 << bitPosition);
86-
if (!s.operators[operatorId].whitelisted) s.operators[operatorId].whitelisted = true;
87-
88-
emit OperatorWhitelistUpdated(operatorId, whitelistAddress);
89-
}
90-
91-
function setOperatorMultipleWhitelists(
92-
uint64[] calldata operatorIds,
93-
address[] calldata whitelistAddresses
94-
) external override {
95-
OperatorLib.updateMultipleWhitelists(whitelistAddresses, operatorIds, true, SSVStorage.load());
96-
}
97-
98-
function removeOperatorMultipleWhitelists(
99-
uint64[] calldata operatorIds,
100-
address[] calldata whitelistAddresses
101-
) external override {
102-
OperatorLib.updateMultipleWhitelists(whitelistAddresses, operatorIds, false, SSVStorage.load());
103-
}
104-
105-
function setOperatorsWhitelistingContract(uint64[] calldata operatorIds, address whitelistingContract) external {
106-
uint256 operatorsLength = operatorIds.length;
107-
if (operatorsLength == 0) revert InvalidOperatorIdsLength();
108-
109-
StorageData storage s = SSVStorage.load();
110-
111-
for (uint256 i = 0; i < operatorsLength; ++i) {
112-
OperatorLib.updateWhitelistingContract(operatorIds[i], whitelistingContract, s);
113-
}
114-
emit OperatorWhitelistingContractUpdated(operatorIds, whitelistingContract);
115-
}
116-
11776
function declareOperatorFee(uint64 operatorId, uint256 fee) external override {
11877
StorageData storage s = SSVStorage.load();
11978
s.operators[operatorId].checkOwner();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
pragma solidity 0.8.18;
3+
4+
import {ISSVOperatorsWhitelist} from "../interfaces/ISSVOperatorsWhitelist.sol";
5+
import {ISSVWhitelistingContract} from "../interfaces/external/ISSVWhitelistingContract.sol";
6+
import {Types64, Types256} from "../libraries/Types.sol";
7+
import {StorageData, SSVStorage} from "../libraries/SSVStorage.sol";
8+
import {OperatorLib} from "../libraries/OperatorLib.sol";
9+
10+
contract SSVOperatorsWhitelist is ISSVOperatorsWhitelist {
11+
using Types256 for uint256;
12+
using Types64 for uint64;
13+
using OperatorLib for Operator;
14+
15+
/*******************************/
16+
/* Operator External Functions */
17+
/*******************************/
18+
19+
function setOperatorWhitelist(uint64 operatorId, address whitelistAddress) external override {
20+
StorageData storage s = SSVStorage.load();
21+
s.operators[operatorId].checkOwner();
22+
23+
if (OperatorLib.isWhitelistingContract(whitelistAddress))
24+
revert AddressIsWhitelistingContract(whitelistAddress);
25+
26+
// Set the bit at bitPosition for the operatorId in the corresponding uint256 blockIndex
27+
(uint256 blockIndex, uint256 bitPosition) = OperatorLib.getBitmapIndexes(operatorId);
28+
29+
s.addressWhitelistedForOperators[whitelistAddress][blockIndex] |= (1 << bitPosition);
30+
if (!s.operators[operatorId].whitelisted) s.operators[operatorId].whitelisted = true;
31+
32+
emit OperatorWhitelistUpdated(operatorId, whitelistAddress);
33+
}
34+
35+
function setOperatorMultipleWhitelists(
36+
uint64[] calldata operatorIds,
37+
address[] calldata whitelistAddresses
38+
) external override {
39+
OperatorLib.updateMultipleWhitelists(whitelistAddresses, operatorIds, true, SSVStorage.load());
40+
}
41+
42+
function removeOperatorMultipleWhitelists(
43+
uint64[] calldata operatorIds,
44+
address[] calldata whitelistAddresses
45+
) external override {
46+
OperatorLib.updateMultipleWhitelists(whitelistAddresses, operatorIds, false, SSVStorage.load());
47+
}
48+
49+
function setOperatorsWhitelistingContract(
50+
uint64[] calldata operatorIds,
51+
ISSVWhitelistingContract whitelistingContract
52+
) external {
53+
uint256 operatorsLength = operatorIds.length;
54+
if (operatorsLength == 0) revert InvalidOperatorIdsLength();
55+
56+
StorageData storage s = SSVStorage.load();
57+
58+
for (uint256 i = 0; i < operatorsLength; ++i) {
59+
OperatorLib.updateWhitelistingContract(operatorIds[i], whitelistingContract, s);
60+
}
61+
62+
// TODO test set event param type to ISSVOperatorsWhitelist
63+
emit OperatorWhitelistingContractUpdated(operatorIds, address(whitelistingContract));
64+
}
65+
}

0 commit comments

Comments
 (0)