Skip to content

Commit

Permalink
fix: move updates from SR to NOR
Browse files Browse the repository at this point in the history
  • Loading branch information
krogla committed Feb 16, 2023
1 parent 0050dea commit 1351b16
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 92 deletions.
67 changes: 57 additions & 10 deletions contracts/0.4.24/nos/NodeOperatorsRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -420,27 +420,70 @@ contract NodeOperatorsRegistry is AragonApp, Versioned {
/// @notice Called by StakingRouter to update the number of the validators of the given node
/// operator that were requested to exit but failed to do so in the max allowed time
///
/// @param _nodeOperatorId Id of the node operator
/// @param _stuckValidatorsCount New number of stuck validators of the node operator
function updateStuckValidatorsCount(uint256 _nodeOperatorId, uint256 _stuckValidatorsCount) external {
_onlyExistedNodeOperator(_nodeOperatorId);
/// @param _nodeOperatorIds bytes packed array of the node operators id
/// @param _stuckValidatorsCounts bytes packed array of the new number of stuck validators for the node operators
function updateStuckValidatorsCount(
bytes _nodeOperatorIds,
bytes _stuckValidatorsCounts
)
external
{
_auth(STAKING_ROUTER_ROLE);
_requireValidReportData(_nodeOperatorIds.length % 8 == 0 && _stuckValidatorsCounts.length % 16 == 0);

_updateStuckValidatorsCount(_nodeOperatorId, uint64(_stuckValidatorsCount));
uint256 nodeOperatorsCount = _nodeOperatorIds.length / 8;
_requireValidReportData(_stuckValidatorsCounts.length / 16 == nodeOperatorsCount);
uint256 totalNodeOperatorsCount = getNodeOperatorsCount();

uint256 nodeOperatorId;
uint64 validatorsCount;
for (uint256 i; i < nodeOperatorsCount; ) {
/// @solidity memory-safe-assembly
assembly {
let _nodeOperatorIdsOffset := add(calldataload(4), 36) // arg1 calldata offset + 4 (signature len) + 32 (length slot)
let _stuckValidatorsCountsOffset := add(calldataload(36), 36) // arg2 calldata offset + 4 (signature len) + 32 (length slot)
nodeOperatorId := shr(192, calldataload(add(_nodeOperatorIdsOffset, mul(i, 8))))
validatorsCount := shr(128, calldataload(add(_stuckValidatorsCountsOffset, mul(i, 16))))
i := add(i, 1)
}
_requireValidRange(nodeOperatorId < totalNodeOperatorsCount);
_updateStuckValidatorsCount(nodeOperatorId, validatorsCount);
}
}

/// @notice Called by StakingRouter to update the number of the validators in the EXITED state
/// for node operator with given id
///
/// @param _nodeOperatorId Id of the node operator
/// @param _exitedValidatorsCount New number of EXITED validators of the node operator
function updateExitedValidatorsCount(uint256 _nodeOperatorId, uint256 _exitedValidatorsCount)
/// @param _nodeOperatorIds bytes packed array of the node operators id
/// @param _stuckValidatorsCounts bytes packed array of the new number of EXITED validators for the node operators
function updateExitedValidatorsCount(
bytes _nodeOperatorIds,
bytes _stuckValidatorsCounts
)
external
{
_onlyExistedNodeOperator(_nodeOperatorId);
_auth(STAKING_ROUTER_ROLE);
_requireValidReportData(_nodeOperatorIds.length % 8 == 0 && _stuckValidatorsCounts.length % 16 == 0);

uint256 nodeOperatorsCount = _nodeOperatorIds.length / 8;
_requireValidReportData(_stuckValidatorsCounts.length / 16 == nodeOperatorsCount);
uint256 totalNodeOperatorsCount = getNodeOperatorsCount();

_updateExitedValidatorsCount(_nodeOperatorId, uint64(_exitedValidatorsCount), false);
uint256 nodeOperatorId;
uint64 validatorsCount;

for (uint256 i; i < nodeOperatorsCount; ) {
/// @solidity memory-safe-assembly
assembly {
let _nodeOperatorIdsOffset := add(calldataload(4), 36) // arg1 calldata offset + 4 (signature len) + 32 (length slot)
let _stuckValidatorsCountsOffset := add(calldataload(36), 36) // arg2 calldata offset + 4 (signature len) + 32 (length slot)
nodeOperatorId := shr(192, calldataload(add(_nodeOperatorIdsOffset, mul(i, 8))))
validatorsCount := shr(128, calldataload(add(_stuckValidatorsCountsOffset, mul(i, 16))))
i := add(i, 1)
}
_requireValidRange(nodeOperatorId < totalNodeOperatorsCount);
_updateExitedValidatorsCount(nodeOperatorId, validatorsCount, false);
}
}

/// @notice Updates the number of the refunded validators for node operator with the given id
Expand Down Expand Up @@ -1272,6 +1315,10 @@ contract NodeOperatorsRegistry is AragonApp, Versioned {
require(_pass, "OUT_OF_RANGE");
}

function _requireValidReportData(bool _pass) internal pure {
require(_pass, "INVALID_REPORT_DATA");
}

function _onlyCorrectNodeOperatorState(bool _pass) internal pure {
require(_pass, "WRONG_OPERATOR_ACTIVE_STATE");
}
Expand Down
43 changes: 2 additions & 41 deletions contracts/0.8.9/StakingRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -303,15 +303,6 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version
external
onlyRole(REPORT_EXITED_VALIDATORS_ROLE)
{
if (_nodeOperatorIds.length % 8 != 0 || _exitedValidatorsCounts.length % 16 != 0) {
revert InvalidReportData();
}

uint256 totalNodeOps = _nodeOperatorIds.length / 8;
if (_exitedValidatorsCounts.length / 16 != totalNodeOps) {
revert InvalidReportData();
}

StakingModule storage stakingModule = _getStakingModuleById(_stakingModuleId);
IStakingModule moduleContract = IStakingModule(stakingModule.stakingModuleAddress);
(
Expand All @@ -320,17 +311,7 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version
/* uint256 depositableValidatorsCount */
) = moduleContract.getStakingModuleSummary();

for (uint256 i = 0; i < totalNodeOps; ) {
uint256 nodeOpId;
uint256 validatorsCount;
/// @solidity memory-safe-assembly
assembly {
nodeOpId := shr(192, calldataload(add(_nodeOperatorIds.offset, mul(i, 8))))
validatorsCount := shr(128, calldataload(add(_exitedValidatorsCounts.offset, mul(i, 16))))
i := add(i, 1)
}
moduleContract.updateExitedValidatorsCount(nodeOpId, validatorsCount);
}
moduleContract.updateExitedValidatorsCount(_nodeOperatorIds, _exitedValidatorsCounts);

uint256 prevReportedExitedValidatorsCount = stakingModule.exitedValidatorsCount;
(
Expand Down Expand Up @@ -444,28 +425,8 @@ contract StakingRouter is AccessControlEnumerable, BeaconChainDepositor, Version
external
onlyRole(REPORT_EXITED_VALIDATORS_ROLE)
{
if (_nodeOperatorIds.length % 8 != 0 || _stuckValidatorsCounts.length % 16 != 0) {
revert InvalidReportData();
}

uint256 totalNodeOps = _nodeOperatorIds.length / 8;
if (_stuckValidatorsCounts.length / 16 != totalNodeOps) {
revert InvalidReportData();
}

address moduleAddr = _getStakingModuleById(_stakingModuleId).stakingModuleAddress;

for (uint256 i = 0; i < totalNodeOps; ) {
uint256 nodeOpId;
uint256 validatorsCount;
/// @solidity memory-safe-assembly
assembly {
nodeOpId := shr(192, calldataload(add(_nodeOperatorIds.offset, mul(i, 8))))
validatorsCount := shr(128, calldataload(add(_stuckValidatorsCounts.offset, mul(i, 16))))
i := add(i, 1)
}
IStakingModule(moduleAddr).updateStuckValidatorsCount(nodeOpId, validatorsCount);
}
IStakingModule(moduleAddr).updateStuckValidatorsCount(_nodeOperatorIds, _stuckValidatorsCounts);
}

function getExitedValidatorsCountAcrossAllModules() external view returns (uint256) {
Expand Down
16 changes: 8 additions & 8 deletions contracts/0.8.9/interfaces/IStakingModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,19 +83,19 @@ interface IStakingModule {

/// @notice Updates the number of the validators of the given node operator that were requested
/// to exit but failed to do so in the max allowed time
/// @param _nodeOperatorId Id of the node operator
/// @param _stuckValidatorsCount New number of stuck validators of the node operator
/// @param _nodeOperatorIds bytes packed array of the node operators id
/// @param _stuckValidatorsCounts bytes packed array of the new number of STUCK validators for the node operators
function updateStuckValidatorsCount(
uint256 _nodeOperatorId,
uint256 _stuckValidatorsCount
bytes calldata _nodeOperatorIds,
bytes calldata _stuckValidatorsCounts
) external;

/// @notice Updates the number of the validators in the EXITED state for node operator with given id
/// @param _nodeOperatorId Id of the node operator
/// @param _exitedValidatorsCount New number of EXITED validators of the node operator
/// @param _nodeOperatorIds bytes packed array of the node operators id
/// @param _stuckValidatorsCounts bytes packed array of the new number of EXITED validators for the node operators
function updateExitedValidatorsCount(
uint256 _nodeOperatorId,
uint256 _exitedValidatorsCount
bytes calldata _nodeOperatorIds,
bytes calldata _stuckValidatorsCounts
) external;

/// @notice Updates the number of the refunded validators for node operator with the given id
Expand Down
9 changes: 6 additions & 3 deletions contracts/0.8.9/test_helpers/ModuleSolo.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,14 @@ contract ModuleSolo is IStakingModule {
function handleRewardsMinted(uint256 _totalShares) external {}

function updateStuckValidatorsCount(
uint256 _nodeOperatorId,
uint256 _stuckValidatorKeysCount
bytes calldata _nodeOperatorIds,
bytes calldata _stuckValidatorsCounts
) external {}

function updateExitedValidatorsCount(uint256, uint256) external {}
function updateExitedValidatorsCount(
bytes calldata _nodeOperatorIds,
bytes calldata _stuckValidatorsCounts
) external {}

function updateRefundedValidatorsCount(uint256 _nodeOperatorId, uint256 _refundedValidatorsCount) external {}

Expand Down
9 changes: 6 additions & 3 deletions contracts/0.8.9/test_helpers/StakingModuleMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,14 @@ contract StakingModuleMock is IStakingModule {
function handleRewardsMinted(uint256 _totalShares) external {}

function updateStuckValidatorsCount(
uint256 _nodeOperatorId,
uint256 _stuckValidatorKeysCount
bytes calldata _nodeOperatorIds,
bytes calldata _stuckValidatorsCounts
) external {}

function updateExitedValidatorsCount(uint256, uint256) external {}
function updateExitedValidatorsCount(
bytes calldata _nodeOperatorIds,
bytes calldata _stuckValidatorsCounts
) external {}

function updateRefundedValidatorsCount(uint256 _nodeOperatorId, uint256 _refundedValidatorsCount) external {}

Expand Down
2 changes: 1 addition & 1 deletion lib/abi/NodeOperatorsRegistry.json

Large diffs are not rendered by default.

Loading

0 comments on commit 1351b16

Please sign in to comment.