# Tokenomics: Development ![](https://i.imgur.com/aNXFrjQ.png) # <font color="red">TODO</font> 1. Продумать использование значенией с плавающей точкой > скорее всего использование `big.Int` или `big.Float` # Константы 1. Определить в файле `config/params/config.go` 2. Задать значения в файле `config/params/mainnet_config.go` ### стейк для одного координатора (*уже определен*) > s = 32000 ````go MaxEffectiveBalance: 32 * 1e9 * 1000, ```` ### time of i-th slot in the Coordinating network (sec), (*уже определен*) > $t_i^с$ – the time of i-th slot in the Coordinating network (sec), initial value = 4; ````go SecondsPerSlot: 4, ```` ### current optimal number of Coordinators > ![](https://i.imgur.com/xLZKtov.png) ````go optimalCoordinatorsNr: 8196 ```` ### maximum annualized return rate with N<sub>0</sub> Coordinators > ![](https://i.imgur.com/pVb3TTk.png) ````go optimalMaxAnnualizedRate: 0.20 ```` ### Shares of Base Slot Reward by roles Константы пропорций распределения Базовой Награды за слот (BaseSlotReward ) по ролям участников ````go BsrShareAgregatator: 1/3, BsrShareProposer: 1/3, BsrShareAttesters: 1/3, ```` share # Вычисляемые значения *Реализовать в хелперах* ### N – the current number of Workers; уже реализовано, см. `beacon-chain/core/helpers/validators.go:145` ````go // ActiveValidatorCount returns the number of active validators in the state // at the given epoch. func ActiveValidatorCount(ctx context.Context, s state.ReadOnlyBeaconState, epoch types.Epoch) (uint64, error) ```` ### maximum annualized return rate with N Coordinators > $R = {R_0 * \sqrt{N_0 \over N}}$ ````go func MaxAnnualizedRate(ctx context.Context, s state.ReadOnlyBeaconState, epoch types.Epoch) (float64, error){ r_0 := params.BeaconConfig().optimalMaxAnnualizedRate n_0 := params.BeaconConfig().optimalCoordinatorsNr n := ActiveValidatorCount() r := r_0 * math.sqrt(n_0/n) return r } ```` ### the annualized minted amount > $V = {R_0 * s * \sqrt{N_0 * N}}$ ````go func AnnualizedMintingAmount(ctx context.Context, s state.ReadOnlyBeaconState, epoch types.Epoch) (uint64, error){ r_0 := params.BeaconConfig().optimalMaxAnnualizedRate s := params.BeaconConfig().MaxEffectiveBalance n_0 := params.BeaconConfig().optimalCoordinatorsNr n := ActiveValidatorCount() v := r_0 * s * math.sqrt(n_0 * n) return v } ```` ### slots per year > $B_i^c={60 * 60 * 24 * 365.25 \over t_i^с}$ ````go func SlotsPerYear() (float64){ yearSec := 60 * 60 * 24 * 365.25 t_c := params.BeaconConfig().SecondsPerSlot return yearSec / t_c } ```` ### reward per i-th block (Base Slot Reward) Базовая награда за слот - основа расчета всех остальных наград > $W = W_i^c = {V\over B_i^с}$ ````go func BaseSlotReward() (float64){ yearSec := 60 * 60 * 24 * 365.25 t_c := params.BeaconConfig().SecondsPerSlot return yearSec / t_c } ```` ### number of members in committee *посмотреть целесообразность, может можно и без этой обойтись* $M$ – the number of members in committee. ````go func CommitteeLen(ctx context.Context, state state.ReadOnlyBeaconState, slot types.Slot, committeeIndex types.CommitteeIndex) (uint64, error){ // validator indexes of committee committee, err := helpers.BeaconCommitteeFromState(ctx, beaconState, att.Data.Slot, att.Data.CommitteeIndex) if err != nil { return 0, err } return len(committee), nil } ```` ### number of committees *уже реализовано* $L$ – the number of committees. ````go // SlotCommitteeCount returns the number of beacon committees of a slot. The // active validator count is provided as an argument rather than an imported implementation // from the spec definition. Having the active validator count as an argument allows for // cheaper computation, instead of retrieving head state, one can retrieve the validator // count. func SlotCommitteeCount(activeValidatorCount uint64) uint64 { var committeesPerSlot = activeValidatorCount / uint64(params.BeaconConfig().SlotsPerEpoch) / params.BeaconConfig().TargetCommitteeSize if committeesPerSlot > params.BeaconConfig().MaxCommitteesPerSlot { return params.BeaconConfig().MaxCommitteesPerSlot } if committeesPerSlot == 0 { return 1 } return committeesPerSlot } ```` # награда за создание блока в координирующей сети >Лидер слота выбирается среди членов комитета. > $rwd = {W \over 3} * 𝛾_2$ > – the base reward of a slot leader, > $𝛾_2 \in (0,1]$ - a ratio of included aggregators’ messages. ###### на рассмотрение: > $𝛾_2$ - расчитываем следующим образом: > $𝛾_2 = {\sum_{i=0}^n (T_i + S_i + H_i) \over M * 3}$ где: $T_i$ - таргет-аттестация $S_i$ - сорс-аттестация $H_i$ - хед-аттестация $M$ – the number of members per committee. $3$ - кол-во типов аттестаций ($T_i, S_i, H_i$) за которые начисляются поинты Лидер слота - Proposer Имплементировать в ````go // ProcessAttestationNoVerifySignature processes the attestation without verifying the attestation signature. This // method is used to validate attestations whose signatures have already been verified or will be verified later. func ProcessAttestationNoVerifySignature(...) ... { ... // validator indexes of committee committee, err := helpers.BeaconCommitteeFromState(ctx, beaconState, att.Data.Slot, att.Data.CommitteeIndex) ... //RM depracated // return SetParticipationAndRewardProposer(ctx, beaconState, att.Data.Target.Epoch, indices, participatedFlags, totalBalance) return SetParticipationAndRewardProposer(ctx, beaconState, att.Data.Target.Epoch, indices, committee, participatedFlags, totalBalance) } ```` ````go // SetParticipationAndRewardProposer retrieves and sets the epoch participation bits in state. Based on the epoch participation, it rewards // the proposer in state. func SetParticipationAndRewardProposer( ctx context.Context, beaconState state.BeaconState, targetEpoch types.Epoch, indices []uint64, committee []types.ValidatorIndex, // add new param participatedFlags map[uint8]bool, totalBalance uint64) (state.BeaconState, error) { // effective attestations count // io proposerRewardNumerator var attsCount uint64 // var proposerRewardNumerator uint64 ... if targetEpoch == currentEpoch { stateErr = beaconState.ModifyCurrentParticipationBits(func(val []byte) ([]byte, error) { // propRewardNum, epochParticipation, err := EpochParticipation(beaconState, indices, val, participatedFlags, totalBalance) attCnt, epochParticipation, err := EpochParticipation(beaconState, indices, val, participatedFlags, totalBalance) ... // proposerRewardNumerator = propRewardNum attsCount = attCnt return epochParticipation, nil }) } else { stateErr = beaconState.ModifyPreviousParticipationBits(func(val []byte) ([]byte, error) { // propRewardNum, epochParticipation, err := EpochParticipation(beaconState, indices, val, participatedFlags, totalBalance) attCnt, epochParticipation, err := EpochParticipation(beaconState, indices, val, participatedFlags, totalBalance) ... // proposerRewardNumerator = propRewardNum attsCount = attCnt return epochParticipation, nil }) } /*RM depracated if err := RewardProposer(ctx, beaconState, proposerRewardNumerator); err != nil { //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return nil, err } */ var attsRewardRate float64 = attsCount/(len(committee) * 3) if err := RewardProposer(ctx, beaconState, attsRate); err != nil { //^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return nil, err } return beaconState, nil } ```` ````go // EpochParticipation sets and returns the proposer reward numerator and epoch participation. func EpochParticipation(beaconState state.BeaconState, indices []uint64, epochParticipation []byte, participatedFlags map[uint8]bool, totalBalance uint64) (uint64, []byte, error) { cfg := params.BeaconConfig() sourceFlagIndex := cfg.TimelySourceFlagIndex targetFlagIndex := cfg.TimelyTargetFlagIndex headFlagIndex := cfg.TimelyHeadFlagIndex // proposerRewardNumerator := uint64(0) // io proposerRewardNumerator attCnt := := uint64(0) for _, index := range indices { if index >= uint64(len(epochParticipation)) { return 0, nil, fmt.Errorf("index %d exceeds participation length %d", index, len(epochParticipation)) } br, err := BaseRewardWithTotalBalance(beaconState, types.ValidatorIndex(index), totalBalance) if err != nil { return 0, nil, err } has, err := HasValidatorFlag(epochParticipation[index], sourceFlagIndex) if err != nil { return 0, nil, err } if participatedFlags[sourceFlagIndex] && !has { epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], sourceFlagIndex) if err != nil { return 0, nil, err } attCnt++ // proposerRewardNumerator += br * cfg.TimelySourceWeight } has, err = HasValidatorFlag(epochParticipation[index], targetFlagIndex) if err != nil { return 0, nil, err } if participatedFlags[targetFlagIndex] && !has { epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], targetFlagIndex) if err != nil { return 0, nil, err } attCnt++ // proposerRewardNumerator += br * cfg.TimelyTargetWeight } has, err = HasValidatorFlag(epochParticipation[index], headFlagIndex) if participatedFlags[headFlagIndex] && !has { epochParticipation[index], err = AddValidatorFlag(epochParticipation[index], headFlagIndex) ... attCnt++ // proposerRewardNumerator += br * cfg.TimelyHeadWeight } } //RM depracated //return proposerRewardNumerator, epochParticipation, nil return attCnt, epochParticipation, nil } ```` ````go // RewardProposer rewards proposer by increasing proposer's balance // func RewardProposer(ctx context.Context, beaconState state.BeaconState, proposerRewardNumerator uint64) error { func RewardProposer(ctx context.Context, beaconState state.BeaconState uint64, attsRewardRate float64) error { /* RM depracated cfg := params.BeaconConfig() d := (cfg.WeightDenominator - cfg.ProposerWeight) * cfg.WeightDenominator / cfg.ProposerWeight proposerReward := proposerRewardNumerator / d */ bsr := helper.BaseSlotReward() proposerReward := bsr * params.BeaconConfig().BsrShareProposer * attsRewardRate i, err := helpers.BeaconProposerIndex(ctx, beaconState) if err != nil { return err } return helpers.IncreaseBalance(beaconState, i, proposerReward) } ```` # награда за агрегацию аттестаций в координирующей сети > $L$ – the number of committees. Агрегатор выбирается среди членов своего комитета. W3L1 – the base reward of a committee aggregator, 1(2/3,1], where $1 \in (2/3,1]$ is a ratio of included committee members’ signatures to the committee size M. Агрегатор - роль агрегатора выполняет Proposer. ````go /* Function ProcessSyncAggregate /home/mezin/go/src/tesseract/beacon-chain/core/transition transition_no_verify_sig.go ProcessBlockForStateRoot state, err = altair.ProcessSyncAggregate(ctx, state, sa) */ // ProcessSyncAggregate verifies sync committee aggregate signature signing over the previous slot block root. func ProcessSyncAggregate(ctx context.Context, s state.BeaconStateAltair, sync *ethpb.SyncAggregate) (state.BeaconStateAltair, error) { votedKeys, votedIndices, didntVoteIndices, err := FilterSyncCommitteeVotes(s, sync) ... if err := VerifySyncCommitteeSig(s, votedKeys, sync.SyncCommitteeSignature); err != nil { return nil, err } return ApplySyncRewardsPenalties(ctx, s, votedIndices, didntVoteIndices) //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ } ```` ````go // ApplySyncRewardsPenalties applies rewards and penalties for proposer and sync committee participants. func ApplySyncRewardsPenalties(ctx context.Context, s state.BeaconStateAltair, votedIndices, didntVoteIndices []types.ValidatorIndex) (state.BeaconStateAltair, error) { activeBalance, err := helpers.TotalActiveBalance(s) ... proposerReward, participantReward, err := SyncRewards(activeBalance) ... // Apply sync committee rewards. earnedProposerReward := uint64(0) for _, index := range votedIndices { /* index=118 participantReward=350 */ if err := helpers.IncreaseBalance(s, index, participantReward); err != nil { //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return nil, err } earnedProposerReward += proposerReward //^^^^^^^^^^^^^^^^^^^^ } // Apply proposer rewards. proposerIndex, err := helpers.BeaconProposerIndex(ctx, s) ... /* earnedProposerReward=25600 proposerIndex=7 */ if err := helpers.IncreaseBalance(s, proposerIndex, earnedProposerReward); err != nil { return nil, err } // Apply sync committee penalties. for _, index := range didntVoteIndices { if err := helpers.DecreaseBalance(s, index, participantReward); err != nil { //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ return nil, err } } return s, nil } // SyncRewards returns the proposer reward and the sync participant reward given the total active balance in state. func SyncRewards(activeBalance uint64) (proposerReward, participantReward uint64, err error) { cfg := params.BeaconConfig() totalActiveIncrements := activeBalance / cfg.EffectiveBalanceIncrement baseRewardPerInc, err := BaseRewardPerIncrement(activeBalance) if err != nil { return 0, 0, err } totalBaseRewards := baseRewardPerInc * totalActiveIncrements maxParticipantRewards := totalBaseRewards * cfg.SyncRewardWeight / cfg.WeightDenominator / uint64(cfg.SlotsPerEpoch) participantReward = maxParticipantRewards / cfg.SyncCommitteeSize proposerReward = participantReward * cfg.ProposerWeight / (cfg.WeightDenominator - cfg.ProposerWeight) return } // BaseRewardPerIncrement of the beacon state // // Spec code: // def get_base_reward_per_increment(state: BeaconState) -> Gwei: // return Gwei(EFFECTIVE_BALANCE_INCREMENT * BASE_REWARD_FACTOR // integer_squareroot(get_total_active_balance(state))) func BaseRewardPerIncrement(activeBalance uint64) (uint64, error) { if activeBalance == 0 { return 0, errors.New("active balance can't be 0") } cfg := params.BeaconConfig() return cfg.EffectiveBalanceIncrement * cfg.BaseRewardFactor / math.IntegerSquareRoot(activeBalance), nil } ````