Skip to content

Commit

Permalink
Revert "feat: fixed rate minting rewards (#71)"
Browse files Browse the repository at this point in the history
This reverts commit 22fe4fc.
  • Loading branch information
ejfitzgerald committed Feb 17, 2021
1 parent 77e5a11 commit 0f89d36
Show file tree
Hide file tree
Showing 7 changed files with 213 additions and 38 deletions.
4 changes: 3 additions & 1 deletion x/mint/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ func BeginBlocker(ctx sdk.Context, k Keeper) {

// recalculate inflation rate
totalStakingSupply := k.StakingTokenSupply(ctx)
minter.Inflation = minter.NextInflationRate(params)
bondedRatio := k.BondedRatio(ctx)
minter.Inflation = minter.NextInflationRate(params, bondedRatio)
minter.AnnualProvisions = minter.NextAnnualProvisions(params, totalStakingSupply)
k.SetMinter(ctx, minter)

Expand All @@ -42,6 +43,7 @@ func BeginBlocker(ctx sdk.Context, k Keeper) {
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeMint,
sdk.NewAttribute(types.AttributeKeyBondedRatio, bondedRatio.String()),
sdk.NewAttribute(types.AttributeKeyInflation, minter.Inflation.String()),
sdk.NewAttribute(types.AttributeKeyAnnualProvisions, minter.AnnualProvisions.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, mintedCoin.Amount.String()),
Expand Down
1 change: 1 addition & 0 deletions x/mint/internal/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package types
const (
EventTypeMint = ModuleName

AttributeKeyBondedRatio = "bonded_ratio"
AttributeKeyInflation = "inflation"
AttributeKeyAnnualProvisions = "annual_provisions"
)
26 changes: 23 additions & 3 deletions x/mint/internal/types/minter.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,29 @@ func ValidateMinter(minter Minter) error {
}

// NextInflationRate returns the new inflation rate for the next hour.
func (m Minter) NextInflationRate(params Params) sdk.Dec {
// the annual inflation rate is just the fixed rate
return params.InflationRate
func (m Minter) NextInflationRate(params Params, bondedRatio sdk.Dec) sdk.Dec {
// The target annual inflation rate is recalculated for each previsions cycle. The
// inflation is also subject to a rate change (positive or negative) depending on
// the distance from the desired ratio (67%). The maximum rate change possible is
// defined to be 13% per year, however the annual inflation is capped as between
// 7% and 20%.

// (1 - bondedRatio/GoalBonded) * InflationRateChange
inflationRateChangePerYear := sdk.OneDec().
Sub(bondedRatio.Quo(params.GoalBonded)).
Mul(params.InflationRateChange)
inflationRateChange := inflationRateChangePerYear.Quo(sdk.NewDec(int64(params.BlocksPerYear)))

// adjust the new annual inflation for this next cycle
inflation := m.Inflation.Add(inflationRateChange) // note inflationRateChange may be negative
if inflation.GT(params.InflationMax) {
inflation = params.InflationMax
}
if inflation.LT(params.InflationMin) {
inflation = params.InflationMin
}

return inflation
}

// NextAnnualProvisions returns the annual provisions based on current total
Expand Down
38 changes: 29 additions & 9 deletions x/mint/internal/types/minter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,41 @@ import (
func TestNextInflation(t *testing.T) {
minter := DefaultInitialMinter()
params := DefaultParams()
blocksPerYr := sdk.NewDec(int64(params.BlocksPerYear))

// Governing Mechanism:
// inflationRateChangePerYear = (1- BondedRatio/ GoalBonded) * MaxInflationRateChange

tests := []struct {
setInflation, expChange sdk.Dec
bondedRatio, setInflation, expChange sdk.Dec
}{
// no change from the default (3%)
{sdk.NewDecWithPrec(3, 2), sdk.ZeroDec()},
// with 0% bonded atom supply the inflation should increase by InflationRateChange
{sdk.ZeroDec(), sdk.NewDecWithPrec(7, 2), params.InflationRateChange.Quo(blocksPerYr)},

// 100% bonded, starting at 20% inflation and being reduced
// (1 - (1/0.67))*(0.13/8667)
{sdk.OneDec(), sdk.NewDecWithPrec(20, 2),
sdk.OneDec().Sub(sdk.OneDec().Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(blocksPerYr)},

// 50% bonded, starting at 10% inflation and being increased
{sdk.NewDecWithPrec(5, 1), sdk.NewDecWithPrec(10, 2),
sdk.OneDec().Sub(sdk.NewDecWithPrec(5, 1).Quo(params.GoalBonded)).Mul(params.InflationRateChange).Quo(blocksPerYr)},

// a change from 4% to default (3%)
{sdk.NewDecWithPrec(4, 2), sdk.NewDecWithPrec(-1, 2)},
// test 7% minimum stop (testing with 100% bonded)
{sdk.OneDec(), sdk.NewDecWithPrec(7, 2), sdk.ZeroDec()},
{sdk.OneDec(), sdk.NewDecWithPrec(700000001, 10), sdk.NewDecWithPrec(-1, 10)},

// a change from 1% to default (3%)
{sdk.NewDecWithPrec(1, 2), sdk.NewDecWithPrec(2, 2)},
// test 20% maximum stop (testing with 0% bonded)
{sdk.ZeroDec(), sdk.NewDecWithPrec(20, 2), sdk.ZeroDec()},
{sdk.ZeroDec(), sdk.NewDecWithPrec(1999999999, 10), sdk.NewDecWithPrec(1, 10)},

// perfect balance shouldn't change inflation
{sdk.NewDecWithPrec(67, 2), sdk.NewDecWithPrec(15, 2), sdk.ZeroDec()},
}
for i, tc := range tests {
minter.Inflation = tc.setInflation
inflation := minter.NextInflationRate(params)

inflation := minter.NextInflationRate(params, tc.bondedRatio)
diffInflation := inflation.Sub(tc.setInflation)

require.True(t, diffInflation.Equal(tc.expChange),
Expand Down Expand Up @@ -88,10 +107,11 @@ func BenchmarkBlockProvision(b *testing.B) {
func BenchmarkNextInflation(b *testing.B) {
minter := InitialMinter(sdk.NewDecWithPrec(1, 1))
params := DefaultParams()
bondedRatio := sdk.NewDecWithPrec(1, 1)

// run the NextInflationRate function b.N times
for n := 0; n < b.N; n++ {
minter.NextInflationRate(params)
minter.NextInflationRate(params, bondedRatio)
}

}
Expand Down
108 changes: 93 additions & 15 deletions x/mint/internal/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ var (

// mint parameters
type Params struct {
MintDenom string `json:"mint_denom" yaml:"mint_denom"` // type of coin to mint
InflationRate sdk.Dec `json:"inflation_rate" yaml:"inflation_rate"` // the fixed inflation rate
BlocksPerYear uint64 `json:"blocks_per_year" yaml:"blocks_per_year"` // expected blocks per year
MintDenom string `json:"mint_denom" yaml:"mint_denom"` // type of coin to mint
InflationRateChange sdk.Dec `json:"inflation_rate_change" yaml:"inflation_rate_change"` // maximum annual change in inflation rate
InflationMax sdk.Dec `json:"inflation_max" yaml:"inflation_max"` // maximum inflation rate
InflationMin sdk.Dec `json:"inflation_min" yaml:"inflation_min"` // minimum inflation rate
GoalBonded sdk.Dec `json:"goal_bonded" yaml:"goal_bonded"` // goal of percent bonded atoms
BlocksPerYear uint64 `json:"blocks_per_year" yaml:"blocks_per_year"` // expected blocks per year
}

// ParamTable for minting module.
Expand All @@ -32,21 +35,27 @@ func ParamKeyTable() params.KeyTable {
}

func NewParams(
mintDenom string, inflationRate sdk.Dec, blocksPerYear uint64,
mintDenom string, inflationRateChange, inflationMax, inflationMin, goalBonded sdk.Dec, blocksPerYear uint64,
) Params {

return Params{
MintDenom: mintDenom,
InflationRate: inflationRate,
BlocksPerYear: blocksPerYear,
MintDenom: mintDenom,
InflationRateChange: inflationRateChange,
InflationMax: inflationMax,
InflationMin: inflationMin,
GoalBonded: goalBonded,
BlocksPerYear: blocksPerYear,
}
}

// default minting module parameters
func DefaultParams() Params {
return Params{
MintDenom: sdk.DefaultBondDenom,
InflationRate: sdk.NewDecWithPrec(3, 2),
InflationRateChange: sdk.NewDecWithPrec(13, 2),
InflationMax: sdk.NewDecWithPrec(20, 2),
InflationMin: sdk.NewDecWithPrec(7, 2),
GoalBonded: sdk.NewDecWithPrec(67, 2),
BlocksPerYear: uint64(60 * 60 * 8766 / 5), // assuming 5 second block times
}
}
Expand All @@ -56,32 +65,54 @@ func (p Params) Validate() error {
if err := validateMintDenom(p.MintDenom); err != nil {
return err
}
if err := validateInflationRate(p.InflationRate); err != nil {
if err := validateInflationRateChange(p.InflationRateChange); err != nil {
return err
}
if err := validateInflationMax(p.InflationMax); err != nil {
return err
}
if err := validateInflationMin(p.InflationMin); err != nil {
return err
}
if err := validateGoalBonded(p.GoalBonded); err != nil {
return err
}
if err := validateBlocksPerYear(p.BlocksPerYear); err != nil {
return err
}
if p.InflationMax.LT(p.InflationMin) {
return fmt.Errorf(
"max inflation (%s) must be greater than or equal to min inflation (%s)",
p.InflationMax, p.InflationMin,
)
}

return nil

}

func (p Params) String() string {
return fmt.Sprintf(`Minting Params:
Mint Denom: %s
Inflation Rate: %s
Blocks Per Year: %d
Mint Denom: %s
Inflation Rate Change: %s
Inflation Max: %s
Inflation Min: %s
Goal Bonded: %s
Blocks Per Year: %d
`,
p.MintDenom, p.InflationRate, p.BlocksPerYear,
p.MintDenom, p.InflationRateChange, p.InflationMax,
p.InflationMin, p.GoalBonded, p.BlocksPerYear,
)
}

// Implements params.ParamSet
func (p *Params) ParamSetPairs() params.ParamSetPairs {
return params.ParamSetPairs{
params.NewParamSetPair(KeyMintDenom, &p.MintDenom, validateMintDenom),
params.NewParamSetPair(KeyInflationRateChange, &p.InflationRate, validateInflationRate),
params.NewParamSetPair(KeyInflationRateChange, &p.InflationRateChange, validateInflationRateChange),
params.NewParamSetPair(KeyInflationMax, &p.InflationMax, validateInflationMax),
params.NewParamSetPair(KeyInflationMin, &p.InflationMin, validateInflationMin),
params.NewParamSetPair(KeyGoalBonded, &p.GoalBonded, validateGoalBonded),
params.NewParamSetPair(KeyBlocksPerYear, &p.BlocksPerYear, validateBlocksPerYear),
}
}
Expand All @@ -102,8 +133,23 @@ func validateMintDenom(i interface{}) error {
return nil
}

func validateInflationRateChange(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

func validateInflationRate(i interface{}) error {
if v.IsNegative() {
return fmt.Errorf("inflation rate change cannot be negative: %s", v)
}
if v.GT(sdk.OneDec()) {
return fmt.Errorf("inflation rate change too large: %s", v)
}

return nil
}

func validateInflationMax(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
Expand All @@ -119,6 +165,38 @@ func validateInflationRate(i interface{}) error {
return nil
}

func validateInflationMin(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

if v.IsNegative() {
return fmt.Errorf("min inflation cannot be negative: %s", v)
}
if v.GT(sdk.OneDec()) {
return fmt.Errorf("min inflation too large: %s", v)
}

return nil
}

func validateGoalBonded(i interface{}) error {
v, ok := i.(sdk.Dec)
if !ok {
return fmt.Errorf("invalid parameter type: %T", i)
}

if v.IsNegative() {
return fmt.Errorf("goal bonded cannot be negative: %s", v)
}
if v.GT(sdk.OneDec()) {
return fmt.Errorf("goal bonded too large: %s", v)
}

return nil
}

func validateBlocksPerYear(i interface{}) error {
v, ok := i.(uint64)
if !ok {
Expand Down
50 changes: 43 additions & 7 deletions x/mint/simulation/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ import (

// Simulation parameter constants
const (
Inflation = "inflation"
InflationRate = "inflation_rate"
Inflation = "inflation"
InflationRateChange = "inflation_rate_change"
InflationMax = "inflation_max"
InflationMin = "inflation_min"
GoalBonded = "goal_bonded"
)

// GenInflation randomized Inflation
Expand All @@ -25,10 +28,25 @@ func GenInflation(r *rand.Rand) sdk.Dec {
}

// GenInflationRateChange randomized InflationRateChange
func GenInflationRate(r *rand.Rand) sdk.Dec {
func GenInflationRateChange(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(int64(r.Intn(99)), 2)
}

// GenInflationMax randomized InflationMax
func GenInflationMax(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(20, 2)
}

// GenInflationMin randomized InflationMin
func GenInflationMin(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(7, 2)
}

// GenGoalBonded randomized GoalBonded
func GenGoalBonded(r *rand.Rand) sdk.Dec {
return sdk.NewDecWithPrec(67, 2)
}

// RandomizedGenState generates a random GenesisState for mint
func RandomizedGenState(simState *module.SimulationState) {
// minter
Expand All @@ -39,15 +57,33 @@ func RandomizedGenState(simState *module.SimulationState) {
)

// params
var inflationRate sdk.Dec
var inflationRateChange sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, InflationRateChange, &inflationRateChange, simState.Rand,
func(r *rand.Rand) { inflationRateChange = GenInflationRateChange(r) },
)

var inflationMax sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, InflationMax, &inflationMax, simState.Rand,
func(r *rand.Rand) { inflationMax = GenInflationMax(r) },
)

var inflationMin sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, InflationMin, &inflationMin, simState.Rand,
func(r *rand.Rand) { inflationMin = GenInflationMin(r) },
)

var goalBonded sdk.Dec
simState.AppParams.GetOrGenerate(
simState.Cdc, InflationRate, &inflationRate, simState.Rand,
func(r *rand.Rand) { inflationRate = GenInflationRate(r) },
simState.Cdc, GoalBonded, &goalBonded, simState.Rand,
func(r *rand.Rand) { goalBonded = GenGoalBonded(r) },
)

mintDenom := sdk.DefaultBondDenom
blocksPerYear := uint64(60 * 60 * 8766 / 5)
params := types.NewParams(mintDenom, inflationRate, blocksPerYear)
params := types.NewParams(mintDenom, inflationRateChange, inflationMax, inflationMin, goalBonded, blocksPerYear)

mintGenesis := types.NewGenesisState(types.InitialMinter(inflation), params)

Expand Down
Loading

0 comments on commit 0f89d36

Please sign in to comment.