API ReferenceUser docs

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 withdrawals (skimmings and exits).

Complexity: Consensus rewards are a combination of the increasing balances of validators on the consensus layer as well as the “skimmings” amounts that are available on the execution layer.

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 == 32 eth AND a balance > 32 eth (partially withdrawable, skimming)
    • C: Or, alternatively to B, have a withdrawable_epoch < current_epoch AND a balance > 0(fully withdrawable, exiting)
  • Determine the position of V in L (N)
  • Compute for each validators in L their next skimming slot:
    • We have:
      • L the list of validator eligible for skimming
      • posX the index in L of the validator we're estimating for, 0 < posX < L
      • N the index in L of 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 + 1 because S already happened

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)
  • 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)
  • 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
  • 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)
  • 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 active_balance_end_of_day - active_balance_start_of_day + sum_withdrawals_during_day
  • 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 UTC counts as 0,5.
  • median_execution_reward: Median based on every single execution rewards earned during the day for all validators in the scope.