The Shapella upgrade included a number of EIPs, including EIP-4895: Beacon chain push withdrawals as operations.
This EIP provides a way for validator withdrawals made on the beacon chain to enter into the EVM.
Withdrawals are represented as a new type of object in the execution payload – an “operation” – that separates the withdrawals feature from user-level transactions.
The "execution payload" is what is returned by
web3.eth.getBlock(). It is called that way to distinguish it from Beacon Chain blocks.
The references for the withdrawal fields and a brief description are:
The execution payload gains a new field for the withdrawals which is an RLP list of Withdrawal data.
The execution payload header gains a new field committing to the withdrawals in the execution payload.
This commitment is constructed identically to the transactions root in the existing execution payload header by inserting each withdrawal into a Merkle-Patricia trie keyed by index in the list of withdrawals.
From EIP-4895, Withdrawal objects are serialized as a RLP list according to the schema:
[index, validator_index, address, amount].
EIP-4895 defines the items in the list as:
- a monotonically increasing
index, starting from 0, as a uint64 value that increments by 1 per withdrawal to uniquely identify each withdrawal
validator_index of the validator, as a uint64 value, on the consensus layer the withdrawal corresponds to
- a recipient for the withdrawn ether
address as a 20-byte value
- a nonzero
amount of ether given in Gwei (1e9 wei) as a uint64 value.
When you are looking at an address and calculating its balance, you have to start looking at the withdrawals fields too, as the address could have received additional ether from a validator. (Also important to know What happens when a validator's withdrawal address is a smart contract with a fallback function?)