# Maximum New Validator Deposits per Transaction, Block and Inclusion List This article explores the maximum number of new validator deposits that fit in a single transaction, block and inclusion list, comparing the Assertoor and Coinbase batching approaches. ## Maximum Deposits per Transaction A transaction is capped at `16,777,216` gas per [EIP-7825](https://eips.ethereum.org/EIPS/eip-7825) and pays a flat `21,000` gas intrinsic before any opcode runs. The maximum deposits one batch transaction can carry is therefore `(16,777,216 − 21,000) / gas_per_deposit`, where `gas_per_deposit` is the amortized cost of one deposit inside a large, mostly-warm batch. This article references to approaches: [Assertoor](https://github.com/ethpandaops/assertoor/tree/master/pkg/tasks/generate_batch_deposits) and [Coinbase](https://etherscan.io/tx/0xa42ae00180479a43732b1ed9e1e204e863f621754b9898936ed64715917b03d3). | Approach | Deposits | Transaction Size | Transaction Gas Used | | :-----------------------------------------------------------------------------------------------------: | :------: | :----------------: | :------------------: | | [Assertoor](https://github.com/ethpandaops/assertoor/tree/master/pkg/tasks/generate_batch_deposits) | 710 | 125,434 B (122 KB) | 16,777,000 | | [Coinbase](https://etherscan.io/tx/0xa42ae00180479a43732b1ed9e1e204e863f621754b9898936ed64715917b03d3) | 620 | 238,490 B (233 KB) | 16,761,000 | Assertoor's `BatchDeposit` batcher concatenates per-deposit data ``(pubkey, signature, deposit_data_root)`` but shares `withdrawal_credentials` and `amount` across the whole batch, so every deposit contributes only 176 unique calldata bytes, costing roughly 23,600 gas. That fits 710 deposits in `21,000 + 710 × 23,600 = 16,777,000` gas. Coinbase's batcher gives each deposit its own `withdrawal_credentials` and `amount` via `bytes[]` and `uint256[]` arrays respectively. This multi-tenant flexibility costs an extra ~200 calldata bytes and ~3,400 gas per deposit, capping the tx at 620 deposits for `21,000 + 620 × 27,000 = 16,761,000` gas. Note that this is based on Fusaka. After Glamsterdam, max deposits per transaction is likely to drop because [EIP-8038](https://eips.ethereum.org/EIPS/eip-8038) raises warm `SSTORE` and `SLOAD` costs. ## Maximum Deposits per Block To fill a block of gas limit `G` with as many deposits as possible, pack `N_full` maximum-deposits transactions and squeeze the leftover gas into one final partial transaction: ``` N_full = floor(G / G_per_full_tx) G_remaining = G − N_full × G_per_full_tx deposits_partial = floor((G_remaining − 21,000) / gas_per_deposit) total_deposits = N_full × max_per_tx + deposits_partial ``` Let's take the 60M block as an example. Assertoor fits `floor(60,000,000 / 16,777,000) = 3` full transactions for `3 × 710 = 2,130` deposits using `50,331,000` gas. The remaining `9,669,000` gas takes one partial transaction with `floor((9,669,000 − 21,000) / 23,600) = 408` deposits, using `9,649,800` gas. Total: `2,538` deposits in `59,980,800` gas, with `19,200` gas unused (below the `23,600` needed for one more deposit). ``` N_full = floor(60,000,000 / 16,777,000) = floor(3.5764…) = 3 G_used_full = 3 × 16,777,000 = 50,331,000 G_remaining = 60,000,000 − 50,331,000 = 9,669,000 deposits_partial = floor((9,669,000 − 21,000) / 23,600) = floor(9,648,000 / 23,600) = floor(408.8135…) = 408 G_used_partial = 21,000 + 408 × 23,600 = 21,000 + 9,628,800 = 9,649,800 G_unused = 9,669,000 − 9,649,800 = 19,200 (< 23,600, can't fit another deposit) Total deposits = 3 × 710 + 408 = 2,538, total gas = 59,980,800 ``` Coinbase fits `3` full transactions for `3 × 620 = 1,860` deposits using `50,283,000` gas. The remaining `9,717,000` gas takes one partial transaction with `floor((9,717,000 − 21,000) / 27,000) = 359` deposits, using `9,714,000` gas. Total: `2,219` deposits in `59,997,000` gas, with `3,000` gas unused. ``` N_full = floor(60,000,000 / 16,761,000) = floor(3.5797…) = 3 G_remaining = 60,000,000 − 3 × 16,761,000 = 60,000,000 − 50,283,000 = 9,717,000 deposits_partial = floor(9,696,000 / 27,000) = floor(359.1111…) = 359 G_used_partial = 21,000 + 359 × 27,000 = 9,714,000 G_unused = 9,717,000 − 9,714,000 = 3,000 (< 23,600, can't fit another deposit) Total = 3 × 620 + 359 = 2,219, total gas = 59,997,000 ``` Applying the same procedure to the`200M`, `300M` and `400M` block gas limits yields (ignoring the `MAX_DEPOSIT_REQUESTS_PER_PAYLOAD` cap): | Block Gas Limit | Assertoor | Coinbase | | :-------------: | :-------: | :------: | | 60M | 2,538 | 2,219 | | 200M | 8,463 | 7,398 | | 300M | 12,695 | 11,097 | | 400M | 16,927 | 14,796 | ## Maximum Deposits per Inclusion List An inclusion list is capped at `MAX_BYTES_PER_INCLUSION_LIST = 8,192` bytes per [EIP-7805](https://eips.ethereum.org/EIPS/eip-7805). To fit as many deposits as possible into one inclusion list, pack a single batch transaction whose calldata plus envelope stays under that limit: ``` envelope (150) + header + bytes_per_deposit * N ≤ 8,192 ``` `header` is the fixed ABI overhead (selector + head slots + length prefixes + shared fields), `bytes_per_deposit` is the unique data per deposit and `150` is the signed type-2 envelope. Assertoor (`header = 4 + 160 + 96 + 64 = 324` and `bytes_per_deposit = 48 + 96 + 32 = 176`) fits `N ≤ (8,192 − 474) / 176 = 43.85`, so `N = 43` deposits result in a `8,042`-byte IL transaction. ``` 150 + 324 + 176 * N ≤ 8,192 176 * N ≤ 8,192 − 474 = 7,718 N ≤ 7,718 / 176 = 43.852… N = 43 → IL_tx_size = 150 + 324 + 176 * 43 = 8,042 bytes ``` Similarly, Coinbase (`header = 260`, `bytes_per_deposit = 384`, with per-deposit `withdrawal_credentials` and `amount` carried in arrays) fits `N ≤ (8,192 − 410) / 384 = 20.27`, i.e., a `8,090`-byte IL transaction. ``` 150 + 260 + 384 * N ≤ 8,192 384 * N ≤ 8,192 − 410 = 7,782 N ≤ 7,782 / 384 = 20.265… N = 20 → IL_tx_size = 150 + 260 + 384 * 20 = 8,090 bytes ``` | Approach | Deposits per IL | IL Size | | :-------: | :-------------: | :-----: | | Assertoor | 43 | 8,042 B | | Coinbase | 20 | 8,090 B |