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:
- reward_for_source: the validator has made a timely vote for the correct source checkpoint;
- reward_for_target : the validator has made a timely vote for the correct target checkpoint;
- reward_for_head: the validator has made a timely vote for the correct head block;
- reward_for_sync: the validator has participated in a sync committee;
- 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.
- penalty_for_source;
- penalty_for_target;
- penalty_for_sync;
Missed rewards
For missing head or proposal duties there are no penalties, but rewards will also not be awarded;
- missed_reward_for_head
- missed_reward_for_proposal
Calculations
This page details how rewards and penalties are calculated.
The data required for calculations is in the following tables:
- t_epoch_summaries
- t_validator_epoch_summaries
- t_sync_committees
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 name | Type | Description |
---|---|---|
f_validator_index | INT | validator for which rewards are considered |
f_epoch | INT | number of epoch in which rewards were awarded |
epoch_ts | INT | epoch timestamp |
reward_for_proposal | INT | reward for block proposal |
missed_reward_for_proposal | INT | missed reward for block proposal |
reward_for_source | FLOAT | reward for source duty |
penalty_for_source | INT | penalty for missed source duty |
reward_for_target | FLOAT | reward for target duty |
penalty_for_target | INT | penalty for missed target duty |
reward_for_head | FLOAT | reward for head duty |
missed_reward_for_head | FLOAT | missed reward for head duty |
reward_for_sync | INT | reward for sync participation |
penalty_for_sync | INT | penalty for missed sync participation |
Updated 25 days ago