Skip to content

Commit

Permalink
tests: some queue tests
Browse files Browse the repository at this point in the history
  • Loading branch information
madlabman committed Mar 20, 2024
1 parent 1831f55 commit 3bc7499
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/CSModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ contract CSModule is ICSModule, CSModuleBase, AccessControl, PausableUntil {
info.totalWithdrawnValidators = no.totalWithdrawnKeys;
info.totalAddedValidators = no.totalAddedKeys;
info.totalDepositedValidators = no.totalDepositedKeys;
info.enqueuedCount = no.enqueuedCount;
return info;
}

Expand Down
1 change: 1 addition & 0 deletions src/interfaces/ICSModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface ICSModule is IStakingModule {
uint256 totalWithdrawnValidators;
uint256 totalAddedValidators;
uint256 totalDepositedValidators;
uint256 enqueuedCount;
}

/// @notice Returns the node operator by id
Expand Down
101 changes: 96 additions & 5 deletions test/CSModule.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ abstract contract CSMFixtures is Test, Fixtures, Utilities, CSModuleBase {
csm.decreaseOperatorVettedKeys(UintArr(noId), UintArr(to));
}

function setStuck(uint256 noId, uint256 to) internal {
csm.updateStuckValidatorsCount(
bytes.concat(bytes8(uint64(noId))),
bytes.concat(bytes16(uint128(to)))
);
}

// Checks that the queue is in the expected state starting from its head.
function _assertQueueState(BatchInfo[] memory exp) internal {
(uint128 curr, ) = csm.queue(); // queue.head
Expand Down Expand Up @@ -792,16 +799,31 @@ contract CSMObtainDepositData is CSMCommon {
function test_obtainDepositData_counters() public {
uint256 noId = createNodeOperator();

vm.expectEmit(true, true, false, true, address(csm));
vm.expectEmit(true, true, true, true, address(csm));
emit DepositedSigningKeysCountChanged(noId, 1);
csm.obtainDepositData(1, "");

CSModule.NodeOperatorInfo memory no = csm.getNodeOperator(0);
NodeOperatorSummary memory summary = getNodeOperatorSummary(0);
CSModule.NodeOperatorInfo memory no = csm.getNodeOperator(noId);
NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertEq(no.enqueuedCount, 0);
assertEq(no.totalDepositedValidators, 1);
assertEq(summary.depositableValidatorsCount, 0);
}

function test_obtainDepositData_counters_WhenLessThanLastBatch() public {
uint256 noId = createNodeOperator(7);

vm.expectEmit(true, true, true, true, address(csm));
emit DepositedSigningKeysCountChanged(noId, 3);
csm.obtainDepositData(3, "");

CSModule.NodeOperatorInfo memory no = csm.getNodeOperator(noId);
NodeOperatorSummary memory summary = getNodeOperatorSummary(noId);
assertEq(no.enqueuedCount, 4);
assertEq(no.totalDepositedValidators, 3);
assertEq(summary.depositableValidatorsCount, 4);
}

function test_obtainDepositData_RevertWhenNoMoreKeys() public {
vm.expectRevert(NotEnoughKeys.selector);
csm.obtainDepositData(1, "");
Expand Down Expand Up @@ -1180,15 +1202,60 @@ contract CsmQueueOps is CSMCommon {
csm.cleanDepositQueue(LOOKUP_DEPTH);
_assertQueueIsEmpty();
}

function test_normalizeQueue_NothingToDo() public {
// `normalizeQueue` will be called on creating a node operator and uploading a key.
uint256 noId = createNodeOperator();

vm.recordLogs();
vm.prank(nodeOperator);
csm.normalizeQueue(noId);
Vm.Log[] memory logs = vm.getRecordedLogs();
assertEq(logs.length, 0);
}

function test_normalizeQueue_OnSkippedKeys_WhenStuckKeys() public {
uint256 noId = createNodeOperator(7);
csm.obtainDepositData(3, "");
setStuck(noId, 1);
csm.cleanDepositQueue(1);
setStuck(noId, 0);

vm.expectEmit(true, true, true, true, address(csm));
emit BatchEnqueued(noId, 4);

vm.prank(nodeOperator);
csm.normalizeQueue(noId);
}

function test_normalizeQueue_OnSkippedKeys_WhenTargetLimit() public {
uint256 noId = createNodeOperator(7);
csm.updateTargetValidatorsLimits({
nodeOperatorId: noId,
isTargetLimitActive: true,
targetLimit: 0
});
csm.cleanDepositQueue(1);
csm.updateTargetValidatorsLimits({
nodeOperatorId: noId,
isTargetLimitActive: true,
targetLimit: 7
});

vm.expectEmit(true, true, true, true, address(csm));
emit BatchEnqueued(noId, 7);

vm.prank(nodeOperator);
csm.normalizeQueue(noId);
}
}

contract CsmUnvetKeys is CSMCommon {
// TODO: more tests for unvetKeys
function test_unvetKeys_counters() public {
uint256 noId = createNodeOperator(3);
uint256 nonce = csm.getNonce();

vm.expectEmit(true, true, false, true, address(csm));
vm.expectEmit(true, true, true, true, address(csm));
emit VettedSigningKeysCountChanged(noId, 1);
unvetKeys({ noId: noId, to: 1 });

Expand All @@ -1198,6 +1265,30 @@ contract CsmUnvetKeys is CSMCommon {
assertEq(no.totalVettedValidators, 1);
assertEq(summary.depositableValidatorsCount, 1);
}

function test_unvetKeys_MultipleOperators() public {
createNodeOperator(3);
createNodeOperator(7);
uint256 nonce = csm.getNonce();

vm.expectEmit(true, true, true, true, address(csm));
emit VettedSigningKeysCountChanged(0, 2);
emit VettedSigningKeysCountChanged(1, 3);
csm.decreaseOperatorVettedKeys(UintArr(0, 1), UintArr(2, 3));

assertEq(csm.getNonce(), nonce + 1);
CSModule.NodeOperatorInfo memory no;
no = csm.getNodeOperator(0);
assertEq(no.totalVettedValidators, 2);
no = csm.getNodeOperator(1);
assertEq(no.totalVettedValidators, 3);
}

function test_unvetKeys_RevertIfNodeOperatorDoesntExist() public {
createNodeOperator(); // Make sure there is at least one node operator.
vm.expectRevert(NodeOperatorDoesNotExist.selector);
csm.decreaseOperatorVettedKeys(UintArr(1), UintArr(0));
}
}

contract CsmViewKeys is CSMCommon {
Expand Down
12 changes: 10 additions & 2 deletions test/helpers/Utilities.sol
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,22 @@ contract Utilities is CommonBase {
return new uint256[](0);
}

/// @dev It's super annoying to make a memory array all the time without an array literal, so the function pretends
/// to provide the familiar syntax. By overloading the function, we can have a different number of arguments.
function UintArr(uint256 e0) public pure returns (uint256[] memory) {
uint256[] memory arr = new uint256[](1);
arr[0] = e0;
return arr;
}

function UintArr(
uint256 e0,
uint256 e1
) public pure returns (uint256[] memory) {
uint256[] memory arr = new uint256[](2);
arr[0] = e0;
arr[1] = e1;
return arr;
}

/// See https://github.com/Vectorized/solady - MIT licensed.
/// @dev Fills the memory with junk, for more robust testing of inline assembly
/// which reads/write to the memory.
Expand Down

0 comments on commit 3bc7499

Please sign in to comment.