// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import {CapabilitiesRegistry} from "../CapabilitiesRegistry.sol"; import {BaseTest} from "./BaseTest.t.sol"; contract CapabilitiesRegistry_AddNodesTest is BaseTest { function setUp() public override { BaseTest.setUp(); CapabilitiesRegistry.Capability[] memory capabilities = new CapabilitiesRegistry.Capability[](2); capabilities[0] = s_basicCapability; capabilities[1] = s_capabilityWithConfigurationContract; changePrank(ADMIN); s_CapabilitiesRegistry.addNodeOperators(_getNodeOperators()); s_CapabilitiesRegistry.addCapabilities(capabilities); } function test_RevertWhen_CalledByNonNodeOperatorAdminAndNonOwner() public { changePrank(STRANGER); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.AccessForbidden.selector, STRANGER)); s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_AddingNodeWithInvalidNodeOperator() public { changePrank(ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; uint32 invalidNodeOperatorId = 10_000; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: invalidNodeOperatorId, // Invalid NOP p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert( abi.encodeWithSelector(CapabilitiesRegistry.NodeOperatorDoesNotExist.selector, invalidNodeOperatorId) ); s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_SignerAddressEmpty() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: bytes32(""), encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_EncryptionPublicKeyEmpty() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: bytes32(""), hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeEncryptionPublicKey.selector, bytes32(""))); s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_SignerAddressNotUnique() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); s_CapabilitiesRegistry.addNodes(nodes); changePrank(NODE_OPERATOR_TWO_ADMIN); // Try adding another node with the same signer address nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_TWO_ID, p2pId: P2P_ID_TWO, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeSigner.selector)); s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_AddingDuplicateP2PId() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); s_CapabilitiesRegistry.addNodes(nodes); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.NodeAlreadyExists.selector, P2P_ID)); s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_P2PIDEmpty() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_basicHashedCapabilityId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: bytes32(""), signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeP2PId.selector, bytes32(""))); s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_AddingNodeWithoutCapabilities() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](0); nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); s_CapabilitiesRegistry.addNodes(nodes); } function test_RevertWhen_AddingNodeWithInvalidCapability() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](1); hashedCapabilityIds[0] = s_nonExistentHashedCapabilityId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectRevert(abi.encodeWithSelector(CapabilitiesRegistry.InvalidNodeCapabilities.selector, hashedCapabilityIds)); s_CapabilitiesRegistry.addNodes(nodes); } function test_AddsNodeParams() public { changePrank(NODE_OPERATOR_ONE_ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](2); hashedCapabilityIds[0] = s_basicHashedCapabilityId; hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectEmit(address(s_CapabilitiesRegistry)); emit CapabilitiesRegistry.NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); s_CapabilitiesRegistry.addNodes(nodes); CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); assertEq(node.p2pId, P2P_ID); assertEq(node.hashedCapabilityIds.length, 2); assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); assertEq(node.configCount, 1); } function test_OwnerCanAddNodes() public { changePrank(ADMIN); CapabilitiesRegistry.NodeParams[] memory nodes = new CapabilitiesRegistry.NodeParams[](1); bytes32[] memory hashedCapabilityIds = new bytes32[](2); hashedCapabilityIds[0] = s_basicHashedCapabilityId; hashedCapabilityIds[1] = s_capabilityWithConfigurationContractId; nodes[0] = CapabilitiesRegistry.NodeParams({ nodeOperatorId: TEST_NODE_OPERATOR_ONE_ID, p2pId: P2P_ID, signer: NODE_OPERATOR_ONE_SIGNER_ADDRESS, encryptionPublicKey: TEST_ENCRYPTION_PUBLIC_KEY, hashedCapabilityIds: hashedCapabilityIds }); vm.expectEmit(address(s_CapabilitiesRegistry)); emit CapabilitiesRegistry.NodeAdded(P2P_ID, TEST_NODE_OPERATOR_ONE_ID, NODE_OPERATOR_ONE_SIGNER_ADDRESS); s_CapabilitiesRegistry.addNodes(nodes); CapabilitiesRegistry.NodeInfo memory node = s_CapabilitiesRegistry.getNode(P2P_ID); assertEq(node.nodeOperatorId, TEST_NODE_OPERATOR_ONE_ID); assertEq(node.p2pId, P2P_ID); assertEq(node.hashedCapabilityIds.length, 2); assertEq(node.hashedCapabilityIds[0], s_basicHashedCapabilityId); assertEq(node.hashedCapabilityIds[1], s_capabilityWithConfigurationContractId); assertEq(node.configCount, 1); } }