Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(cip-29): reduce inflation #4299

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions x/mint/types/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,22 @@ const (
InitialInflationRate = 0.08
// DisinflationRate is the rate at which the inflation rate decreases each year.
DisinflationRate = 0.1
// InitialInflationRateCip29 is the inflation rate specified in CIP-29.
InitialInflationRateCip29 = 0.0536
// DisinflationRateCip29 is the rate at which the inflation rate decreases each year (after CIP-29 was introduced).
DisinflationRateCip29 = 0.067
// TargetInflationRate is the inflation rate that the network aims to
// stabilize at. In practice, TargetInflationRate acts as a minimum so that
// the inflation rate doesn't decrease after reaching it.
TargetInflationRate = 0.015
)

var (
initialInflationRateAsDec = sdk.NewDecWithPrec(InitialInflationRate*1000, 3)
disinflationRateAsDec = sdk.NewDecWithPrec(DisinflationRate*1000, 3)
targetInflationRateAsDec = sdk.NewDecWithPrec(TargetInflationRate*1000, 3)
initialInflationRateAsDec = sdk.NewDecWithPrec(InitialInflationRate*1000, 3)
initialInflationRateCip29AsDec = sdk.NewDecWithPrec(InitialInflationRateCip29*10000, 4)
disinflationRateAsDec = sdk.NewDecWithPrec(DisinflationRate*1000, 3)
disinflationRateCip29AsDec = sdk.NewDecWithPrec(DisinflationRateCip29*1000, 3)
targetInflationRateAsDec = sdk.NewDecWithPrec(TargetInflationRate*1000, 3)
)

