-
Notifications
You must be signed in to change notification settings - Fork 264
[EPIC] Lido V3 Release #1584
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
[EPIC] Lido V3 Release #1584
Conversation
tamtamchik
commented
Dec 2, 2025
- [EPIC] stVaults #874
[VAULTS] Audit fixes 7
fix: burning external shares with paused staking
…te related functions
feat: pause VaultHub implementation
[VAULTS] Fix/no-fee-revamp-2
[VAULTS] Final fix for the wrong shortfall problem
[VAULTS] Audit fixes 8
test: add a test for static array zeroing
feat: sync master with develop
| function _getTotalAndExternalShares() internal view returns (uint256, uint256) { | ||
| return TOTAL_AND_EXTERNAL_SHARES_POSITION.getLowAndHighUint128(); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| function _getBufferedEtherAndDepositedValidators() internal view returns (uint256, uint256) { | ||
| return BUFFERED_ETHER_AND_DEPOSITED_VALIDATORS_POSITION.getLowAndHighUint128(); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| function _getClBalanceAndClValidators() internal view returns (uint256, uint256) { | ||
| return CL_BALANCE_AND_CL_VALIDATORS_POSITION.getLowAndHighUint128(); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| 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
- totalFee = (_pubkeys.length / PUBLIC_KEY_LENGTH) * feePerRequest
| 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
- totalFee = (_pubkeys.length / PUBLIC_KEY_LENGTH) * feePerRequest
| 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
contracts/openzeppelin/5.2/upgradeable/access/extensions/AccessControlEnumerableUpgradeable.sol
Dismissed
Show dismissed
Hide dismissed
| 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
Hardhat Unit Tests Coverage SummaryDiff against masterResults for commit: 77c3ed4 Minimum allowed coverage is ♻️ This comment has been updated with latest results |
fix: update hardcoded IVaultsAdapter
test: add a node operator happy path
feat: redeploy V3VoteScript with correct VaultsAdapter interface
feat: add pause to pdg
PDG test improvements
Make Hoodi green again
test: test recover tokens
…dg-pause feat: redeploy V3VoteScript with PDG pause on start