Skip to content

Commit

Permalink
Only allow approved operators to register nodes, expose nodes by oper…
Browse files Browse the repository at this point in the history
  • Loading branch information
pfives and jterzis authored Jun 13, 2024
1 parent 98fadea commit ea8c3cb
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ contract DeployEntitlementChecker is Deployer, FacetHelper {
addSelector(EntitlementChecker.getNodeAtIndex.selector);
addSelector(EntitlementChecker.getRandomNodes.selector);
addSelector(EntitlementChecker.requestEntitlementCheck.selector);
addSelector(EntitlementChecker.getNodesByOperator.selector);
}

function initializer() public pure override returns (bytes4) {
Expand Down
44 changes: 41 additions & 3 deletions contracts/src/base/registry/facets/checker/EntitlementChecker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {IEntitlementChecker} from "./IEntitlementChecker.sol";
// libraries
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {EntitlementCheckerStorage} from "./EntitlementCheckerStorage.sol";
import {NodeOperatorStorage} from "contracts/src/base/registry/facets/operator/NodeOperatorStorage.sol";
import {NodeOperatorStorage, NodeOperatorStatus} from "contracts/src/base/registry/facets/operator/NodeOperatorStorage.sol";

// contracts
import {Facet} from "contracts/src/diamond/facets/Facet.sol";
Expand Down Expand Up @@ -35,13 +35,20 @@ contract EntitlementChecker is IEntitlementChecker, Facet {
_;
}

modifier onlyRegisteredOperator() {
modifier onlyRegisteredApprovedOperator() {
NodeOperatorStorage.Layout storage nodeOperatorLayout = NodeOperatorStorage
.layout();

if (!nodeOperatorLayout.operators.contains(msg.sender))
revert EntitlementChecker_InvalidOperator();
_;

if (
nodeOperatorLayout.statusByOperator[msg.sender] !=
NodeOperatorStatus.Approved
) {
revert EntitlementChecker_OperatorNotActive();
}
}

// =============================================================
Expand All @@ -53,7 +60,7 @@ contract EntitlementChecker is IEntitlementChecker, Facet {
* @param node The address of the node to register
* @dev Only valid operators can register a node
*/
function registerNode(address node) external onlyRegisteredOperator {
function registerNode(address node) external onlyRegisteredApprovedOperator {
EntitlementCheckerStorage.Layout storage layout = EntitlementCheckerStorage
.layout();

Expand Down Expand Up @@ -153,6 +160,37 @@ contract EntitlementChecker is IEntitlementChecker, Facet {
);
}

/**
* @notice Get the nodes registered by an operator
* @param operator The address of the operator
* @return An array of node addresses
*/
function getNodesByOperator(
address operator
) external view returns (address[] memory) {
EntitlementCheckerStorage.Layout storage layout = EntitlementCheckerStorage
.layout();
uint256 totalNodeCount = layout.nodes.length();
uint256 nodeCount = 0;
for (uint256 i = 0; i < totalNodeCount; i++) {
address node = layout.nodes.at(i);
if (layout.operatorByNode[node] == operator) {
nodeCount++;
}
}
address[] memory nodes = new address[](nodeCount);
uint256 j = 0;
for (uint256 i = 0; i < totalNodeCount; i++) {
address node = layout.nodes.at(i);
if (layout.operatorByNode[node] == operator) {
nodes[j] = node;
j++;
}
}

return nodes;
}

// =============================================================
// Internal
// =============================================================
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface IEntitlementCheckerBase {
error EntitlementChecker_InsufficientNumberOfNodes();
error EntitlementChecker_InvalidNodeOperator();
error EntitlementChecker_InvalidOperator();
error EntitlementChecker_OperatorNotActive();

// Events
event NodeRegistered(address indexed nodeAddress);
Expand Down Expand Up @@ -42,4 +43,8 @@ interface IEntitlementChecker is IEntitlementCheckerBase {
uint256 roleId,
address[] memory nodes
) external;

function getNodesByOperator(
address operator
) external view returns (address[] memory);
}
38 changes: 37 additions & 1 deletion contracts/test/crosschain/EntitlementChecker.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {BaseSetup} from "contracts/test/spaces/BaseSetup.sol";

//interfaces
import {IEntitlementCheckerBase} from "contracts/src/base/registry/facets/checker/IEntitlementChecker.sol";
import {NodeOperatorStatus} from "contracts/src/base/registry/facets/operator/NodeOperatorStorage.sol";

//libraries

Expand All @@ -31,6 +32,12 @@ contract EntitlementCheckerTest is BaseSetup, IEntitlementCheckerBase {
_;
}

modifier givenOperatorIsApproved(address operator) {
vm.prank(deployer);
nodeOperator.setOperatorStatus(operator, NodeOperatorStatus.Approved);
_;
}

modifier givenNodeIsRegistered(address operator, address node) {
vm.assume(node != address(0));
vm.assume(!entitlementChecker.isValidNode(node));
Expand Down Expand Up @@ -60,6 +67,7 @@ contract EntitlementCheckerTest is BaseSetup, IEntitlementCheckerBase {
)
external
givenOperatorIsRegistered(operator)
givenOperatorIsApproved(operator)
givenNodeIsRegistered(operator, node)
{
assertTrue(entitlementChecker.isValidNode(node));
Expand All @@ -71,6 +79,7 @@ contract EntitlementCheckerTest is BaseSetup, IEntitlementCheckerBase {
)
external
givenOperatorIsRegistered(operator)
givenOperatorIsApproved(operator)
givenNodeIsRegistered(operator, node)
{
vm.prank(operator);
Expand All @@ -87,6 +96,7 @@ contract EntitlementCheckerTest is BaseSetup, IEntitlementCheckerBase {
)
external
givenOperatorIsRegistered(operator)
givenOperatorIsApproved(operator)
givenNodeIsRegistered(operator, node)
givenNodeIsNotRegistered(operator, node)
{
Expand All @@ -96,7 +106,11 @@ contract EntitlementCheckerTest is BaseSetup, IEntitlementCheckerBase {
function test_unregisterNode_revert_nodeNotRegistered(
address operator,
address node
) external givenOperatorIsRegistered(operator) {
)
external
givenOperatorIsRegistered(operator)
givenOperatorIsApproved(operator)
{
vm.prank(operator);
vm.expectRevert(EntitlementChecker_InvalidNodeOperator.selector);
entitlementChecker.unregisterNode(node);
Expand All @@ -121,4 +135,26 @@ contract EntitlementCheckerTest is BaseSetup, IEntitlementCheckerBase {
vm.expectRevert(EntitlementChecker_InsufficientNumberOfNodes.selector);
entitlementChecker.getRandomNodes(26);
}

// =============================================================
// Nodes by Operator
// =============================================================

function test_getNodesByOperator() external {
for (uint256 i = 0; i < operators.length; i++) {
uint256 totalNodes = 0;

address[] memory nodes = entitlementChecker.getNodesByOperator(
operators[i]
);
uint256 nodeLen = nodes.length;

for (uint256 j = 0; j < nodeLen; j++) {
vm.prank(operators[i]);
assertTrue(entitlementChecker.isValidNode(nodes[j]));
totalNodes++;
}
assertEq(totalNodes, nodes.length);
}
}
}
3 changes: 3 additions & 0 deletions contracts/test/spaces/BaseSetup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {IWalletLink} from "contracts/src/factory/facets/wallet-link/IWalletLink.
import {ISpaceOwner} from "contracts/src/spaces/facets/owner/ISpaceOwner.sol";
import {IMainnetDelegation} from "contracts/src/tokens/river/base/delegation/IMainnetDelegation.sol";
import {INodeOperator} from "contracts/src/base/registry/facets/operator/INodeOperator.sol";
import {NodeOperatorStatus} from "contracts/src/base/registry/facets/operator/NodeOperatorStorage.sol";

// libraries

Expand Down Expand Up @@ -149,6 +150,8 @@ contract BaseSetup is TestUtils, SpaceHelper {
for (uint256 i = 0; i < operators.length; i++) {
vm.prank(operators[i]);
nodeOperator.registerOperator(operators[i]);
vm.prank(deployer);
nodeOperator.setOperatorStatus(operators[i], NodeOperatorStatus.Approved);
}
}

Expand Down
9 changes: 9 additions & 0 deletions core/xchain/create_multi.sh
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,15 @@ cast send \
$OPERATOR_ADDRESS \
2 > /dev/null

# set operator to approved
cast send \
--rpc-url http://127.0.0.1:8545 \
--private-key $TESTNET_PRIVATE_KEY \
$BASE_REGISTRY_ADDRESS \
"setOperatorStatus(address,uint8)" \
$OPERATOR_ADDRESS \
2 \
2 > /dev/null

# Number of instances
N=5
Expand Down

0 comments on commit ea8c3cb

Please sign in to comment.