Skip to content

Commit

Permalink
refactor cluster and operators libraries
Browse files Browse the repository at this point in the history
  • Loading branch information
mtabasco committed Dec 15, 2023
1 parent d24c4a2 commit 331420f
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 222 deletions.
71 changes: 71 additions & 0 deletions contracts/libraries/ClusterLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ pragma solidity 0.8.18;

import "../interfaces/ISSVNetworkCore.sol";
import "./SSVStorage.sol";
import "./SSVStorageProtocol.sol";
import "./OperatorLib.sol";
import "./ProtocolLib.sol";
import "./Types.sol";

library ClusterLib {
using Types64 for uint64;
using ProtocolLib for StorageProtocol;

function updateBalance(
ISSVNetworkCore.Cluster memory cluster,
Expand Down Expand Up @@ -80,4 +84,71 @@ library ClusterLib {
)
);
}

function validateClusterOnRegistration(
ISSVNetworkCore.Cluster memory cluster,
uint64[] memory operatorIds,
StorageData storage s
) internal view returns (bytes32 hashedCluster) {
hashedCluster = keccak256(abi.encodePacked(msg.sender, operatorIds));

bytes32 clusterData = s.clusters[hashedCluster];
if (clusterData == bytes32(0)) {
if (
cluster.validatorCount != 0 ||
cluster.networkFeeIndex != 0 ||
cluster.index != 0 ||
cluster.balance != 0 ||
!cluster.active
) {
revert ISSVNetworkCore.IncorrectClusterState();
}
} else if (clusterData != hashClusterData(cluster)) {
revert ISSVNetworkCore.IncorrectClusterState();
} else {
validateClusterIsNotLiquidated(cluster);
}
}

function updateClusterOnRegistration(
ISSVNetworkCore.Cluster memory cluster,
uint64[] memory operatorIds,
bytes32 hashedCluster,
uint32 validatorCountDelta,
StorageData storage s,
StorageProtocol storage sp
) internal {
uint64 burnRate;

if (cluster.active) {
(uint64 clusterIndex, uint64 burnRate) = OperatorLib.updateClusterOperators(
operatorIds,
true,
true,
validatorCountDelta,
s,
sp
);

updateClusterData(cluster, clusterIndex, sp.currentNetworkFeeIndex());

sp.updateDAO(true, validatorCountDelta);
}

cluster.validatorCount += validatorCountDelta;

if (
isLiquidatable(
cluster,
burnRate,
sp.networkFee,
sp.minimumBlocksBeforeLiquidation,
sp.minimumLiquidationCollateral
)
) {
revert ISSVNetworkCore.InsufficientBalance();
}

s.clusters[hashedCluster] = hashClusterData(cluster);
}
}
55 changes: 45 additions & 10 deletions contracts/libraries/OperatorLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,29 +30,64 @@ library OperatorLib {
if (operator.owner != msg.sender) revert ISSVNetworkCore.CallerNotOwner();
}

function updateOperators(
function updateClusterOperators(
uint64[] memory operatorIds,
bool isRegisteringValidator,
bool increaseValidatorCount,
uint32 deltaValidatorCount,
StorageData storage s,
StorageProtocol storage sp
) internal returns (uint64 clusterIndex, uint64 burnRate) {
) internal returns (uint64 cumulativeIndex, uint64 cumulativeFee) {
uint256 operatorsLength = operatorIds.length;

for (uint256 i; i < operatorsLength; ) {
uint64 operatorId = operatorIds[i];
ISSVNetworkCore.Operator storage operator = s.operators[operatorId];
if (operator.snapshot.block != 0) {
updateSnapshotSt(operator);
if (!increaseValidatorCount) {
operator.validatorCount -= deltaValidatorCount;
} else if ((operator.validatorCount += deltaValidatorCount) > sp.validatorsPerOperatorLimit) {

if (!isRegisteringValidator) {
ISSVNetworkCore.Operator storage operator = s.operators[operatorId];

if (operator.snapshot.block != 0) {
updateSnapshotSt(operator);
if (!increaseValidatorCount) {
operator.validatorCount -= deltaValidatorCount;
} else if ((operator.validatorCount += deltaValidatorCount) > sp.validatorsPerOperatorLimit) {
revert ISSVNetworkCore.ExceedValidatorLimit();
}

cumulativeFee += operator.fee;
}
cumulativeIndex += operator.snapshot.index;
} else {
if (i + 1 < operatorsLength) {
if (operatorId > operatorIds[i + 1]) {
revert ISSVNetworkCore.UnsortedOperatorsList();
} else if (operatorId == operatorIds[i + 1]) {
revert ISSVNetworkCore.OperatorsListNotUnique();
}
}
ISSVNetworkCore.Operator memory operator = s.operators[operatorId];

if (operator.snapshot.block == 0) {
revert ISSVNetworkCore.OperatorDoesNotExist();
}
if (operator.whitelisted) {
address whitelisted = s.operatorsWhitelist[operatorId];
if (whitelisted != address(0) && whitelisted != msg.sender) {
revert ISSVNetworkCore.CallerNotWhitelisted();
}
}

updateSnapshot(operator);
if ((operator.validatorCount += deltaValidatorCount) > sp.validatorsPerOperatorLimit) {
revert ISSVNetworkCore.ExceedValidatorLimit();
}
burnRate += operator.fee;

cumulativeFee += operator.fee;
cumulativeIndex += operator.snapshot.index;

s.operators[operatorId] = operator;
}

clusterIndex += operator.snapshot.index;
unchecked {
++i;
}
Expand Down
15 changes: 15 additions & 0 deletions contracts/libraries/ValidatorLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,23 @@ import "../interfaces/ISSVNetworkCore.sol";
import "./SSVStorage.sol";

library ValidatorLib {
uint64 private constant MIN_OPERATORS_LENGTH = 4;
uint64 private constant MAX_OPERATORS_LENGTH = 13;
uint64 private constant MODULO_OPERATORS_LENGTH = 3;
uint64 private constant PUBLIC_KEY_LENGTH = 48;

function validateOperatorsLength(uint64[] memory operatorIds) internal pure {
uint256 operatorsLength = operatorIds.length;

if (
operatorsLength < MIN_OPERATORS_LENGTH ||
operatorsLength > MAX_OPERATORS_LENGTH ||
operatorsLength % MODULO_OPERATORS_LENGTH != 1
) {
revert ISSVNetworkCore.InvalidOperatorIdsLength();
}
}

function registerPublicKeys(
bytes[] calldata publicKeys,
uint64[] memory operatorIds,
Expand Down
Loading

0 comments on commit 331420f

Please sign in to comment.