Rewards

This page describes how you can calculate rewards and penalties for validators for performing duties on the network.

The total validator’s rewards are calculated as the sum of five components:

  1. reward_for_source: the validator has made a timely vote for the correct source checkpoint;
  2. reward_for_target : the validator has made a timely vote for the correct target checkpoint;
  3. reward_for_head: the validator has made a timely vote for the correct head block;
  4. reward_for_sync: the validator has participated in a sync committee;
  5. reward_for_proposal: the validator has proposed a block in the correct slot;

Penalties

Besides rewards for source, target and sync duties there are penalties, if they are missed.

If the validator has not fulfilled duty, rewards are not awarded, but penalties are charged.

  1. penalty_for_source;
  2. penalty_for_target;
  3. penalty_for_sync;

Missed rewards

For missing head or proposal duties there are no penalties, but rewards will also not be awarded;

  1. missed_reward_for_head
  2. missed_reward_for_proposal

Calculations

This page details how rewards and penalties are calculated.

The data required for calculations is in the following tables:

Query with calculations

with 
cometee as  (
 SELECT
f_period*256-1 as start_epoch,
f_period*256+256 as end_epoch,
f_committee
 
FROM raw_beaconchain.t_sync_committees
),
rewards as (
SELECT
rewards.f_epoch,
cast(64000000000/sqrt(f_active_balance) as int) as br,
floor((f_active_balance/f_active_validators)/power(10,9)) as increment,
cast(64000000000/sqrt(f_active_balance)*floor((f_active_balance/f_active_validators)/power(10,9))*14/64 as int) as head_reward,
cast(64000000000/sqrt(f_active_balance)*floor((f_active_balance/f_active_validators)/power(10,9))*14/64 as int) as source_reward,
cast(64000000000/sqrt(f_active_balance)*floor((f_active_balance/f_active_validators)/power(10,9))*26/64 as int) as target_reward,
cast((f_active_validators/32)*(8/56)*(54/64*64000000000/sqrt(f_active_balance)*floor((f_active_balance/f_active_validators)/power(10,9))) as int) as proposer_reward,
cast(2/(512*64*32)*f_active_validators* 64000000000/sqrt(f_active_balance)*floor((f_active_balance/f_active_validators)/power(10,9))*32 as int) as sync_reward,
cast(512*8/56*2/(32*512*64)*f_active_validators* 64000000000/sqrt(f_active_balance)*floor((f_active_balance/f_active_validators)/power(10,9)) as int) as sync_reward_proposer,
f_attesting_balance/f_active_balance AS source_coef,
f_target_correct_balance/f_active_balance AS target_coef,
f_head_correct_balance/f_active_balance AS head_coef
 
FROM raw_beaconchain.t_epoch_summaries as rewards
 
)
 
 
SELECT
f_validator_index,
val_info.f_epoch,
(1606824023 + (val_info.f_epoch * 12 * 32)) AS epoch_ts,
case
when cast(f_validator_index as string) in unnest(SPLIT(SUBSTR(cometee.f_committee, 2 , LENGTH(cometee.f_committee) - 2)))
then 1
else 0 end as sync_cometee_participation,
case
when f_proposer_duties = 1 and  f_proposals_included=1
then proposer_reward+sync_reward_proposer
else 0
end as reward_for_proposal,
case
when f_proposer_duties = 1 and  f_proposals_included=0
then proposer_reward
when f_proposer_duties = 1 and  f_proposals_included=1 and cast(f_validator_index as string) in unnest(SPLIT(SUBSTR(cometee.f_committee, 2 , LENGTH(cometee.f_committee) - 2)))
then proposer_reward+sync_reward_proposer
else 0 end as missed_reward_for_proposal,
case
when f_attestation_source_timely is true
then source_reward*source_coef
else 0 end as reward_for_source,
case
when f_attestation_source_timely is not true
then source_reward
else 0 end as penalty_for_source,
case
when f_attestation_target_correct is true and f_attestation_target_timely is true
then target_reward*target_coef
else 0 end as reward_for_target,
case
when f_attestation_target_correct is not true or f_attestation_target_timely is not true
then target_reward
else 0 end as penalty_for_target,
case
when f_attestation_head_correct is true and f_attestation_head_timely is true
then head_reward*head_coef
else 0 end as reward_for_head,
case
when f_attestation_head_correct is not true or f_attestation_head_timely is not true
then head_reward*head_coef
else 0 end as missed_reward_for_head,
case
when f_attestation_source_timely is true and f_attestation_target_correct is true and f_attestation_target_timely is true and f_attestation_head_correct is true and f_attestation_head_timely is true and cast(f_validator_index as string) in unnest(SPLIT(SUBSTR(cometee.f_committee, 2 , LENGTH(cometee.f_committee) - 2)))
then sync_reward
else 0 end as reward_for_sync,
case
when (f_attestation_head_correct is not true or f_attestation_head_timely is not true ) and (cast(f_validator_index as string) in unnest(SPLIT(SUBSTR(cometee.f_committee, 2 , LENGTH(cometee.f_committee) - 2))))
then sync_reward
else 0 end as penalty_for_sync
FROM raw_beaconchain.chaind.t_validator_epoch_summaries as val_info
inner join cometee on val_info.f_epoch >= cometee.start_epoch and val_info.f_epoch <= cometee.end_epoch
inner join rewards on rewards.f_epoch=val_info.f_epoch
where val_info.f_epoch>80000

Output schema

Column nameTypeDescription
f_validator_indexINTvalidator for which rewards are considered
f_epochINTnumber of epoch in which rewards were awarded
epoch_tsINTepoch timestamp
reward_for_proposalINTreward for block proposal
missed_reward_for_proposalINTmissed reward for block proposal
reward_for_sourceFLOATreward for source duty
penalty_for_sourceINTpenalty for missed source duty
reward_for_targetFLOATreward for target duty
penalty_for_targetINTpenalty for missed target duty
reward_for_headFLOATreward for head duty
missed_reward_for_headFLOATmissed reward for head duty
reward_for_syncINTreward for sync participation
penalty_for_syncINTpenalty for missed sync participation