Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
112 commits
Select commit Hold shift + click to select a range
1a372a1
feat: draft maxeb deposits
Amuhar Aug 23, 2025
a7cebc1
fix: typecheck in tests
Amuhar Aug 24, 2025
c38ae90
fix: tests
Amuhar Aug 26, 2025
f7362eb
fix: disable solhint for lib sol version range
Amuhar Aug 26, 2025
4da61f1
feat: add consolidation requests support to withdrawal vault
mkurayan Aug 27, 2025
de6c47b
feat: fix withdrawal vault tests
mkurayan Aug 28, 2025
d56ff5d
feat: add consolidation request tests
mkurayan Aug 28, 2025
b7e22c0
fix: migration state & temp disable allocation tests
Amuhar Sep 2, 2025
614dbbb
fix: removed unnecessary file
Amuhar Sep 2, 2025
4024767
fix: moved staking router to 0.8.25 folder
Amuhar Sep 2, 2025
c5ad4ff
fix: test on deposit 0x02 type & temp storage read
Amuhar Sep 3, 2025
4618b77
fix: test getStakingModuleMaxInitialDepositsAmount
Amuhar Sep 4, 2025
b90f789
fix: test file path
krogla Sep 3, 2025
a3447f0
fix: foundry mappings
krogla Sep 3, 2025
42914d4
feat: new allocation strategy lib
krogla Sep 3, 2025
c69583e
fix: setWithdrawalCredentials02 in tests
Amuhar Sep 5, 2025
71fad3c
fix: withdrawal creds check
Amuhar Sep 5, 2025
f6195aa
fix: deposit tracker without cleaning
Amuhar Sep 8, 2025
983fd60
fix: deposit tracker getDepositedEth tests
Amuhar Sep 8, 2025
a9a8a38
fix: separate moveCursorToSlot and getDepositedEthUpToSlot in deposit…
Amuhar Sep 9, 2025
0a9faed
fix: comments
Amuhar Sep 9, 2025
275cd51
feat: add request limit utils
mkurayan Sep 9, 2025
40542fa
feat: add consolidation gateway
mkurayan Sep 9, 2025
01f64f6
feat: add consolidation gateway to scratch deploy
mkurayan Sep 9, 2025
b0194c2
feat: move rate limit lib to common
mkurayan Sep 9, 2025
545ab58
feat: add unit test for rate limit librray
mkurayan Sep 9, 2025
506dabb
Merge commit 'de33222eb3fccdd15239a28093cb8ac4a682353e' into feat/sta…
mkurayan Sep 9, 2025
d59d203
fix: contracts deploy
Amuhar Sep 9, 2025
d687b0c
Merge remote-tracking branch 'origin/feat/staking-router-3.0' into fe…
Amuhar Sep 9, 2025
623ba88
fix: compile
Amuhar Sep 9, 2025
83f4aba
fix: IPausableUntil -> IPausableUntilWithRoles in V3TemporaryAdmin
Amuhar Sep 9, 2025
cf9617c
fix: disable check of few contracts in check-interface
Amuhar Sep 10, 2025
31e03bd
fix: stas lib refactor
krogla Sep 10, 2025
072f964
fix: formatting & scratch deploy
Amuhar Sep 10, 2025
1493e1f
fix: tests
Amuhar Sep 10, 2025
6e04d9e
fix: ts linter
Amuhar Sep 10, 2025
bc463d7
Merge pull request #1412 from lidofinance/feat/maxeb-deposits
Amuhar Sep 11, 2025
6eb0870
fix: stas lib refactor
krogla Sep 12, 2025
26d7c86
fix: sr refactor into ext lib+STAS integration
krogla Sep 13, 2025
06ff2bb
test: new SR deploy, fixed mocks, partial fixed tests
krogla Sep 13, 2025
acf0ed1
chore: move file to complete merge
krogla Sep 13, 2025
1ef2c2a
Merge branch 'feat/staking-router-3.0' into feat/maxed-allocation-lib
krogla Sep 13, 2025
a4c5ada
feat: initial srv3 accounting implementation
eddort Sep 15, 2025
e295bcf
feat: initial srv3 accounting tests
eddort Sep 15, 2025
8b6f3df
feat: srv3 accounting submitReport tests
eddort Sep 15, 2025
19fef4b
fix: get allocation/rewards refactor, minor fixes
krogla Sep 16, 2025
f4a7b40
test: sr test fixes
krogla Sep 16, 2025
dd5551d
test: fix scratch deploy
krogla Sep 16, 2025
e284bb5
fix: lint/compile problems and fix unit tests
eddort Sep 16, 2025
6c87ed4
fix: format
eddort Sep 16, 2025
686d51b
fix: test/0.4.24/lido/lido.finalizeUpgrade_v3.test.ts format
eddort Sep 16, 2025
fd29ca6
test: fix sr tests
krogla Sep 16, 2025
451e733
Merge branch 'feat/staking-router-3.0' of github.com:lidofinance/core…
eddort Sep 16, 2025
16e0fce
Merge pull request #1445 from lidofinance/feat/srv3-accounting
eddort Sep 16, 2025
01dcbfd
Merge branch 'feat/staking-router-3.0' into feat/maxed-allocation-lib
krogla Sep 16, 2025
6b4272a
Merge branch 'feat/staking-router-3.0' into feat/maxed-allocation-lib
krogla Sep 16, 2025
623964d
test: fix contract location
krogla Sep 16, 2025
64ca314
test: fix scratch deploy
krogla Sep 16, 2025
8f03876
feat: consolidation gateway unit tests
mkurayan Sep 16, 2025
3fd5a40
fix: allocation to non-active modules
krogla Sep 16, 2025
bdb5342
fix: revert depositedValidators counter, partial test fixes
krogla Sep 16, 2025
8fa24d6
style: fix formatting
krogla Sep 16, 2025
f6ff81e
Update test/0.8.25/stakingRouter/stakingRouter.module-sync.test.ts
krogla Sep 17, 2025
17aabe8
Update test/0.8.25/stakingRouter/stakingRouter.misc.test.ts
krogla Sep 17, 2025
ff4dab8
Update test/0.8.25/stakingRouter/stakingRouter.module-sync.test.ts
krogla Sep 17, 2025
c04a969
Update test/0.8.25/stakingRouter/stakingRouter.misc.test.ts
krogla Sep 17, 2025
8ca11ce
Update contracts/0.8.25/sr/StakingRouter.sol
krogla Sep 17, 2025
a3f4dd9
Merge pull request #1447 from lidofinance/feat/maxed-allocation-lib
krogla Sep 17, 2025
a4bb52b
feat: refactoring consolidation gateway unit tests
mkurayan Sep 17, 2025
73c897e
feat: remove Consolidation Gateway harness
mkurayan Sep 17, 2025
4a0b0ac
feat: temporary grant consolidation role to deployer
mkurayan Sep 17, 2025
1cb4db5
Merge pull request #1450 from lidofinance/feat/staking-router-3.0-con…
mkurayan Sep 17, 2025
5fa5544
fix: deposit tracker changes
Amuhar Sep 17, 2025
8650a35
Merge remote-tracking branch 'origin/feat/staking-router-3.0' into fi…
Amuhar Sep 17, 2025
45f8107
fix: use tracker in accounting
Amuhar Sep 17, 2025
c7cc5ec
fix: format
Amuhar Sep 17, 2025
11a2d08
fix: accounting e2e tests
eddort Sep 17, 2025
71d8bb4
fix: move cursor on ao report
Amuhar Sep 18, 2025
2fbb2ff
feat: new accounting deposits tracker integration
eddort Sep 18, 2025
783acd3
fix: accounting unit tests
eddort Sep 18, 2025
268e514
fix: sr unit tests
eddort Sep 18, 2025
3564d9e
fix: scratch deploy
eddort Sep 18, 2025
5b2b297
test: fix sr unit tests
krogla Sep 18, 2025
608c55c
fix: deposit tracker storage to SRStorage & deploy as embedded lib
Amuhar Sep 18, 2025
21e91ed
Merge remote-tracking branch 'origin/fix-tracker' into fix-tracker
Amuhar Sep 18, 2025
299140d
fix: tracker update
krogla Sep 18, 2025
93c76d8
fix: accounting scratch deploy
Amuhar Sep 18, 2025
4148c91
Merge remote-tracking branch 'origin/feat/staking-router-3.0' into fi…
Amuhar Sep 19, 2025
5b4d71d
fix: add module balances to AO report
krogla Sep 19, 2025
16f0e49
test: fix unit oracle test
krogla Sep 19, 2025
4b0c029
fix: set withdrawalCredentials02 in migration_v4
Amuhar Sep 19, 2025
c9fcd89
fix: add nodules pending balances to AO report
krogla Sep 23, 2025
330a5de
test: update helpers and unit tests
krogla Sep 23, 2025
0219a4a
fix: allocation logic in SR
krogla Sep 24, 2025
2caadd6
fix: remove dedicated wc02 methods, minor refactor and cleanup
krogla Sep 24, 2025
0febe40
refactor: deposits count refactor, cleanup
krogla Sep 25, 2025
371497e
fix: on accounting - put deposited eth into update object
krogla Sep 25, 2025
40767a3
test: silence negative rebase tests due to MEB and outdated SanityChe…
krogla Sep 25, 2025
c08059a
refactor: del unused type
krogla Sep 25, 2025
4194386
Merge pull request #1455 from lidofinance/fix-reportdata
krogla Sep 25, 2025
22395db
refactor: deposit temp storage
krogla Sep 25, 2025
00f747f
fix: add helper library for transient storage
krogla Sep 25, 2025
bd94f00
feat: add sessions to transient storage to avoid non-clear temp storage
krogla Sep 25, 2025
a1348bb
fix: accounting constructor params order, upgrade deploy scripts
krogla Sep 25, 2025
ddb84cd
Merge branch 'feat/testnet-2' into fix-tracker
krogla Sep 25, 2025
b95852f
Merge pull request #1452 from lidofinance/fix-tracker
krogla Sep 25, 2025
d7397a7
fix: removed separate wc02
krogla Sep 25, 2025
93ac560
Merge branch 'feat/staking-router-3.0' into feat/sr-migration-v4
krogla Sep 25, 2025
e24df8f
Merge pull request #1456 from lidofinance/feat/sr-migration-v4
krogla Sep 25, 2025
b09712b
feat: add consolidation gateway test
mkurayan Sep 29, 2025
c902c53
Merge pull request #1486 from lidofinance/consolidation-fixes
mkurayan Sep 29, 2025
949fb7b
Merge remote-tracking branch 'origin/feat/vaults' into feat/staking-r…
Amuhar Sep 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 60 additions & 50 deletions contracts/0.4.24/Lido.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ interface IBurnerMigration {
}

