Skip to content

Commit ad9c1c6

Browse files
committed
feat: add operator table updater to CCR (#1451)
**Motivation:** The offchain generation service should be able to retrieve the `OperatorTableUpdater` on-chain. **Modifications:** - Update `_whitelistedChainIDs` to be an enumerable map from `chainID` to `operatorTableUpdater` - Update `addChainIDsToWhitelist` to take in a list of `operatorTableUpdaters` - Update `getSupportedChains` to return chainIDs and `operatorTableUpdaters` **Result:** Clearer introspection.
1 parent 4b86ae4 commit ad9c1c6

File tree

6 files changed

+118
-40
lines changed

6 files changed

+118
-40
lines changed

src/contracts/interfaces/ICrossChainRegistry.sol

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ interface ICrossChainRegistryErrors {
4343

4444
/// @notice Thrown when the storage is not cleared
4545
error NeedToDelete();
46+
47+
/// @notice Thrown when the lengths between two arrays are not the same
48+
error ArrayLengthMismatch();
4649
}
4750

4851
interface ICrossChainRegistryTypes {
@@ -77,7 +80,7 @@ interface ICrossChainRegistryEvents is ICrossChainRegistryTypes {
7780
event TransportDestinationRemoved(OperatorSet operatorSet, uint256 chainID);
7881

7982
/// @notice Emitted when a chainID is added to the whitelist
80-
event ChainIDAddedToWhitelist(uint256 chainID);
83+
event ChainIDAddedToWhitelist(uint256 chainID, address operatorTableUpdater);
8184

8285
/// @notice Emitted when a chainID is removed from the whitelist
8386
event ChainIDRemovedFromWhitelist(uint256 chainID);
@@ -150,11 +153,10 @@ interface ICrossChainRegistry is ICrossChainRegistryErrors, ICrossChainRegistryE
150153
/**
151154
* @notice Adds chainIDs to the whitelist of chainIDs that can be transported to
152155
* @param chainIDs the chainIDs to add to the whitelist
156+
* @param operatorTableUpdaters the operatorTableUpdaters for each whitelisted chainID
153157
* @dev msg.sender must be the owner of the CrossChainRegistry
154158
*/
155-
function addChainIDsToWhitelist(
156-
uint256[] calldata chainIDs
157-
) external;
159+
function addChainIDsToWhitelist(uint256[] calldata chainIDs, address[] calldata operatorTableUpdaters) external;
158160

159161
/**
160162
* @notice Removes chainIDs from the whitelist of chainIDs that can be transported to
@@ -228,6 +230,7 @@ interface ICrossChainRegistry is ICrossChainRegistryErrors, ICrossChainRegistryE
228230
/**
229231
* @notice Gets the list of chains that are supported by the CrossChainRegistry
230232
* @return An array of chainIDs that are supported by the CrossChainRegistry
233+
* @return An array of operatorTableUpdaters corresponding to each chainID
231234
*/
232-
function getSupportedChains() external view returns (uint256[] memory);
235+
function getSupportedChains() external view returns (uint256[] memory, address[] memory);
233236
}

src/contracts/interfaces/IOperatorTableUpdater.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,15 @@ interface IOperatorTableUpdater is
9898
* @param globalTableRoot the new globalTableRoot
9999
* @param operatorSetIndex the index of the given operatorSet being updated
100100
* @param proof the proof of the leaf at index against the globalTableRoot
101-
* @param tableInfo the tableInfo of the operator table
102-
* @dev Depending on the decoded KeyType, the tableInfo will be decoded to a
101+
* @param operatorTableBytes the bytes of the operator table
102+
* @dev Depending on the decoded KeyType, the tableInfo will be decoded
103103
*/
104104
function updateOperatorTable(
105105
uint32 referenceTimestamp,
106106
bytes32 globalTableRoot,
107107
uint32 operatorSetIndex,
108108
bytes calldata proof,
109-
bytes calldata tableInfo
109+
bytes calldata operatorTableBytes
110110
) external;
111111

112112
/**

src/contracts/multichain/CrossChainRegistry.sol

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ contract CrossChainRegistry is
2323
PermissionControllerMixin,
2424
SemVerMixin
2525
{
26+
using EnumerableMap for EnumerableMap.UintToAddressMap;
2627
using EnumerableSet for EnumerableSet.Bytes32Set;
2728
using EnumerableSet for EnumerableSet.UintSet;
2829
using OperatorSetLib for OperatorSet;
@@ -205,18 +206,21 @@ contract CrossChainRegistry is
205206

206207
/// @inheritdoc ICrossChainRegistry
207208
function addChainIDsToWhitelist(
208-
uint256[] calldata chainIDs
209+
uint256[] calldata chainIDs,
210+
address[] calldata operatorTableUpdaters
209211
) external onlyOwner onlyWhenNotPaused(PAUSED_CHAIN_WHITELIST) {
212+
require(chainIDs.length == operatorTableUpdaters.length, ArrayLengthMismatch());
213+
210214
for (uint256 i = 0; i < chainIDs.length; i++) {
211215
uint256 chainID = chainIDs[i];
212216

213217
// Validate chainID
214218
require(chainID != 0, InvalidChainId());
215219

216220
// Add to whitelist
217-
require(_whitelistedChainIDs.add(chainID), ChainIDAlreadyWhitelisted());
221+
require(_whitelistedChainIDs.set(chainID, operatorTableUpdaters[i]), ChainIDAlreadyWhitelisted());
218222

219-
emit ChainIDAddedToWhitelist(chainID);
223+
emit ChainIDAddedToWhitelist(chainID, operatorTableUpdaters[i]);
220224
}
221225
}
222226

@@ -438,7 +442,17 @@ contract CrossChainRegistry is
438442
}
439443

440444
/// @inheritdoc ICrossChainRegistry
441-
function getSupportedChains() external view returns (uint256[] memory) {
442-
return _whitelistedChainIDs.values();
445+
function getSupportedChains() external view returns (uint256[] memory, address[] memory) {
446+
uint256 length = _whitelistedChainIDs.length();
447+
uint256[] memory chainIDs = new uint256[](length);
448+
address[] memory operatorTableUpdaters = new address[](length);
449+
450+
for (uint256 i = 0; i < length; i++) {
451+
(uint256 chainID, address operatorTableUpdater) = _whitelistedChainIDs.at(i);
452+
chainIDs[i] = chainID;
453+
operatorTableUpdaters[i] = operatorTableUpdater;
454+
}
455+
456+
return (chainIDs, operatorTableUpdaters);
443457
}
444458
}

src/contracts/multichain/CrossChainRegistryStorage.sol

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
pragma solidity ^0.8.27;
33

44
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
5+
import "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
56
import "../interfaces/ICrossChainRegistry.sol";
67
import "../interfaces/IOperatorTableCalculator.sol";
78
import "../interfaces/IAllocationManager.sol";
@@ -15,6 +16,7 @@ import "../libraries/OperatorSetLib.sol";
1516
* @dev This abstract contract is designed to be inherited by the CrossChainRegistry implementation
1617
*/
1718
abstract contract CrossChainRegistryStorage is ICrossChainRegistry {
19+
using EnumerableMap for EnumerableMap.UintToAddressMap;
1820
using EnumerableSet for EnumerableSet.Bytes32Set;
1921
using EnumerableSet for EnumerableSet.UintSet;
2022
using OperatorSetLib for OperatorSet;
@@ -62,8 +64,8 @@ abstract contract CrossChainRegistryStorage is ICrossChainRegistry {
6264

6365
/// CHAIN WHITELISTING
6466

65-
/// @dev Set of whitelisted chain IDs that can be used as transport destinations
66-
EnumerableSet.UintSet internal _whitelistedChainIDs;
67+
/// @dev Map of whitelisted chain IDs to operator table updaters
68+
EnumerableMap.UintToAddressMap internal _whitelistedChainIDs;
6769

6870
// Construction
6971

@@ -77,5 +79,5 @@ abstract contract CrossChainRegistryStorage is ICrossChainRegistry {
7779
* variables without shifting down storage in the inheritance chain.
7880
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
7981
*/
80-
uint256[43] private __gap;
82+
uint256[42] private __gap;
8183
}

src/contracts/multichain/OperatorTableUpdater.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ contract OperatorTableUpdater is Initializable, OwnableUpgradeable, OperatorTabl
8989
bytes32 globalTableRoot,
9090
uint32 operatorSetIndex,
9191
bytes calldata proof,
92-
bytes calldata tableInfo
92+
bytes calldata operatorTableBytes
9393
) external {
9494
(OperatorSet memory operatorSet, CurveType curveType, OperatorSetConfig memory operatorSetConfig) =
95-
_getOperatorTableInfo(tableInfo);
95+
_getOperatorTableInfo(operatorTableBytes);
9696

9797
// Check that the `referenceTimestamp` is greater than the latest reference timestamp
9898
require(
@@ -107,17 +107,17 @@ contract OperatorTableUpdater is Initializable, OwnableUpgradeable, OperatorTabl
107107
globalTableRoot: globalTableRoot,
108108
operatorSetIndex: operatorSetIndex,
109109
proof: proof,
110-
operatorSetLeafHash: keccak256(tableInfo)
110+
operatorSetLeafHash: keccak256(operatorTableBytes)
111111
});
112112

113113
// Update the operator table
114114
if (curveType == CurveType.BN254) {
115115
bn254CertificateVerifier.updateOperatorTable(
116-
operatorSet, referenceTimestamp, _getBN254OperatorSetInfo(tableInfo), operatorSetConfig
116+
operatorSet, referenceTimestamp, _getBN254OperatorSetInfo(operatorTableBytes), operatorSetConfig
117117
);
118118
} else if (curveType == CurveType.ECDSA) {
119119
ecdsaCertificateVerifier.updateOperatorTable(
120-
operatorSet, referenceTimestamp, _getECDSAOperatorSetInfo(tableInfo), operatorSetConfig
120+
operatorSet, referenceTimestamp, _getECDSAOperatorSetInfo(operatorTableBytes), operatorSetConfig
121121
);
122122
} else {
123123
revert InvalidCurveType();

0 commit comments

Comments
 (0)