---
# System prepended metadata

title: 'Tokenomics: Development'

---

# 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
}

````

