Ethereum reporting methodology
Methodology deep dive for the Ethereum Reporting API
Coverage
- All network: All stakes (Kiln and non Kiln)
- All time: Since inception of the beacon chain Dec 2020 https://beaconcha.in/slot/1 (before the merge execution layer will be 0)
Methodology
Consensus Layer
- Track all validators balances each day.
- Track all deposits and withdrawals (top-ups, partials, skimmings and exits).
- Track all attestations, sync committee and proposer rewards.
Complexity: Consensus rewards are a combination of attestations, sync committee and proposer rewards.
Execution Layer
- Track every block rewards since “The Merge”.
- Track all relays delivered payloads.
Complexity: Rewards are earned through gas fees in every block as well as through custom payouts with the opaque and partially off-chain MEV (Maximal Extractable Value) system.
Skimming slot
Endpoint: https://docs.api.kiln.fi/reference/getethstakes
To compute estimated_next_skimming_slot for a given validator, we do the following:
- Determine the index of the last validator skimmed (V) and the slot at which it happened (S)
- Determine the list of validators that are eligible to skimming (L), it's ordered by validator indexes, to be eligible the validator must:
- A: Have a withdrawal credential starting with 0x01
- B: Have an effective balance == 32eth AND abalance > 32eth (partially withdrawable, skimming)
- C: Or, alternatively to B, have a withdrawable_epoch < current_epochAND abalance > 0(fully withdrawable, exiting)
 
- Determine the position of VinL (N)
- Compute for each validators in Ltheir next skimming slot:- We have:
- Lthe list of validator eligible for skimming
- posXthe index in- Lof the validator we're estimating for,- 0 < posX < L
- Nthe index in- Lof the last validator skimmed,- 0 < N < L
 
- S + 1 + (abs((L/16)*(posX<=N) - abs(N-posX)/16))- this assumes false=0&true=1
- S + 1because- Salready happened
 
- this assumes 
 
- We have:
Entry & Exit time estimations
Endpoint: https://docs.api.kiln.fi/reference/getethnetworkstats
To compute estimated_entry_time_seconds we do the following:
- We take the time for the consensus layer to acknowledge a deposit:
- A: every 2048 blocks * 12 seconds=24,576 seconds (6.83 hours)
- B: beacons get deposits made from the last [-13.66, -6.83]hours
- after this, elligible deposits are queued for activation
- As we provide a generic queue time, not based on a specific validator, we don't have a specific deposit timestamp so we take the middle ground of B's range: 10h14m24s (as in A * 1.5)
 
- A: every 
- Then we calculate the time it takes to go through the activation queue (timeToEmptyActivationQueue)- Determine how many epochs are needed to empty the queue: nb of validators in pending_queued state / 8- 8 is how many validators get activated by epoch.
- This value only stands on networks post Dencun hardfork, before that it used to be more approximate.
 
- Now that we know how many epochs are needed to empty the queue we just need to do: epochsToEmptyQueue * 12sec * SlotsPerEpoch(=32)
 
- Determine how many epochs are needed to empty the queue: nb of validators in 
- Lastly, we sum 10h14m24s + timeToEmptyActivationQueue
To compute estimated exit_time_seconds we do the following:
- We take the time to enter the exit queue:
- We can exit at least on the next epoch + MAX_SEED_LOOKAHEAD (4)epochs
- The next epoch is on average in 0.5 epoch, we use the middle point here as an estimation.
- eth.SlotTime(12) * SlotsPerEpoch(32) * (0.5 + MaxSeedLookahead) = 1728sec = 28min48sec
 
- We can exit at least on the 
- Then we calculate the time it takes to go through the exit queue (timeToEmptyExitQueue)- Determine how many epochs are needed to empty the queue: number of validators in active_exiting state / 8(same 8 as used to compute the entry queue)
- Now that we know how many epochs are needed to empty the queue we just need to do: epochsToEmptyQueue * 12sec * SlotsPerEpoch(=32)
 
- Determine how many epochs are needed to empty the queue: number of validators in 
- Lastly, we sum 28m48s + timeToEmptyExitQueue
To compute the estimated_withdrawal_time_seconds we do the following:
- Every slots there are 16 withdrawals processed by the consensus layer
- (# of active_ongoing validators + # of active_exiting validators) / 16= number of slot for the next withdraw
- Which we then convert to seconds: # of slot for the next withdraw * 12s (slot time)
Rewards
Endpoint: https://docs.api.kiln.fi/reference/getethrewards
With no scope filter provided, for the given validators:
- stake_balance: Is the active balance at the end of the day
- consensus_rewards: Is computed as- SUM(attestations+sync_committee+proposer_rewards)
- execution_rewards: Is computed as- SUM(blocks_rewards_of_day) AND/OR SUM(mev_rewards_of_day)
With scope=kiln|network data is computed in aggregate as such:
- stake_balance:- SUM(stake_balance)
- consensus_rewards:- SUM(consensus_rewards)
- mev_execution_rewards / non_mev_execution_rewards: execution rewards earned through MEV vs natively.
- execution_rewards:- mev_execution_rewards+non_mev_execution_rewards
- active_validator_count: Weighted number of active validators during the day. i.e. A validator joining at- 12:00:00 UTCcounts as 0,5.
- median_execution_reward: Median based on every single execution rewards earned during the day for all validators in the scope.
Updated about 2 months ago
