# Besu Deposit Contract Address Postmortem
An analysis of the spec changes and the evolution of the Besu codebase leading to the omission of the `DEPOSIT_CONTRACT_ADDRESS` for Holesky and Sepolia.
This ultimately lead to a supermajority chain split on Holesky since Geth and Nethermind had a similar bug: https://github.com/ethereum/pm/blob/master/Pectra/holesky-postmortem.md
The point of this postmortem is not to assign blame, but rather help understand how we might avoid similar problems in the future.
## Potential Contributing Factors
### General
* Testnets use different values for `DEPOSIT_CONTRACT_ADDRESS` compared to Mainnet
* https://eips.ethereum.org/EIPS/eip-6110#configuration doesn't include testnet contract addresses
* Unlike CLs, EL config files are different per client
* Unlike CLs, EL config isn't considered part of the spec
* https://github.com/eth-clients/holesky doesn't include `depositContractAddress` in any of the EL configs
* https://github.com/eth-clients/sepolia only includes `depositContractAddress` for genesis.json; not besu.json or chainspec.json
* No way to verify contract configuration between clients
### Besu specific
* Besu defaults to Mainnet address if not present in config
* Besu uses custom genesis config for automated tests rather than loading public testnet config
* Various PR authors/reviewers spanning nearly 3 years - no single Besu dev championing the feature
## Learnings
* Don't rely on defaults, fail early instead
* https://github.com/hyperledger/besu/issues/8367
* https://github.com/jflo/besu/tree/failFastOnUndefinedSystemContract
* Adopt `eth_config` https://hackmd.io/@shemnon/eth_config
* https://github.com/hyperledger/besu/pull/8417
* Use a shared config between ELs (`eth_config` might mitigate this anyway)
* https://github.com/hyperledger/besu/issues/7273
* A shared config could be used as part of the specification for a fork
## Timeline
### Oct 2020
https://eth2book.info/capella/part2/deposits-withdrawals/contract/
> The deposit contract was deployed on October the 14th, 2020, at 09:22:52 UTC to Ethereum address
`0x00000000219ab540356cbb839cbe05303d7705fa`.
### Oct 2021
https://github.com/eth-clients/sepolia/
Sepolia launched (without deposit contract)
### June 2022
Sepolia deposit contract deployed on `Jun-09-2022 02:58:14 PM UTC` to `0x7f02C3E3c98b133055B8B348B2Ac625669Ed295D`
### December 2022
https://github.com/ethereum/EIPs/pull/6110
Initial spec only includes Mainnet `DEPOSIT_CONTRACT_ADDRESS`
At this point Sepolia deposit contract existed but Holesky network did not exist.
At time of writing (March 2025) the [spec still only contains the Mainnet `DEPOSIT_CONTRACT_ADDRESS`](https://github.com/ethereum/EIPs/blob/05662960071dcd5610f147884aa75210a713d81c/EIPS/eip-6110.md?plain=1#L47)
### June 2023
https://github.com/hyperledger/besu/pull/5295 _(EIP-6110: Add deposit validation and apis)_
- `DEFAULT_DEPOSIT_CONTRACT_ADDRESS` added:
```
public static final Address DEFAULT_DEPOSIT_CONTRACT_ADDRESS =
Address.fromHexString("0x00000000219ab540356cbb839cbe05303d7705fa");
```
- Wired up for "experimental EIPs fork", not yet wired up for Prague:
```
final Address depositContractAddress =
genesisConfigOptions.getDepositContractAddress().orElse(DEFAULT_DEPOSIT_CONTRACT_ADDRESS);
```
- Explicit genesis config for Mainnet omitted - not a bug as default would be used.
- Explicit genesis config for Sepolia omitted - this would have been a bug if Sepolia had gone through Pectra before Holesky.
- **Holesky did not exist yet in order for configuration to be added!**
- Explicit genesis config _was_ added as part of a custom test genesis file.
### Sept 2023
https://github.com/eth-clients/holesky
Holesky launched with `DEPOSIT_CONTRACT_ADDRESS` predeployed in genesis to
`0x4242424242424242424242424242424242424242`
Besu did not add the `depositContractAddress` to the Holesky config that EIP-6110 would use (neither Mainnet, Sepolia nor Goerli had it either).
### March 2024
http://github.com/hyperledger/besu/pull/6783 _(Adding engine_getPayloadV4 and engine_newPayloadV4)_
- `DEFAULT_DEPOSIT_CONTRACT_ADDRESS` wired up for Prague fork
```
final Address depositContractAddress =
genesisConfigOptions.getDepositContractAddress().orElse(DEFAULT_DEPOSIT_CONTRACT_ADDRESS);
```
### May 2024 - Oct 2024
Various PRs (implementing various spec changes) by various people which refactored the location of the `DEFAULT_DEPOSIT_CONTRACT_ADDRESS` and wiring/loading code.
These refactorings didn't have a significant impact on the root cause, but potentially contributed to diluting the knowledge and understanding of the system.
https://github.com/hyperledger/besu/pull/7068 *(EIP-7685 General purpose execution layer requests)*
https://github.com/hyperledger/besu/pull/7647 *(Add consolidationRequestContract in jsonGenesisConfig)*
https://github.com/hyperledger/besu/pull/7771 *(Change requests to use flat encoding)*