Skip to content

Conversation

@tamtamchik
Copy link
Member

folkyatina and others added 30 commits October 29, 2025 10:51
fix: burning external shares with paused staking
[VAULTS] Final fix for the wrong shortfall problem
Comment on lines +1251 to +1253
function _getTotalAndExternalShares() internal view returns (uint256, uint256) {
return TOTAL_AND_EXTERNAL_SHARES_POSITION.getLowAndHighUint128();
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +1271 to +1273
function _getBufferedEtherAndDepositedValidators() internal view returns (uint256, uint256) {
return BUFFERED_ETHER_AND_DEPOSITED_VALIDATORS_POSITION.getLowAndHighUint128();
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +1285 to +1287
function _getClBalanceAndClValidators() internal view returns (uint256, uint256) {
return CL_BALANCE_AND_CL_VALIDATORS_POSITION.getLowAndHighUint128();
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines +382 to +410
function triggerValidatorWithdrawals(
bytes calldata _pubkeys,
uint64[] calldata _amountsInGwei,
address _excessRefundRecipient
) external payable onlyOwner {
if (msg.value == 0) revert ZeroArgument("msg.value");
if (_pubkeys.length == 0) revert ZeroArgument("_pubkeys");
if (_pubkeys.length % PUBLIC_KEY_LENGTH != 0) revert InvalidPubkeysLength();
if (_excessRefundRecipient == address(0)) revert ZeroArgument("_excessRefundRecipient");

uint256 feePerRequest = TriggerableWithdrawals.getWithdrawalRequestFee();
uint256 totalFee = (_pubkeys.length / PUBLIC_KEY_LENGTH) * feePerRequest;
if (msg.value < totalFee) revert InsufficientValidatorWithdrawalFee(msg.value, totalFee);

// If amounts array is empty, trigger full withdrawals, otherwise use amount-driven withdrawal types
if (_amountsInGwei.length == 0) {
TriggerableWithdrawals.addFullWithdrawalRequests(_pubkeys, feePerRequest);
} else {
TriggerableWithdrawals.addWithdrawalRequests(_pubkeys, _amountsInGwei, feePerRequest);
}

uint256 excess = msg.value - totalFee;
if (excess > 0) {
(bool success, ) = _excessRefundRecipient.call{value: excess}("");
if (!success) revert TransferFailed(_excessRefundRecipient, excess);
}

emit ValidatorWithdrawalsTriggered(_pubkeys, _amountsInGwei, excess, _excessRefundRecipient);
}

Check warning

Code scanning / Slither

Divide before multiply Medium

Comment on lines +421 to +443
function ejectValidators(bytes calldata _pubkeys, address _refundRecipient) external payable {
if (msg.value == 0) revert ZeroArgument("msg.value");
if (_pubkeys.length == 0) revert ZeroArgument("_pubkeys");
if (_pubkeys.length % PUBLIC_KEY_LENGTH != 0) revert InvalidPubkeysLength();
if (msg.sender != _storage().nodeOperator) revert SenderNotNodeOperator();

// If the refund recipient is not set, use the sender as the refund recipient
if (_refundRecipient == address(0)) _refundRecipient = msg.sender;

uint256 feePerRequest = TriggerableWithdrawals.getWithdrawalRequestFee();
uint256 totalFee = (_pubkeys.length / PUBLIC_KEY_LENGTH) * feePerRequest;
if (msg.value < totalFee) revert InsufficientValidatorWithdrawalFee(msg.value, totalFee);

TriggerableWithdrawals.addFullWithdrawalRequests(_pubkeys, feePerRequest);

uint256 excess = msg.value - totalFee;
if (excess > 0) {
(bool success, ) = _refundRecipient.call{value: excess}("");
if (!success) revert TransferFailed(_refundRecipient, excess);
}

emit ValidatorEjectionsTriggered(_pubkeys, excess, _refundRecipient);
}

Check warning

Code scanning / Slither

Divide before multiply Medium

Comment on lines +691 to +698
function _burnWstETH(uint256 _amountOfWstETH) internal {
SafeERC20.safeTransferFrom(WSTETH, msg.sender, address(this), _amountOfWstETH);
uint256 unwrappedStETH = WSTETH.unwrap(_amountOfWstETH);
uint256 unwrappedShares = _getSharesByPooledEth(unwrappedStETH);

STETH.transferShares(address(VAULT_HUB), unwrappedShares);
_burnShares(unwrappedShares);
}

Check warning

Code scanning / Slither

Unused return Medium

) internal {
_sanityChecks(_contracts, _report, _pre, _update);

uint256 lastWithdrawalRequestToFinalize;

Check warning

Code scanning / Slither

Uninitialized local variables Medium

if (_token == address(LIDO)) revert StETHRecoveryWrongFunc();

emit ERC721Recovered(msg.sender, _token, _tokenId);
IERC721(_token).transferFrom(address(this), LOCATOR.treasury(), _tokenId);

Check warning

Code scanning / Slither

Token Approve Warning Medium

Burner recoverERC721 parameter from is not related to msg.sender IERC721(_token).transferFrom(address(this),LOCATOR.treasury(),_tokenId)
Comment on lines +97 to +104
function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {
AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
bool revoked = super._revokeRole(role, account);
if (revoked) {
$._roleMembers[role].remove(account);
}
return revoked;
}

Check warning

Code scanning / Slither

Unused return Medium

@github-actions
Copy link

github-actions bot commented Dec 7, 2025

badge

Hardhat Unit Tests Coverage Summary

Filename                                                                Stmts    Miss  Cover    Missing
--------------------------------------------------------------------  -------  ------  -------  -----------------------------------------------------------------------------------------------------------
contracts/0.4.24/Lido.sol                                                 281      11  96.09%   825-844, 940-952
contracts/0.4.24/StETH.sol                                                 80       0  100.00%
contracts/0.4.24/StETHPermit.sol                                           15       0  100.00%
contracts/0.4.24/lib/Packed64x4.sol                                         5       0  100.00%
contracts/0.4.24/lib/SigningKeys.sol                                       36       0  100.00%
contracts/0.4.24/lib/StakeLimitUtils.sol                                   41       0  100.00%
contracts/0.4.24/nos/NodeOperatorsRegistry.sol                            435       0  100.00%
contracts/0.4.24/utils/Pausable.sol                                         9       0  100.00%
contracts/0.4.24/utils/UnstructuredStorageExt.sol                          14       0  100.00%
contracts/0.4.24/utils/Versioned.sol                                        5       0  100.00%
contracts/0.6.12/WstETH.sol                                                17       0  100.00%
contracts/0.8.25/ValidatorExitDelayVerifier.sol                            75       0  100.00%
contracts/0.8.25/utils/AccessControlConfirmable.sol                         2       0  100.00%
contracts/0.8.25/utils/Confirmable2Addresses.sol                            5       0  100.00%
contracts/0.8.25/utils/Confirmations.sol                                   37       0  100.00%
contracts/0.8.25/utils/PausableUntilWithRoles.sol                           3       0  100.00%
contracts/0.8.25/vaults/LazyOracle.sol                                    134      18  86.57%   203-209, 248, 276-279, 436, 449, 467, 515, 556-558, 650, 658
contracts/0.8.25/vaults/OperatorGrid.sol                                  196       1  99.49%   203
contracts/0.8.25/vaults/PinnedBeaconProxy.sol                               6       0  100.00%
contracts/0.8.25/vaults/StakingVault.sol                                  111      14  87.39%   307-341
contracts/0.8.25/vaults/ValidatorConsolidationRequests.sol                 48       3  93.75%   183, 187, 199
contracts/0.8.25/vaults/VaultFactory.sol                                   34       0  100.00%
contracts/0.8.25/vaults/VaultHub.sol                                      425      76  82.12%   257-266, 281-287, 342-366, 383, 552-553, 595-688, 997-999, 1087-1091, 1147, 1202-1209, 1495-1496, 1511-1521
contracts/0.8.25/vaults/dashboard/Dashboard.sol                           137       8  94.16%   183-201, 327, 636-649
contracts/0.8.25/vaults/dashboard/NodeOperatorFee.sol                      70       0  100.00%
contracts/0.8.25/vaults/dashboard/Permissions.sol                          47       2  95.74%   321-330
contracts/0.8.25/vaults/interfaces/IPinnedBeaconProxy.sol                   0       0  100.00%
contracts/0.8.25/vaults/interfaces/IPredepositGuarantee.sol                 0       0  100.00%
contracts/0.8.25/vaults/interfaces/IStakingVault.sol                        0       0  100.00%
contracts/0.8.25/vaults/interfaces/IVaultFactory.sol                        0       0  100.00%
contracts/0.8.25/vaults/lib/PinnedBeaconUtils.sol                           5       0  100.00%
contracts/0.8.25/vaults/lib/RecoverTokens.sol                               5       0  100.00%
contracts/0.8.25/vaults/lib/RefSlotCache.sol                               36       0  100.00%
contracts/0.8.25/vaults/predeposit_guarantee/CLProofVerifier.sol           16       1  93.75%   214
contracts/0.8.25/vaults/predeposit_guarantee/MeIfNobodyElse.sol             3       0  100.00%
contracts/0.8.25/vaults/predeposit_guarantee/PredepositGuarantee.sol      213      12  94.37%   482-502, 531, 670, 677, 699
contracts/0.8.9/Accounting.sol                                             96       2  97.92%   349-350
contracts/0.8.9/BeaconChainDepositor.sol                                   21       2  90.48%   48, 51
contracts/0.8.9/Burner.sol                                                 92       0  100.00%
contracts/0.8.9/DepositSecurityModule.sol                                 128       0  100.00%
contracts/0.8.9/EIP712StETH.sol                                            16       0  100.00%
contracts/0.8.9/LidoExecutionLayerRewardsVault.sol                         16       0  100.00%
contracts/0.8.9/LidoLocator.sol                                            26       0  100.00%
contracts/0.8.9/OracleDaemonConfig.sol                                     28       0  100.00%
contracts/0.8.9/StakingRouter.sol                                         305       0  100.00%
contracts/0.8.9/TokenRateNotifier.sol                                      36      36  0.00%    35-130
contracts/0.8.9/TriggerableWithdrawalsGateway.sol                          54       1  98.15%   271
contracts/0.8.9/WithdrawalQueue.sol                                        88       0  100.00%
contracts/0.8.9/WithdrawalQueueBase.sol                                   146       0  100.00%
contracts/0.8.9/WithdrawalQueueERC721.sol                                  89       0  100.00%
contracts/0.8.9/WithdrawalVault.sol                                        32       0  100.00%
contracts/0.8.9/WithdrawalVaultEIP7002.sol                                 21       0  100.00%
contracts/0.8.9/lib/ExitLimitUtils.sol                                     35       0  100.00%
contracts/0.8.9/lib/Math.sol                                                4       0  100.00%
contracts/0.8.9/lib/PositiveTokenRebaseLimiter.sol                         22       0  100.00%
contracts/0.8.9/lib/UnstructuredRefStorage.sol                              2       0  100.00%
contracts/0.8.9/oracle/AccountingOracle.sol                               174       0  100.00%
contracts/0.8.9/oracle/BaseOracle.sol                                      89       1  98.88%   401
contracts/0.8.9/oracle/HashConsensus.sol                                  263       1  99.62%   1005
contracts/0.8.9/oracle/ValidatorsExitBus.sol                              138      10  92.75%   458-471, 541
contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol                         52       1  98.08%   217
contracts/0.8.9/proxy/OssifiableProxy.sol                                  17       0  100.00%
contracts/0.8.9/proxy/WithdrawalsManagerProxy.sol                          60       0  100.00%
contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol               232      12  94.83%   307-309, 600-605, 800-835, 956
contracts/0.8.9/utils/DummyEmptyContract.sol                                0       0  100.00%
contracts/0.8.9/utils/PausableUntil.sol                                    31       0  100.00%
contracts/0.8.9/utils/Versioned.sol                                        11       0  100.00%
contracts/0.8.9/utils/access/AccessControl.sol                             23       0  100.00%
contracts/0.8.9/utils/access/AccessControlEnumerable.sol                    9       0  100.00%
contracts/common/utils/PausableUntil.sol                                   29       0  100.00%
TOTAL                                                                    4931     212  95.70%

Diff against master

Filename                                                                Stmts    Miss  Cover
--------------------------------------------------------------------  -------  ------  --------
contracts/0.4.24/Lido.sol                                                 +69     +11  -3.91%
contracts/0.4.24/StETH.sol                                                 +8       0  +100.00%
contracts/0.4.24/lib/StakeLimitUtils.sol                                   +4       0  +100.00%
contracts/0.4.24/utils/UnstructuredStorageExt.sol                         +14       0  +100.00%
contracts/0.8.25/utils/AccessControlConfirmable.sol                        +2       0  +100.00%
contracts/0.8.25/utils/Confirmable2Addresses.sol                           +5       0  +100.00%
contracts/0.8.25/utils/Confirmations.sol                                  +37       0  +100.00%
contracts/0.8.25/utils/PausableUntilWithRoles.sol                          +3       0  +100.00%
contracts/0.8.25/vaults/LazyOracle.sol                                   +134     +18  +86.57%
contracts/0.8.25/vaults/OperatorGrid.sol                                 +196      +1  +99.49%
contracts/0.8.25/vaults/PinnedBeaconProxy.sol                              +6       0  +100.00%
contracts/0.8.25/vaults/StakingVault.sol                                 +111     +14  +87.39%
contracts/0.8.25/vaults/ValidatorConsolidationRequests.sol                +48      +3  +93.75%
contracts/0.8.25/vaults/VaultFactory.sol                                  +34       0  +100.00%
contracts/0.8.25/vaults/VaultHub.sol                                     +425     +76  +82.12%
contracts/0.8.25/vaults/dashboard/Dashboard.sol                          +137      +8  +94.16%
contracts/0.8.25/vaults/dashboard/NodeOperatorFee.sol                     +70       0  +100.00%
contracts/0.8.25/vaults/dashboard/Permissions.sol                         +47      +2  +95.74%
contracts/0.8.25/vaults/interfaces/IPinnedBeaconProxy.sol                   0       0  +100.00%
contracts/0.8.25/vaults/interfaces/IPredepositGuarantee.sol                 0       0  +100.00%
contracts/0.8.25/vaults/interfaces/IStakingVault.sol                        0       0  +100.00%
contracts/0.8.25/vaults/interfaces/IVaultFactory.sol                        0       0  +100.00%
contracts/0.8.25/vaults/lib/PinnedBeaconUtils.sol                          +5       0  +100.00%
contracts/0.8.25/vaults/lib/RecoverTokens.sol                              +5       0  +100.00%
contracts/0.8.25/vaults/lib/RefSlotCache.sol                              +36       0  +100.00%
contracts/0.8.25/vaults/predeposit_guarantee/CLProofVerifier.sol          +16      +1  +93.75%
contracts/0.8.25/vaults/predeposit_guarantee/MeIfNobodyElse.sol            +3       0  +100.00%
contracts/0.8.25/vaults/predeposit_guarantee/PredepositGuarantee.sol     +213     +12  +94.37%
contracts/0.8.9/Accounting.sol                                            +96      +2  +97.92%
contracts/0.8.9/Burner.sol                                                +21       0  +100.00%
contracts/0.8.9/LidoLocator.sol                                            +6       0  +100.00%
contracts/0.8.9/TokenRateNotifier.sol                                     +36     +36  +100.00%
contracts/0.8.9/oracle/AccountingOracle.sol                               -19       0  +100.00%
contracts/0.8.9/oracle/ValidatorsExitBus.sol                                0      +9  -6.53%
contracts/0.8.9/proxy/WithdrawalsManagerProxy.sol                         +60       0  +100.00%
contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol                 0     +12  -5.17%
contracts/common/utils/PausableUntil.sol                                  +29       0  +100.00%
TOTAL                                                                   +1857    +205  -1.62%

Results for commit: 77c3ed4

Minimum allowed coverage is 95%

♻️ This comment has been updated with latest results

@folkyatina folkyatina added the vaults Lido stVaults related changes label Dec 8, 2025
folkyatina and others added 24 commits December 8, 2025 13:27
feat: redeploy V3VoteScript with correct VaultsAdapter interface
…dg-pause

feat: redeploy V3VoteScript with PDG pause on start
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

vaults Lido stVaults related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants