-
Notifications
You must be signed in to change notification settings - Fork 51
/
abci.go
146 lines (118 loc) · 4.84 KB
/
abci.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package keeper
import (
errorsmod "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
assetprofiletypes "github.com/elys-network/elys/x/assetprofile/types"
"github.com/elys-network/elys/x/estaking/types"
ptypes "github.com/elys-network/elys/x/parameter/types"
)
// EndBlocker of incentive module
func (k Keeper) EndBlocker(ctx sdk.Context) {
// Rewards distribution
k.ProcessRewardsDistribution(ctx)
// Burn EdenB tokens if staking changed
k.BurnEdenBIfElysStakingReduced(ctx)
}
func (k Keeper) TakeDelegationSnapshot(ctx sdk.Context, addr sdk.AccAddress) {
// Calculate delegated amount per delegator
delAmount := k.CalcDelegationAmount(ctx, addr)
elysStaked := types.ElysStaked{
Address: addr.String(),
Amount: delAmount,
}
// Set Elys staked amount
k.SetElysStaked(ctx, elysStaked)
}
func (k Keeper) BurnEdenBIfElysStakingReduced(ctx sdk.Context) {
addrs := k.GetAllElysStakeChange(ctx)
// Handle addresses recorded on AfterDelegationModified
// This hook is exposed for genesis delegations as well
for _, delAddr := range addrs {
k.BurnEdenBFromElysUnstaking(ctx, delAddr)
k.TakeDelegationSnapshot(ctx, delAddr)
k.RemoveElysStakeChange(ctx, delAddr)
}
}
// Rewards distribution
func (k Keeper) ProcessRewardsDistribution(ctx sdk.Context) {
// Read tokenomics time based inflation params and update incentive module params.
k.ProcessUpdateIncentiveParams(ctx)
err := k.UpdateStakersRewards(ctx)
if err != nil {
ctx.Logger().Error("Failed to update staker rewards unclaimed", "error", err)
}
}
func (k Keeper) ProcessUpdateIncentiveParams(ctx sdk.Context) {
// Non-linear inflation per year happens and this includes yearly inflation data
listTimeBasedInflations := k.tokenomicsKeeper.GetAllTimeBasedInflation(ctx)
if len(listTimeBasedInflations) == 0 {
return
}
params := k.GetParams(ctx)
for _, inflation := range listTimeBasedInflations {
// Finding only current inflation data - and skip rest
if inflation.StartBlockHeight > uint64(ctx.BlockHeight()) || inflation.EndBlockHeight < uint64(ctx.BlockHeight()) {
continue
}
totalBlocksPerYear := sdk.NewInt(int64(inflation.EndBlockHeight - inflation.StartBlockHeight + 1))
// If totalBlocksPerYear is zero, we skip this inflation to avoid division by zero
if totalBlocksPerYear == sdk.ZeroInt() {
continue
}
// ------------- Stakers parameter -------------
blocksDistributed := sdk.NewInt(ctx.BlockHeight() - int64(inflation.StartBlockHeight))
params.StakeIncentives = &types.IncentiveInfo{
EdenAmountPerYear: sdk.NewInt(int64(inflation.Inflation.IcsStakingRewards)),
DistributionStartBlock: sdk.NewInt(int64(inflation.StartBlockHeight)),
TotalBlocksPerYear: totalBlocksPerYear,
BlocksDistributed: blocksDistributed,
}
k.SetParams(ctx, params)
return
}
params.StakeIncentives = nil
k.SetParams(ctx, params)
}
func (k Keeper) UpdateStakersRewards(ctx sdk.Context) error {
baseCurrency, found := k.assetProfileKeeper.GetUsdcDenom(ctx)
if !found {
return errorsmod.Wrapf(assetprofiletypes.ErrAssetProfileNotFound, "asset %s not found", ptypes.BaseCurrency)
}
// USDC amount in sdk.Dec type
feeCollectorAddr := authtypes.NewModuleAddress(authtypes.FeeCollectorName)
totalFeesCollected := k.commKeeper.GetAllBalances(ctx, feeCollectorAddr)
gasFeeCollectedDec := sdk.NewDecCoinsFromCoins(totalFeesCollected...)
dexRevenueStakersAmount := gasFeeCollectedDec.AmountOf(baseCurrency)
// Calculate eden amount per block
params := k.GetParams(ctx)
stakeIncentive := params.StakeIncentives
// Ensure totalBlocksPerYear are not zero to avoid division by zero
totalBlocksPerYear := k.parameterKeeper.GetParams(ctx).TotalBlocksPerYear
// Calculate
edenAmountPerYear := sdk.ZeroInt()
if stakeIncentive != nil && stakeIncentive.EdenAmountPerYear.IsPositive() {
edenAmountPerYear = stakeIncentive.EdenAmountPerYear
}
stakersEdenAmount := edenAmountPerYear.Quo(sdk.NewInt(totalBlocksPerYear))
// Maximum eden APR - 30% by default
totalElysEdenEdenBStake := k.TotalBondedTokens(ctx)
stakersMaxEdenAmount := params.MaxEdenRewardAprStakers.
MulInt(totalElysEdenEdenBStake).
QuoInt64(totalBlocksPerYear)
// Use min amount (eden allocation from tokenomics and max apr based eden amount)
stakersEdenAmount = sdk.MinInt(stakersEdenAmount, stakersMaxEdenAmount.TruncateInt())
stakersEdenBAmount := sdk.NewDecFromInt(totalElysEdenEdenBStake).
Mul(params.EdenBoostApr).
QuoInt64(totalBlocksPerYear).
RoundInt()
// Set block number and total dex rewards given
params.DexRewardsStakers.NumBlocks = sdk.OneInt()
params.DexRewardsStakers.Amount = dexRevenueStakersAmount
k.SetParams(ctx, params)
coins := sdk.NewCoins(
sdk.NewCoin(ptypes.Eden, stakersEdenAmount),
sdk.NewCoin(ptypes.EdenB, stakersEdenBAmount),
)
return k.commKeeper.MintCoins(ctx, authtypes.FeeCollectorName, coins.Sort())
}