func InitialInflationRateAsDec() sdk.Dec {
Expand All @@ -41,3 +47,11 @@ func DisinflationRateAsDec() sdk.Dec {
func TargetInflationRateAsDec() sdk.Dec {
return targetInflationRateAsDec
}

func InitialInflationRateCip29AsDec() sdk.Dec {
return initialInflationRateCip29AsDec
}

func DisinflationRateCip29AsDec() sdk.Dec {
return disinflationRateCip29AsDec
}
37 changes: 37 additions & 0 deletions x/mint/types/minter.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@
// the current block height in context. The inflation rate is expected to
// decrease every year according to the schedule specified in the README.
func (m Minter) CalculateInflationRate(ctx sdk.Context, genesis time.Time) sdk.Dec {
if ctx.ConsensusParams().Version.AppVersion <= 3 {
return calculateInflationRatePreCip29(ctx, genesis)
} else {

Check failure on line 47 in x/mint/types/minter.go

View workflow job for this annotation

GitHub Actions / lint / golangci-lint

indent-error-flow: if block ends with a return statement, so drop this else and outdent its block (revive)
return calculateInflationRatePostCip29(ctx, genesis)
}
}

func calculateInflationRatePreCip29(ctx sdk.Context, genesis time.Time) sdk.Dec {
years := yearsSinceGenesis(genesis, ctx.BlockTime())
inflationRate := InitialInflationRateAsDec().Mul(sdk.OneDec().Sub(DisinflationRateAsDec()).Power(uint64(years)))

Expand All @@ -51,6 +59,35 @@
return inflationRate
}

func calculateInflationRatePostCip29(ctx sdk.Context, genesis time.Time) sdk.Dec {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here the math is slightly off same with the code in the CIP.

Here we are not doing a reduction of the previous year inflation we are taking the original inflation rate for that year reducing it by 33% and then reducing it by 6.7%

in order to calculate the correct inflation we would need to do something like so

func calculateInflationRatePostCip29(ctx sdk.Context, genesis time.Time) sdk.Dec {
	if ctx.ConsensusParams().Version.AppVersion <= 3 {
		panic("calculateInflationRatePostCip29 should not be called with AppVersion <= 3")
	}

	years := yearsSinceGenesis(genesis, ctx.BlockTime())
	initialInflationRate := InitialInflationRateAsDec().Mul(sdk.OneDec().Sub(DisinflationRateAsDec()).Power(uint64(1)))

	updatedInflationRate := sdk.Dec{}
	// For AppVersion > 3, adjust the inflation rate:
	if ctx.ConsensusParams().Version.AppVersion > 3 {
		// First, reduce the current inflation rate by 33%
		updatedInflationRate = initialInflationRate.Mul(sdk.NewDecWithPrec(67, 2)) // 0.67 \= 67%

		// Then, if we are in year two or later, apply a one-time disinflation of 6.7%
		if years >= 2 {
			for i := 1; i < int(years); i++ {
				updatedInflationRate = updatedInflationRate.Mul(sdk.OneDec().Sub(sdk.NewDecWithPrec(67, 3))) // 1 \- 0.067 \= 0.933
			}
		}
	}

	// Ensure the inflation rate does not fall below the target inflation rate.
	if updatedInflationRate.LT(TargetInflationRateAsDec()) {
		return TargetInflationRateAsDec()
	}

	return updatedInflationRate
}

the code isnt the nicest, would be happy to simplify and change the numbers as they are not that far off.

if ctx.ConsensusParams().Version.AppVersion <= 3 {
panic("calculateInflationRatePostCip29 should not be called with AppVersion <= 3")
}

years := yearsSinceGenesis(genesis, ctx.BlockTime())

// Default inflation calculation
inflationRate := InitialInflationRateAsDec().Mul(sdk.OneDec().Sub(DisinflationRateAsDec()).Power(uint64(years)))

// For AppVersion > 3, adjust the inflation rate:
if ctx.ConsensusParams().Version.AppVersion > 3 {
// First, reduce the current inflation rate by 33%
inflationRate = inflationRate.Mul(sdk.NewDecWithPrec(67, 2)) // 0.67 \= 67%

// Then, if we are in year two or later, apply a one-time disinflation of 6.7%
if years >= 2 {
inflationRate = inflationRate.Mul(sdk.OneDec().Sub(sdk.NewDecWithPrec(67, 3))) // 1 \- 0.067 \= 0.933
}
}

// Ensure the inflation rate does not fall below the target inflation rate.
if inflationRate.LT(TargetInflationRateAsDec()) {
return TargetInflationRateAsDec()
}

return inflationRate
}

// CalculateBlockProvision returns the total number of coins that should be
// minted due to inflation for the current block.
func (m Minter) CalculateBlockProvision(current time.Time, previous time.Time) (sdk.Coin, error) {
Expand Down
145 changes: 87 additions & 58 deletions x/mint/types/minter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,71 +9,100 @@ import (
"github.com/stretchr/testify/require"

sdk "github.com/cosmos/cosmos-sdk/types"
abcitypes "github.com/tendermint/tendermint/abci/types"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
)

func TestCalculateInflationRate(t *testing.T) {
minter := DefaultMinter()
genesisTime := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
t.Run("app version 3", func(t *testing.T) {
minter := DefaultMinter()
genesisTime := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)

type testCase struct {
year int64
want float64
}
type testCase struct {
year int64
want float64
}

testCases := []testCase{
{0, 0.08},
{1, 0.072},
{2, 0.0648},
{3, 0.05832},
{4, 0.052488},
{5, 0.0472392},
{6, 0.04251528},
{7, 0.038263752},
{8, 0.0344373768},
{9, 0.03099363912},
{10, 0.027894275208},
{11, 0.0251048476872},
{12, 0.02259436291848},
{13, 0.020334926626632},
{14, 0.0183014339639688},
{15, 0.01647129056757192},
{16, 0.0150},
{17, 0.0150},
{18, 0.0150},
{19, 0.0150},
{20, 0.0150},
{21, 0.0150},
{22, 0.0150},
{23, 0.0150},
{24, 0.0150},
{25, 0.0150},
{26, 0.0150},
{27, 0.0150},
{28, 0.0150},
{29, 0.0150},
{30, 0.0150},
{31, 0.0150},
{32, 0.0150},
{33, 0.0150},
{34, 0.0150},
{35, 0.0150},
{36, 0.0150},
{37, 0.0150},
{38, 0.0150},
{39, 0.0150},
{40, 0.0150},
}
testCases := []testCase{
{0, 0.08},
{1, 0.072},
{2, 0.0648},
{3, 0.05832},
{4, 0.052488},
{5, 0.0472392},
{6, 0.04251528},
{7, 0.038263752},
{8, 0.0344373768},
{9, 0.03099363912},
{10, 0.027894275208},
{11, 0.0251048476872},
{12, 0.02259436291848},
{13, 0.020334926626632},
{14, 0.0183014339639688},
{15, 0.01647129056757192},
{16, 0.0150},
{17, 0.0150},
{18, 0.0150},
{19, 0.0150},
{20, 0.0150},
{21, 0.0150},
{22, 0.0150},
{23, 0.0150},
{24, 0.0150},
{25, 0.0150},
{26, 0.0150},
{27, 0.0150},
{28, 0.0150},
{29, 0.0150},
{30, 0.0150},
{31, 0.0150},
{32, 0.0150},
{33, 0.0150},
{34, 0.0150},
{35, 0.0150},
{36, 0.0150},
{37, 0.0150},
{38, 0.0150},
{39, 0.0150},
{40, 0.0150},
}

for _, tc := range testCases {
years := time.Duration(tc.year * NanosecondsPerYear * int64(time.Nanosecond))
blockTime := genesisTime.Add(years)
ctx := sdk.NewContext(nil, tmproto.Header{}, false, nil).WithBlockTime(blockTime)
inflationRate := minter.CalculateInflationRate(ctx, genesisTime)
got, err := inflationRate.Float64()
assert.NoError(t, err)
assert.Equal(t, tc.want, got, "want %v got %v year %v blockTime %v", tc.want, got, tc.year, blockTime)
}
for _, tc := range testCases {
years := time.Duration(tc.year * NanosecondsPerYear * int64(time.Nanosecond))
blockTime := genesisTime.Add(years)
ctx := sdk.NewContext(nil, tmproto.Header{}, false, nil).WithBlockTime(blockTime).WithConsensusParams(&abcitypes.ConsensusParams{Version: &tmproto.VersionParams{AppVersion: 3}})
inflationRate := minter.CalculateInflationRate(ctx, genesisTime)
got, err := inflationRate.Float64()
assert.NoError(t, err)
assert.Equal(t, tc.want, got, "want %v got %v year %v blockTime %v", tc.want, got, tc.year, blockTime)
}
})
t.Run("app version 4", func(t *testing.T) {
minter := DefaultMinter()
genesisTime := time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)

type testCase struct {
year int64
want float64
}

testCases := []testCase{
{0, 0.0536}, // note this value won't be used in production because celestia-app was on app version 3 in year 0.
{1, 0.04824},
{2, 0.040507128},
{3, 0.0364564152},
}

for _, tc := range testCases {
years := time.Duration(tc.year * NanosecondsPerYear * int64(time.Nanosecond))
blockTime := genesisTime.Add(years)
ctx := sdk.NewContext(nil, tmproto.Header{}, false, nil).WithBlockTime(blockTime).WithConsensusParams(&abcitypes.ConsensusParams{Version: &tmproto.VersionParams{AppVersion: 4}})
inflationRate := minter.CalculateInflationRate(ctx, genesisTime)
got, err := inflationRate.Float64()
assert.NoError(t, err)
assert.Equal(t, tc.want, got, "want %v got %v year %v blockTime %v", tc.want, got, tc.year, blockTime)
}
})
}

func TestCalculateBlockProvision(t *testing.T) {
Expand Down
Loading