Skip to content

Commit 3958cfd

Browse files
committed
fix: keyregistrar and crosschainregistry checks
1 parent c22baf0 commit 3958cfd

File tree

6 files changed

+139
-8
lines changed

6 files changed

+139
-8
lines changed

src/contracts/cloud/ComputeRegistry.sol

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,13 @@ contract ComputeRegistry is Initializable, ComputeRegistryStorage, PermissionCon
5151
constructor(
5252
IReleaseManager _releaseManager,
5353
IAllocationManager _allocationManager,
54+
IKeyRegistrar _keyRegistrar,
55+
ICrossChainRegistry _crossChainRegistry,
5456
IPermissionController _permissionController,
5557
bytes32 _tosHash,
5658
string memory _version
5759
)
58-
ComputeRegistryStorage(_releaseManager, _allocationManager, _tosHash)
60+
ComputeRegistryStorage(_releaseManager, _allocationManager, _keyRegistrar, _crossChainRegistry, _tosHash)
5961
PermissionControllerMixin(_permissionController)
6062
SignatureUtilsMixin(_version)
6163
{
@@ -79,6 +81,13 @@ contract ComputeRegistry is Initializable, ComputeRegistryStorage, PermissionCon
7981
bytes32 operatorSetKey = operatorSet.key();
8082
require(!isOperatorSetRegistered[operatorSetKey], OperatorSetAlreadyRegistered());
8183

84+
// Check if the curve type has been set for the operator set
85+
IKeyRegistrarTypes.CurveType curveType = KEY_REGISTRAR.getOperatorSetCurveType(operatorSet);
86+
require(curveType != IKeyRegistrarTypes.CurveType.NONE, CurveTypeNotSet());
87+
88+
// Check if the operator set has an active generation reservation
89+
require(CROSS_CHAIN_REGISTRY.hasActiveGenerationReservation(operatorSet), NoActiveGenerationReservation());
90+
8291
// Check if there is at least one release for the operator set
8392
// The ReleaseManager will revert with `NoReleases()` if there are no releases for the operator set
8493
RELEASE_MANAGER.getLatestRelease(operatorSet);

src/contracts/cloud/ComputeRegistryStorage.sol

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ pragma solidity ^0.8.27;
44
import "../interfaces/IComputeRegistry.sol";
55
import "../interfaces/IReleaseManager.sol";
66
import "../interfaces/IAllocationManager.sol";
7+
import "../interfaces/IKeyRegistrar.sol";
8+
import "../interfaces/ICrossChainRegistry.sol";
79
import "../libraries/OperatorSetLib.sol";
810

911
abstract contract ComputeRegistryStorage is IComputeRegistry {
@@ -22,6 +24,12 @@ abstract contract ComputeRegistryStorage is IComputeRegistry {
2224
/// @notice The AllocationManager contract
2325
IAllocationManager public immutable ALLOCATION_MANAGER;
2426

27+
/// @notice The KeyRegistrar contract
28+
IKeyRegistrar public immutable KEY_REGISTRAR;
29+
30+
/// @notice The CrossChainRegistry contract
31+
ICrossChainRegistry public immutable CROSS_CHAIN_REGISTRY;
32+
2533
/// @notice The hash of the Terms of Service that AVS operators must sign
2634
bytes32 public immutable TOS_HASH;
2735

@@ -42,9 +50,17 @@ abstract contract ComputeRegistryStorage is IComputeRegistry {
4250
*/
4351
uint256[48] private __gap;
4452

45-
constructor(IReleaseManager _releaseManager, IAllocationManager _allocationManager, bytes32 _tosHash) {
53+
constructor(
54+
IReleaseManager _releaseManager,
55+
IAllocationManager _allocationManager,
56+
IKeyRegistrar _keyRegistrar,
57+
ICrossChainRegistry _crossChainRegistry,
58+
bytes32 _tosHash
59+
) {
4660
RELEASE_MANAGER = _releaseManager;
4761
ALLOCATION_MANAGER = _allocationManager;
62+
KEY_REGISTRAR = _keyRegistrar;
63+
CROSS_CHAIN_REGISTRY = _crossChainRegistry;
4864
TOS_HASH = _tosHash;
4965
}
5066
}

src/contracts/interfaces/IComputeRegistry.sol

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ interface IComputeRegistryErrors {
2626

2727
/// @dev Thrown when an invalid operator set is provided
2828
error InvalidOperatorSet();
29+
30+
/// @dev Thrown when the curve type for an operator set has not been set
31+
error CurveTypeNotSet();
32+
33+
/// @dev Thrown when the operator set does not have an active generation reservation
34+
error NoActiveGenerationReservation();
2935
}
3036

3137
interface IComputeRegistryEvents {
Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
// SPDX-License-Identifier: BUSL-1.1
22
pragma solidity ^0.8.27;
33

4-
import "forge-std/Test.sol";
4+
import "src/contracts/interfaces/ICrossChainRegistry.sol";
5+
import "src/contracts/libraries/OperatorSetLib.sol";
56

6-
import "src/contracts/multichain/CrossChainRegistry.sol";
7-
8-
contract CrossChainRegistryMock is Test, ICrossChainRegistryTypes {
7+
contract CrossChainRegistryMock {
98
using OperatorSetLib for OperatorSet;
109

11-
receive() external payable {}
12-
fallback() external payable {}
10+
mapping(bytes32 => bool) public generationReservations;
11+
12+
function hasActiveGenerationReservation(OperatorSet memory operatorSet) external view returns (bool) {
13+
bytes32 key = keccak256(abi.encode(operatorSet.avs, operatorSet.id));
14+
return generationReservations[key];
15+
}
16+
17+
// Helper function for testing
18+
function setHasActiveGenerationReservation(OperatorSet memory operatorSet, bool hasReservation) external {
19+
bytes32 key = keccak256(abi.encode(operatorSet.avs, operatorSet.id));
20+
generationReservations[key] = hasReservation;
21+
}
1322
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import "src/contracts/interfaces/IKeyRegistrar.sol";
5+
import "src/contracts/libraries/OperatorSetLib.sol";
6+
7+
contract KeyRegistrarMock {
8+
using OperatorSetLib for OperatorSet;
9+
10+
mapping(bytes32 => IKeyRegistrarTypes.CurveType) public operatorSetCurveTypes;
11+
12+
function getOperatorSetCurveType(OperatorSet memory operatorSet) external view returns (IKeyRegistrarTypes.CurveType) {
13+
bytes32 key = keccak256(abi.encode(operatorSet.avs, operatorSet.id));
14+
return operatorSetCurveTypes[key];
15+
}
16+
17+
// Helper function for testing
18+
function setOperatorSetCurveType(OperatorSet memory operatorSet, IKeyRegistrarTypes.CurveType curveType) external {
19+
bytes32 key = keccak256(abi.encode(operatorSet.avs, operatorSet.id));
20+
operatorSetCurveTypes[key] = curveType;
21+
}
22+
}

src/test/unit/ComputeRegistryUnit.t.sol

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import "src/contracts/cloud/ComputeRegistry.sol";
55
import "src/test/utils/EigenLayerUnitTestSetup.sol";
66
import "src/test/mocks/MockAVSRegistrar.sol";
77
import "src/test/mocks/ReleaseManagerMock.sol";
8+
import "src/test/mocks/KeyRegistrarMock.sol";
9+
import "src/test/mocks/CrossChainRegistryMock.sol";
810

911
contract ComputeRegistryUnitTests is EigenLayerUnitTestSetup, IComputeRegistryErrors, IComputeRegistryEvents {
1012
using StdStyle for *;
@@ -19,6 +21,8 @@ contract ComputeRegistryUnitTests is EigenLayerUnitTestSetup, IComputeRegistryEr
1921
// Contracts
2022
ComputeRegistry computeRegistry;
2123
ReleaseManagerMock releaseManagerMock;
24+
KeyRegistrarMock keyRegistrarMock;
25+
CrossChainRegistryMock crossChainRegistryMock;
2226

2327
// Test variables
2428
address defaultAVS;
@@ -31,6 +35,8 @@ contract ComputeRegistryUnitTests is EigenLayerUnitTestSetup, IComputeRegistryEr
3135

3236
// Setup mock contracts
3337
releaseManagerMock = new ReleaseManagerMock();
38+
keyRegistrarMock = new KeyRegistrarMock();
39+
crossChainRegistryMock = new CrossChainRegistryMock();
3440

3541
// Setup default test accounts
3642
defaultSignerPrivateKey = 0x1234;
@@ -41,6 +47,8 @@ contract ComputeRegistryUnitTests is EigenLayerUnitTestSetup, IComputeRegistryEr
4147
computeRegistry = new ComputeRegistry(
4248
IReleaseManager(address(releaseManagerMock)),
4349
IAllocationManager(address(allocationManagerMock)),
50+
IKeyRegistrar(address(keyRegistrarMock)),
51+
ICrossChainRegistry(address(crossChainRegistryMock)),
4452
IPermissionController(address(permissionController)),
4553
TOS_HASH,
4654
VERSION
@@ -52,6 +60,8 @@ contract ComputeRegistryUnitTests is EigenLayerUnitTestSetup, IComputeRegistryEr
5260
// Configure mocks
5361
allocationManagerMock.setIsOperatorSet(defaultOperatorSet, true);
5462
releaseManagerMock.setHasRelease(defaultOperatorSet, true);
63+
keyRegistrarMock.setOperatorSetCurveType(defaultOperatorSet, IKeyRegistrarTypes.CurveType.ECDSA);
64+
crossChainRegistryMock.setHasActiveGenerationReservation(defaultOperatorSet, true);
5565

5666
// Setup permissions for default signer to call registerForCompute and deregisterFromCompute
5767
vm.startPrank(defaultAVS);
@@ -82,6 +92,8 @@ contract ComputeRegistryUnitTests_Initialization is ComputeRegistryUnitTests {
8292
function test_initialization() public view {
8393
assertEq(address(computeRegistry.RELEASE_MANAGER()), address(releaseManagerMock));
8494
assertEq(address(computeRegistry.ALLOCATION_MANAGER()), address(allocationManagerMock));
95+
assertEq(address(computeRegistry.KEY_REGISTRAR()), address(keyRegistrarMock));
96+
assertEq(address(computeRegistry.CROSS_CHAIN_REGISTRY()), address(crossChainRegistryMock));
8597
assertEq(address(computeRegistry.permissionController()), address(permissionController));
8698
assertEq(computeRegistry.TOS_HASH(), TOS_HASH);
8799
assertEq(computeRegistry.MAX_EXPIRY(), MAX_EXPIRY);
@@ -164,6 +176,9 @@ contract ComputeRegistryUnitTests_RegisterForCompute is ComputeRegistryUnitTests
164176
OperatorSet memory operatorSet = OperatorSet(defaultAVS, 1);
165177
allocationManagerMock.setIsOperatorSet(operatorSet, true);
166178
releaseManagerMock.setHasRelease(operatorSet, false);
179+
// Set curve type and generation reservation so we get to the release check
180+
keyRegistrarMock.setOperatorSetCurveType(operatorSet, IKeyRegistrarTypes.CurveType.ECDSA);
181+
crossChainRegistryMock.setHasActiveGenerationReservation(operatorSet, true);
167182

168183
bytes memory signature = _generateTOSSignature(operatorSet, defaultSigner, defaultSignerPrivateKey);
169184

@@ -189,6 +204,60 @@ contract ComputeRegistryUnitTests_RegisterForCompute is ComputeRegistryUnitTests
189204
vm.expectRevert(ISignatureUtilsMixinErrors.InvalidSignature.selector);
190205
computeRegistry.registerForCompute(defaultOperatorSet, signature);
191206
}
207+
208+
function test_registerForCompute_revert_curveTypeNotSet() public {
209+
OperatorSet memory operatorSet = OperatorSet(defaultAVS, 2);
210+
allocationManagerMock.setIsOperatorSet(operatorSet, true);
211+
// Curve type defaults to NONE in the mock
212+
crossChainRegistryMock.setHasActiveGenerationReservation(operatorSet, true);
213+
releaseManagerMock.setHasRelease(operatorSet, true);
214+
215+
bytes memory signature = _generateTOSSignature(operatorSet, defaultSigner, defaultSignerPrivateKey);
216+
217+
vm.prank(defaultSigner);
218+
vm.expectRevert(CurveTypeNotSet.selector);
219+
computeRegistry.registerForCompute(operatorSet, signature);
220+
}
221+
222+
function test_registerForCompute_revert_noActiveGenerationReservation() public {
223+
OperatorSet memory operatorSet = OperatorSet(defaultAVS, 3);
224+
allocationManagerMock.setIsOperatorSet(operatorSet, true);
225+
keyRegistrarMock.setOperatorSetCurveType(operatorSet, IKeyRegistrarTypes.CurveType.BN254);
226+
// Generation reservation defaults to false in the mock
227+
releaseManagerMock.setHasRelease(operatorSet, true);
228+
229+
bytes memory signature = _generateTOSSignature(operatorSet, defaultSigner, defaultSignerPrivateKey);
230+
231+
vm.prank(defaultSigner);
232+
vm.expectRevert(NoActiveGenerationReservation.selector);
233+
computeRegistry.registerForCompute(operatorSet, signature);
234+
}
235+
236+
function test_registerForCompute_withDifferentCurveTypes() public {
237+
// Test with ECDSA curve type
238+
OperatorSet memory ecdsaOperatorSet = OperatorSet(defaultAVS, 4);
239+
allocationManagerMock.setIsOperatorSet(ecdsaOperatorSet, true);
240+
keyRegistrarMock.setOperatorSetCurveType(ecdsaOperatorSet, IKeyRegistrarTypes.CurveType.ECDSA);
241+
crossChainRegistryMock.setHasActiveGenerationReservation(ecdsaOperatorSet, true);
242+
releaseManagerMock.setHasRelease(ecdsaOperatorSet, true);
243+
244+
bytes memory signature1 = _generateTOSSignature(ecdsaOperatorSet, defaultSigner, defaultSignerPrivateKey);
245+
vm.prank(defaultSigner);
246+
computeRegistry.registerForCompute(ecdsaOperatorSet, signature1);
247+
assertTrue(computeRegistry.isOperatorSetRegistered(ecdsaOperatorSet.key()));
248+
249+
// Test with BN254 curve type
250+
OperatorSet memory bn254OperatorSet = OperatorSet(defaultAVS, 5);
251+
allocationManagerMock.setIsOperatorSet(bn254OperatorSet, true);
252+
keyRegistrarMock.setOperatorSetCurveType(bn254OperatorSet, IKeyRegistrarTypes.CurveType.BN254);
253+
crossChainRegistryMock.setHasActiveGenerationReservation(bn254OperatorSet, true);
254+
releaseManagerMock.setHasRelease(bn254OperatorSet, true);
255+
256+
bytes memory signature2 = _generateTOSSignature(bn254OperatorSet, defaultSigner, defaultSignerPrivateKey);
257+
vm.prank(defaultSigner);
258+
computeRegistry.registerForCompute(bn254OperatorSet, signature2);
259+
assertTrue(computeRegistry.isOperatorSetRegistered(bn254OperatorSet.key()));
260+
}
192261
}
193262

194263
contract ComputeRegistryUnitTests_DeregisterFromCompute is ComputeRegistryUnitTests {

0 commit comments

Comments
 (0)