interface IStakingRouter {
function deposit(uint256 _depositsCount, uint256 _stakingModuleId, bytes _depositCalldata) external payable;
function deposit(uint256 _stakingModuleId, bytes _depositCalldata) external payable;

function getStakingModuleMaxDepositsCount(
uint256 _stakingModuleId,
uint256 _maxDepositsValue
uint256 _depositableEth
) external view returns (uint256);

function getTotalFeeE4Precision() external view returns (uint16 totalFee);
Expand All @@ -34,7 +34,15 @@ interface IStakingRouter {

function getWithdrawalCredentials() external view returns (bytes32);

function getStakingFeeAggregateDistributionE4Precision() external view returns (uint16 modulesFee, uint16 treasuryFee);
function getStakingFeeAggregateDistributionE4Precision()
external
view
returns (uint16 modulesFee, uint16 treasuryFee);

function getStakingModuleMaxInitialDepositsAmount(
uint256 _stakingModuleId,
uint256 _depositableEth
) external returns (uint256 depositsAmount, uint256 depositsCount);
}

interface IWithdrawalQueue {
Expand Down Expand Up @@ -123,6 +131,17 @@ contract Lido is Versioned, StETHPermit, AragonApp {
/// keccak256("lido.Lido.clBalanceAndClValidators");
bytes32 internal constant CL_BALANCE_AND_CL_VALIDATORS_POSITION =
0xc36804a03ec742b57b141e4e5d8d3bd1ddb08451fd0f9983af8aaab357a78e2f;

// Storage for balance-based accounting
/// @dev storage slot position for CL active balance
/// keccak256("lido.Lido.clActiveBalance");
bytes32 internal constant CL_ACTIVE_BALANCE_POSITION =
keccak256("lido.Lido.clActiveBalance");
/// @dev storage slot position for CL pending balance
/// keccak256("lido.Lido.clPendingBalance");
bytes32 internal constant CL_PENDING_BALANCE_POSITION =
keccak256("lido.Lido.clPendingBalance");

/// @dev storage slot position of the staking rate limit structure
/// keccak256("lido.Lido.stakeLimit");
bytes32 internal constant STAKING_STATE_POSITION =
Expand All @@ -142,8 +161,12 @@ contract Lido is Versioned, StETHPermit, AragonApp {
event StakingLimitRemoved();

// Emitted when validators number delivered by the oracle
// @deprecated This event is deprecated. Use CLBalancesUpdated instead for balance-based accounting
event CLValidatorsUpdated(uint256 indexed reportTimestamp, uint256 preCLValidators, uint256 postCLValidators);

// Emitted when CL balances are updated by the oracle
event CLBalancesUpdated(uint256 indexed reportTimestamp, uint256 clActiveBalance, uint256 clPendingBalance);

// Emitted when depositedValidators value is changed
event DepositedValidatorsChanged(uint256 depositedValidators);

Expand Down Expand Up @@ -591,16 +614,17 @@ contract Lido is Versioned, StETHPermit, AragonApp {
/**
* @notice Get the key values related to the Consensus Layer side of the contract.
* @return depositedValidators - number of deposited validators from Lido contract side
* @return beaconValidators - number of Lido validators visible on Consensus Layer, reported by oracle
* @return beaconBalance - total amount of ether on the Consensus Layer side (sum of all the balances of Lido validators)
* @return clActiveBalance - Active balance of validators on the consensus layer (without pending deposits)
* @return clPendingBalance - Pending deposits balance on the consensus layer
*/
function getBeaconStat()
external
view
returns (uint256 depositedValidators, uint256 beaconValidators, uint256 beaconBalance)
returns (uint256 depositedValidators, uint256 clActiveBalance, uint256 clPendingBalance)
{
depositedValidators = _getDepositedValidators();
(beaconBalance, beaconValidators) = _getClBalanceAndClValidators();
clActiveBalance = CL_ACTIVE_BALANCE_POSITION.getStorageUint256();
clPendingBalance = CL_PENDING_BALANCE_POSITION.getStorageUint256();
}

/**
Expand All @@ -623,40 +647,39 @@ contract Lido is Versioned, StETHPermit, AragonApp {

/**
* @notice Invoke a deposit call to the Staking Router contract and update buffered counters
* @param _maxDepositsCount max deposits count
* @param _maxDepositsAmountPerBlock max deposits amount per block
* @param _stakingModuleId id of the staking module to be deposited
* @param _depositCalldata module calldata
*/
function deposit(uint256 _maxDepositsCount, uint256 _stakingModuleId, bytes _depositCalldata) external {
function deposit(uint256 _maxDepositsAmountPerBlock, uint256 _stakingModuleId, bytes _depositCalldata) external {
// TODO: get rid of _maxDepositsAmountPerBlock
ILidoLocator locator = _getLidoLocator();

require(msg.sender == locator.depositSecurityModule(), "APP_AUTH_DSM_FAILED");
require(canDeposit(), "CAN_NOT_DEPOSIT");

IStakingRouter stakingRouter = _stakingRouter(locator);
uint256 depositsCount = Math256.min(
_maxDepositsCount,
stakingRouter.getStakingModuleMaxDepositsCount(_stakingModuleId, getDepositableEther())
(uint256 depositsAmount, uint256 depositsCount) = stakingRouter.getStakingModuleMaxInitialDepositsAmount(
_stakingModuleId,
Math256.min(_maxDepositsAmountPerBlock, getDepositableEther())
);

uint256 depositsValue;
if (depositsCount > 0) {
depositsValue = depositsCount.mul(DEPOSIT_SIZE);
if (depositsAmount > 0) {
/// @dev firstly update the local state of the contract to prevent a reentrancy attack,
/// even if the StakingRouter is a trusted contract.

(uint256 bufferedEther, uint256 depositedValidators) = _getBufferedEtherAndDepositedValidators();
depositedValidators = depositedValidators.add(depositsCount);

_setBufferedEtherAndDepositedValidators(bufferedEther.sub(depositsValue), depositedValidators);
emit Unbuffered(depositsValue);
_setBufferedEtherAndDepositedValidators(bufferedEther.sub(depositsAmount), depositedValidators);
emit Unbuffered(depositsAmount);
emit DepositedValidatorsChanged(depositedValidators);
}

/// @dev transfer ether to StakingRouter and make a deposit at the same time. All the ether
/// sent to StakingRouter is counted as deposited. If StakingRouter can't deposit all
/// passed ether it MUST revert the whole transaction (never happens in normal circumstances)
stakingRouter.deposit.value(depositsValue)(depositsCount, _stakingModuleId, _depositCalldata);
stakingRouter.deposit.value(depositsAmount)(_stakingModuleId, _depositCalldata);
}

/**
Expand Down Expand Up @@ -779,26 +802,24 @@ contract Lido is Versioned, StETHPermit, AragonApp {
/**
* @notice Process CL related state changes as a part of the report processing
* @dev All data validation was done by Accounting and OracleReportSanityChecker
* @dev V2: Replaces validator counting with direct balance tracking for EIP-7251 support
* @param _reportTimestamp timestamp of the report
* @param _preClValidators number of validators in the previous CL state (for event compatibility)
* @param _reportClValidators number of validators in the current CL state
* @param _reportClBalance total balance of the current CL state
* @param _clActiveBalance Active balance of validators on the consensus layer
* @param _clPendingBalance Pending deposits balance on the consensus layer
*/
function processClStateUpdate(
function processClStateUpdateV2(
uint256 _reportTimestamp,
uint256 _preClValidators,
uint256 _reportClValidators,
uint256 _reportClBalance
uint256 _clActiveBalance,
uint256 _clPendingBalance
) external {
_whenNotStopped();
_auth(_accounting());

// Save the current CL balance and validators to
// calculate rewards on the next rebase
_setClBalanceAndClValidators(_reportClBalance, _reportClValidators);
// Update storage with new balance model
CL_ACTIVE_BALANCE_POSITION.setStorageUint256(_clActiveBalance);
CL_PENDING_BALANCE_POSITION.setStorageUint256(_clPendingBalance);

emit CLValidatorsUpdated(_reportTimestamp, _preClValidators, _reportClValidators);
// cl balance change are logged in ETHDistributed event later
emit CLBalancesUpdated(_reportTimestamp, _clActiveBalance, _clPendingBalance);
}

/**
Expand Down Expand Up @@ -948,7 +969,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {
////////////////////////////////////////////////////////////////////////////

/**
* @notice DEPRECATED: Returns current withdrawal credentials of deposited validators
* @notice DEPRECATED: Returns current 0x01 withdrawal credentials of deposited validators
* @dev DEPRECATED: use StakingRouter.getWithdrawalCredentials() instead
*/
function getWithdrawalCredentials() external view returns (bytes32) {
Expand Down Expand Up @@ -1023,20 +1044,15 @@ contract Lido is Versioned, StETHPermit, AragonApp {
}

/// @dev Get the total amount of ether controlled by the protocol internally
/// (buffered + CL balance of StakingRouter controlled validators + transient)
/// (buffered + CL active balance + CL pending balance)
function _getInternalEther() internal view returns (uint256) {
(uint256 bufferedEther, uint256 depositedValidators) = _getBufferedEtherAndDepositedValidators();
(uint256 clBalance, uint256 clValidators) = _getClBalanceAndClValidators();

// clValidators can never exceed depositedValidators.
assert(depositedValidators >= clValidators);
// the total base balance (multiple of 32) of validators in transient state,
// i.e. submitted to the official Deposit contract but not yet visible in the CL state.
uint256 transientEther = (depositedValidators - clValidators) * DEPOSIT_SIZE;
uint256 bufferedEther = _getBufferedEther();
uint256 clActiveBalance = CL_ACTIVE_BALANCE_POSITION.getStorageUint256();
uint256 clPendingBalance = CL_PENDING_BALANCE_POSITION.getStorageUint256();

return bufferedEther
.add(clBalance)
.add(transientEther);
// With balance-based accounting, we don't need to calculate transientEther
// as pending deposits are already included in clPendingBalance
return bufferedEther.add(clActiveBalance).add(clPendingBalance);
}

/// @dev Calculate the amount of ether controlled by external entities
Expand Down Expand Up @@ -1089,9 +1105,7 @@ contract Lido is Versioned, StETHPermit, AragonApp {

if (totalShares * maxRatioBP <= externalShares * TOTAL_BASIS_POINTS) return 0;

return
(totalShares * maxRatioBP - externalShares * TOTAL_BASIS_POINTS) /
(TOTAL_BASIS_POINTS - maxRatioBP);
return (totalShares * maxRatioBP - externalShares * TOTAL_BASIS_POINTS) / (TOTAL_BASIS_POINTS - maxRatioBP);
}

function _pauseStaking() internal {
Expand Down Expand Up @@ -1277,10 +1291,6 @@ contract Lido is Versioned, StETHPermit, AragonApp {
);
}

function _getClBalanceAndClValidators() internal view returns (uint256, uint256) {
return CL_BALANCE_AND_CL_VALIDATORS_POSITION.getLowAndHighUint128();
}

function _setClBalanceAndClValidators(uint256 _newClBalance, uint256 _newClValidators) internal {
CL_BALANCE_AND_CL_VALIDATORS_POSITION.setLowAndHighUint128(_newClBalance, _newClValidators);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// SPDX-License-Identifier: GPL-3.0

// See contracts/COMPILERS.md
pragma solidity 0.8.9;
pragma solidity 0.8.25;

import {MemUtils} from "../common/lib/MemUtils.sol";
import {MemUtils} from "contracts/common/lib/MemUtils.sol";

interface IDepositContract {
function get_deposit_root() external view returns (bytes32 rootHash);
Expand All @@ -17,83 +17,92 @@
) external payable;
}

contract BeaconChainDepositor {
library BeaconChainDepositor {
uint256 internal constant PUBLIC_KEY_LENGTH = 48;
uint256 internal constant SIGNATURE_LENGTH = 96;
uint256 internal constant DEPOSIT_SIZE = 32 ether;
// uint256 internal constant DEPOSIT_SIZE = 32 ether;
// uint256 internal constant DEPOSIT_SIZE_02 = 2048 ether;

/// @dev deposit amount 32eth in gweis converted to little endian uint64
/// DEPOSIT_SIZE_IN_GWEI_LE64 = toLittleEndian64(32 ether / 1 gwei)
uint64 internal constant DEPOSIT_SIZE_IN_GWEI_LE64 = 0x0040597307000000;

IDepositContract public immutable DEPOSIT_CONTRACT;

constructor(address _depositContract) {
if (_depositContract == address(0)) revert DepositContractZeroAddress();
DEPOSIT_CONTRACT = IDepositContract(_depositContract);
}
// constructor(address _depositContract) {
// if (_depositContract == address(0)) revert DepositContractZeroAddress();
// DEPOSIT_CONTRACT = IDepositContract(_depositContract);
// }

/// @dev Invokes a deposit call to the official Beacon Deposit contract
/// @param _depositContract - IDepositContract deposit contract
/// @param _keysCount amount of keys to deposit
/// @param _withdrawalCredentials Commitment to a public key for withdrawals
/// @param _publicKeysBatch A BLS12-381 public keys batch
/// @param _signaturesBatch A BLS12-381 signatures batch
function _makeBeaconChainDeposits32ETH(
function makeBeaconChainDeposits32ETH(
// TODO: remove 32 from name
IDepositContract _depositContract,
uint256 _keysCount,
uint256 depositSize,
bytes memory _withdrawalCredentials,
bytes memory _publicKeysBatch,
bytes memory _signaturesBatch
) internal {
) public {
if (_publicKeysBatch.length != PUBLIC_KEY_LENGTH * _keysCount) {
revert InvalidPublicKeysBatchLength(_publicKeysBatch.length, PUBLIC_KEY_LENGTH * _keysCount);
}
if (_signaturesBatch.length != SIGNATURE_LENGTH * _keysCount) {
revert InvalidSignaturesBatchLength(_signaturesBatch.length, SIGNATURE_LENGTH * _keysCount);
}

bytes memory publicKey = MemUtils.unsafeAllocateBytes(PUBLIC_KEY_LENGTH);
bytes memory signature = MemUtils.unsafeAllocateBytes(SIGNATURE_LENGTH);

for (uint256 i; i < _keysCount;) {
for (uint256 i; i < _keysCount; ) {
MemUtils.copyBytes(_publicKeysBatch, publicKey, i * PUBLIC_KEY_LENGTH, 0, PUBLIC_KEY_LENGTH);
MemUtils.copyBytes(_signaturesBatch, signature, i * SIGNATURE_LENGTH, 0, SIGNATURE_LENGTH);

DEPOSIT_CONTRACT.deposit{value: DEPOSIT_SIZE}(
publicKey, _withdrawalCredentials, signature, _computeDepositDataRoot(_withdrawalCredentials, publicKey, signature)
_depositContract.deposit{value: depositSize}(
publicKey,
_withdrawalCredentials,
signature,
_computeDepositDataRoot(_withdrawalCredentials, publicKey, signature)
);

unchecked {
++i;
}
}
}

/// @dev computes the deposit_root_hash required by official Beacon Deposit contract
/// @param _publicKey A BLS12-381 public key.
/// @param _signature A BLS12-381 signature
function _computeDepositDataRoot(bytes memory _withdrawalCredentials, bytes memory _publicKey, bytes memory _signature)
private
pure
returns (bytes32)
{
function _computeDepositDataRoot(
bytes memory _withdrawalCredentials,
bytes memory _publicKey,
bytes memory _signature
) private pure returns (bytes32) {
// Compute deposit data root (`DepositData` hash tree root) according to deposit_contract.sol
bytes memory sigPart1 = MemUtils.unsafeAllocateBytes(64);
bytes memory sigPart2 = MemUtils.unsafeAllocateBytes(SIGNATURE_LENGTH - 64);
MemUtils.copyBytes(_signature, sigPart1, 0, 0, 64);
MemUtils.copyBytes(_signature, sigPart2, 64, 0, SIGNATURE_LENGTH - 64);

bytes32 publicKeyRoot = sha256(abi.encodePacked(_publicKey, bytes16(0)));
bytes32 signatureRoot = sha256(abi.encodePacked(sha256(abi.encodePacked(sigPart1)), sha256(abi.encodePacked(sigPart2, bytes32(0)))));
bytes32 signatureRoot = sha256(
abi.encodePacked(sha256(abi.encodePacked(sigPart1)), sha256(abi.encodePacked(sigPart2, bytes32(0))))
);

return sha256(
return
sha256(
abi.encodePacked(
sha256(abi.encodePacked(publicKeyRoot, _withdrawalCredentials)),
sha256(abi.encodePacked(DEPOSIT_SIZE_IN_GWEI_LE64, bytes24(0), signatureRoot))
)
);
}

error DepositContractZeroAddress();
// error DepositContractZeroAddress();
error InvalidPublicKeysBatchLength(uint256 actual, uint256 expected);
error InvalidSignaturesBatchLength(uint256 actual, uint256 expected);
}
Loading
Loading