Skip to content

Commit

Permalink
feat: updateTargetValidatorsLimits implementation
Browse files Browse the repository at this point in the history
fix: reworked depositableValidatorsCount calculations
a lot of new tests
  • Loading branch information
skhomuti committed Nov 23, 2023
1 parent 60bd48f commit c682cd7
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 39 deletions.
28 changes: 20 additions & 8 deletions src/CSModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -555,9 +555,16 @@ contract CSModule is IStakingModule, CSModuleBase {
stuckPenaltyEndTimestamp = no.stuckPenaltyEndTimestamp;
totalExitedValidators = no.totalExitedKeys;
totalDepositedValidators = no.totalDepositedKeys;
depositableValidatorsCount = no.isTargetLimitActive
? no.targetLimit - no.totalDepositedKeys
: no.totalVettedKeys - no.totalDepositedKeys;
depositableValidatorsCount =
no.totalVettedKeys -
totalDepositedValidators;
if (no.isTargetLimitActive) {
depositableValidatorsCount = targetValidatorsCount <=
totalDepositedValidators
? 0
: Math.min(targetValidatorsCount, no.totalVettedKeys) -
totalDepositedValidators;
}
}

function getNonce() external view returns (uint256) {
Expand Down Expand Up @@ -657,11 +664,16 @@ contract CSModule is IStakingModule, CSModuleBase {
}

function updateTargetValidatorsLimits(
uint256 /*_nodeOperatorId*/,
bool /*_isTargetLimitActive*/,
uint256 /*_targetLimit*/
) external {
// TODO: implement
uint256 nodeOperatorId,
bool isTargetLimitActive,
uint256 targetLimit
) external onlyExistingNodeOperator(nodeOperatorId) onlyStakingRouter {
// TODO sanity checks?
NodeOperator storage no = _nodeOperators[nodeOperatorId];
no.isTargetLimitActive = isTargetLimitActive;
no.targetLimit = targetLimit;
emit TargetValidatorsCountChanged(nodeOperatorId, targetLimit);
_incrementNonce();
}

function onExitedAndStuckValidatorsCountsUpdated() external {
Expand Down
8 changes: 5 additions & 3 deletions src/lib/ValidatorCountsReport.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ library ValidatorCountsReport {
}

function validate(bytes calldata ids, bytes calldata counts) internal pure {
uint256 count = count(ids);
if (
counts.length / 16 != count ||
counts.length / 16 != count(ids) ||
ids.length % 8 != 0 ||
counts.length % 16 != 0) revert InvalidReportData();
counts.length % 16 != 0
) {
revert InvalidReportData();
}
}

function next(
Expand Down
184 changes: 156 additions & 28 deletions test/CSModule.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ contract CSMCommon is Test, Fixtures, Utilities, CSModuleBase {
address internal alice;
address internal nodeOperator;

struct NodeOperatorSummary {
bool isTargetLimitActive;
uint256 targetValidatorsCount;
uint256 stuckValidatorsCount;
uint256 refundedValidatorsCount;
uint256 stuckPenaltyEndTimestamp;
uint256 totalExitedValidators;
uint256 totalDepositedValidators;
uint256 depositableValidatorsCount;
}

function setUp() public {
alice = address(1);
nodeOperator = address(2);
Expand Down Expand Up @@ -80,6 +91,32 @@ contract CSMCommon is Test, Fixtures, Utilities, CSModuleBase {
);
return csm.getNodeOperatorsCount() - 1;
}

function getNodeOperatorSummary(
uint256 noId
) public returns (NodeOperatorSummary memory) {
(
bool isTargetLimitActive,
uint256 targetValidatorsCount,
uint256 stuckValidatorsCount,
uint256 refundedValidatorsCount,
uint256 stuckPenaltyEndTimestamp,
uint256 totalExitedValidators,
uint256 totalDepositedValidators,
uint256 depositableValidatorsCount
) = csm.getNodeOperatorSummary(noId);
return
NodeOperatorSummary({
isTargetLimitActive: isTargetLimitActive,
targetValidatorsCount: targetValidatorsCount,
stuckValidatorsCount: stuckValidatorsCount,
refundedValidatorsCount: refundedValidatorsCount,
stuckPenaltyEndTimestamp: stuckPenaltyEndTimestamp,
totalExitedValidators: totalExitedValidators,
totalDepositedValidators: totalDepositedValidators,
depositableValidatorsCount: depositableValidatorsCount
});
}
}

contract CsmInitialization is CSMCommon {
Expand Down Expand Up @@ -671,24 +708,120 @@ contract CsmVetKeys is CSMCommon {
contract CsmGetNodeOperatorSummary is CSMCommon {
// TODO add more tests here

function test_depositableValidatorsCount_whenStuckKeys() public {
function test_getNodeOperatorSummary_defaultValues() public {
uint256 noId = createNodeOperator();

NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertEq(summary.isTargetLimitActive, false);
assertEq(summary.targetValidatorsCount, 0);
assertEq(summary.stuckValidatorsCount, 0);
assertEq(summary.refundedValidatorsCount, 0);
assertEq(summary.stuckPenaltyEndTimestamp, 0);
assertEq(summary.totalExitedValidators, 0);
assertEq(summary.totalDepositedValidators, 0);
assertEq(summary.depositableValidatorsCount, 0);
}

function test_getNodeOperatorSummary_vetKeys() public {
uint256 noId = createNodeOperator(2);
csm.vetKeys(noId, 1);

NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertEq(summary.depositableValidatorsCount, 1);
assertEq(summary.totalDepositedValidators, 0);
}

function test_getNodeOperatorSummary_depositedKey() public {
uint256 noId = createNodeOperator(2);
csm.vetKeys(noId, 1);
csm.obtainDepositData(1, "");

NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertEq(summary.depositableValidatorsCount, 0);
assertEq(summary.totalDepositedValidators, 1);
}

function test_getNodeOperatorSummary_targetLimit() public {
uint256 noId = createNodeOperator(3);
csm.vetKeys(noId, 3);

csm.updateTargetValidatorsLimits(noId, true, 1);
NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);

summary = getNodeOperatorSummary(noId);
assertEq(summary.targetValidatorsCount, 1);
assertTrue(summary.isTargetLimitActive);
assertEq(summary.depositableValidatorsCount, 0);
}

function test_getNodeOperatorSummary_targetLimitEqualToDepositedKeys()
public
{
uint256 noId = createNodeOperator(3);
csm.vetKeys(noId, 1);
csm.obtainDepositData(1, "");

(, , , , , , , uint256 depositableValidatorsCount) = csm
.getNodeOperatorSummary(noId);
assertEq(depositableValidatorsCount, 2);
csm.updateTargetValidatorsLimits(noId, true, 1);
NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertTrue(summary.isTargetLimitActive);
assertEq(summary.targetValidatorsCount, 1);
assertEq(summary.depositableValidatorsCount, 0);
}

csm.updateStuckValidatorsCount(
bytes.concat(bytes8(0x0000000000000000)),
bytes.concat(bytes16(0x00000000000000000000000000000001))
);
function test_getNodeOperatorSummary_targetLimitLowerThanDepositedKeys()
public
{
uint256 noId = createNodeOperator(3);
csm.vetKeys(noId, 3);
csm.obtainDepositData(2, "");

(, , , , , , , depositableValidatorsCount) = csm.getNodeOperatorSummary(
noId
);
assertEq(depositableValidatorsCount, 0);
csm.updateTargetValidatorsLimits(noId, true, 1);
NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertTrue(summary.isTargetLimitActive);
assertEq(summary.targetValidatorsCount, 1);
assertEq(summary.depositableValidatorsCount, 0);
}

function test_getNodeOperatorSummary_targetLimitLowerThanVettedKeys()
public
{
uint256 noId = createNodeOperator(3);
csm.vetKeys(noId, 3);

csm.updateTargetValidatorsLimits(noId, true, 2);
NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertTrue(summary.isTargetLimitActive);
assertEq(summary.targetValidatorsCount, 2);
assertEq(summary.depositableValidatorsCount, 2);
}

function test_getNodeOperatorSummary_targetLimitHigherThanVettedKeys()
public
{
uint256 noId = createNodeOperator(3);
csm.vetKeys(noId, 3);

csm.updateTargetValidatorsLimits(noId, true, 5);
NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertTrue(summary.isTargetLimitActive);
assertEq(summary.targetValidatorsCount, 5);
assertEq(summary.depositableValidatorsCount, 3);
}
}

contract CsmUpdateTargetValidatorsLimits is CSMCommon {
function test_updateTargetValidatorsLimits() public {
uint256 noId = createNodeOperator();

vm.expectEmit(true, true, false, true, address(csm));
emit TargetValidatorsCountChanged(noId, 1);
csm.updateTargetValidatorsLimits(noId, true, 1);
}

function test_updateTargetValidatorsLimits_RevertWhenNoNodeOperator()
public
{
vm.expectRevert(NodeOperatorDoesNotExist.selector);
csm.updateTargetValidatorsLimits(0, true, 1);
}
}

Expand All @@ -707,22 +840,17 @@ contract CsmUpdateStuckValidatorsCount is CSMCommon {
bytes.concat(bytes16(0x00000000000000000000000000000001))
);

(
bool isTargetLimitActive,
uint256 targetValidatorsCount,
uint256 stuckValidatorsCount,
,
,
,
uint256 totalDepositedValidators,

) = csm.getNodeOperatorSummary(noId);
assertEq(stuckValidatorsCount, 1, "stuckValidatorsCount");
NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertEq(
summary.stuckValidatorsCount,
1,
"stuckValidatorsCount not increased"
);
assertEq(
targetValidatorsCount,
totalDepositedValidators,
"targetValidatorsCount"
summary.targetValidatorsCount,
summary.totalDepositedValidators,
"targetValidatorsCount should be limited to totalDepositedValidators"
);
assertTrue(isTargetLimitActive, "isTargetLimitActive");
assertTrue(summary.isTargetLimitActive, "isTargetLimitActive is false");
}
}

0 comments on commit c682cd7

Please sign in to comment.