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

tests: inflation rate change #2236

Merged
merged 3 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
10 changes: 8 additions & 2 deletions app/inflation/inflation.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ func (c Calculator) InflationRate(ctx sdk.Context, minter minttypes.Minter, mint
factor := bpmath.One - inflationParams.InflationReductionRate
mintParams.InflationMax = factor.MulDec(mintParams.InflationMax)
mintParams.InflationMin = factor.MulDec(mintParams.InflationMin)
// inflation rate change = (max rate - min rate) / 6months
mintParams.InflationRateChange = sdk.NewDec(2).Mul(mintParams.InflationMax.Sub(mintParams.InflationMin))
mintParams.InflationRateChange = fastInflationRateChange(mintParams)
c.MintKeeper.SetParams(ctx, mintParams)

err := ugovKeeper.SetInflationCycleEnd(ctx.BlockTime().Add(inflationParams.InflationCycle))
Expand All @@ -50,6 +49,13 @@ func (c Calculator) InflationRate(ctx sdk.Context, minter minttypes.Minter, mint
return c.AdjustInflation(stakingTokenSupply, inflationParams.MaxSupply.Amount, minter, mintParams)
}

var two = sdk.NewDec(2)

// inflation rate change = (max_rate - min_rate) * 2
func fastInflationRateChange(p minttypes.Params) sdk.Dec {
return two.Mul(p.InflationMax.Sub(p.InflationMin))
}

// AdjustInflation checks if newly minting coins will execeed the MaxSupply then it will adjust the inflation with
// respect to MaxSupply
func (c Calculator) AdjustInflation(stakingTokenSupply, maxSupply math.Int, minter minttypes.Minter,
Expand Down
145 changes: 93 additions & 52 deletions app/inflation/inflation_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package inflation_test
package inflation

import (
"testing"
Expand All @@ -11,11 +11,11 @@ import (
"github.com/golang/mock/gomock"
"gotest.tools/v3/assert"

"github.com/umee-network/umee/v6/app/inflation"
mocks "github.com/umee-network/umee/v6/app/inflation/mocks"
appparams "github.com/umee-network/umee/v6/app/params"
"github.com/umee-network/umee/v6/tests/tsdk"
"github.com/umee-network/umee/v6/util/bpmath"
"github.com/umee-network/umee/v6/util/checkers"
"github.com/umee-network/umee/v6/util/coin"
"github.com/umee-network/umee/v6/x/ugov"
ugovmocks "github.com/umee-network/umee/v6/x/ugov/mocks"
Expand Down Expand Up @@ -66,7 +66,7 @@ func TestAdjustInflation(t *testing.T) {

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
calc := inflation.Calculator{}
calc := Calculator{}
mintParams := test.params(mintParams)
result := calc.AdjustInflation(test.totalSupply, test.maxSupply, test.minter, mintParams)

Expand Down Expand Up @@ -216,7 +216,7 @@ func TestInflationRate(t *testing.T) {
mockUGovKeeper.EXPECT().InflationCycleEnd().Return(test.cycleEndTime()).AnyTimes()
mockUGovKeeper.EXPECT().SetInflationCycleEnd(gomock.Any()).Return(nil).AnyTimes()

calc := inflation.Calculator{
calc := Calculator{
MintKeeper: mockMintKeeper,
UgovKeeperB: ugovmocks.NewParamsBuilder(mockUGovKeeper),
}
Expand All @@ -229,65 +229,106 @@ func TestInflationRate(t *testing.T) {
}
}

func TestNextInflationRate(t *testing.T) {
minter := minttypes.Minter{
Inflation: sdk.NewDecWithPrec(0, 2),
func TestInflationRateChange(t *testing.T) {
bondedRatio := sdk.NewDecWithPrec(1, 1) // 10% -> below the goal
mparamsStd := minttypes.Params{ // minting params for a standard x/mint minting process
MintDenom: sdk.DefaultBondDenom,
InflationMax: sdk.NewDecWithPrec(5, 1), // 0.5
InflationMin: sdk.NewDecWithPrec(1, 1), // 0.1
GoalBonded: sdk.NewDecWithPrec(5, 1), // 0.5
BlocksPerYear: 5 * 60 * 24 * 365, // 1 block per 6s => 5 blocks per min.
}
mparamsFast := mparamsStd // minting params for the umee inflation calculator
mparamsFast.InflationRateChange = fastInflationRateChange(mparamsFast)
mparamsStd.InflationRateChange = mparamsFast.InflationRateChange.Quo(two)
minterFast := minttypes.Minter{
Inflation: sdk.NewDecWithPrec(1, 2), // 0.01 -- less than InflationMin
}
minterStd := minterFast

mintParams := minttypes.DefaultParams()
mintParams.InflationMax = sdk.NewDecWithPrec(40, 2)
mintParams.InflationMin = sdk.NewDecWithPrec(1, 2)
mintParams.InflationRateChange = sdk.NewDec(1)
mintParams.BlocksPerYear = 100
mintParams.GoalBonded = sdk.NewDec(33)
//
// Test1: inflation rate should jump to InflationMin in the first round.
//
ir := minterFast.NextInflationRate(mparamsFast, bondedRatio)
assert.Equal(t, ir, mparamsFast.InflationMin, "initial rate should immediately adjust to InflationMin")

bondedRatio := sdk.NewDec(20)
//
// Test2
// in half a year inflation should go from 0 towards max. Note: with the existing Cosmos SDK
// algorithm, we won't reach max. So we compare our settings with the standard minter, and check
// if it's almost the same.
//

// default inflation rate (1 year inflation rate change speed )
ir := minter.NextInflationRate(mintParams, bondedRatio)
assert.DeepEqual(t, mintParams.InflationMin, ir)
// in 5 months, the fast minter should not reach the max.
month := int(mparamsFast.BlocksPerYear / 12)
for i := 0; i <= month*5; i++ {
minterFast.Inflation = minterFast.NextInflationRate(mparamsFast, bondedRatio)
}
assert.Assert(t, minterFast.Inflation.LT(mparamsFast.InflationMax), "current: %v", minterFast.Inflation)

// changing inflation rate speed from 1 year to 6 months
mintParams.BlocksPerYear = mintParams.BlocksPerYear * 2
nir := minter.NextInflationRate(mintParams, bondedRatio)
// we should get similar result to the standard minter after 10 months
for i := 0; i <= month*10; i++ {
minterStd.Inflation = minterStd.NextInflationRate(mparamsStd, bondedRatio)
}

assert.DeepEqual(t, mintParams.InflationMin, nir)
}
checkers.RequireDecMaxDiff(t, minterStd.Inflation, minterFast.Inflation, sdk.NewDecWithPrec(1, 5),
"fast minter and standard minter should end up with similar inflation change after 5months and 10months repectively")

func TestInflationRateChange(t *testing.T) {
minter := minttypes.Minter{
Inflation: sdk.NewDecWithPrec(0, 2),
// continue one more month
for i := 0; i <= month; i++ {
minterFast.Inflation = minterFast.NextInflationRate(mparamsFast, bondedRatio)
}
checkers.RequireDecMaxDiff(t, mparamsFast.InflationMax, minterFast.Inflation,
mparamsFast.InflationRateChange.QuoInt64(10),
"fast minter, afer 6 months should go close enough to max")

mintParams := minttypes.DefaultParams()
mintParams.InflationMax = sdk.NewDecWithPrec(5, 1) // 0.5
mintParams.InflationMin = sdk.NewDecWithPrec(2, 2) // 0.02
mintParams.InflationRateChange = sdk.NewDec(1) // will be overwritten in the `NextInflationRate`
mintParams.BlocksPerYear = 100
//
// test3, let's see with smaller min and max.
//
mparamsFast.InflationMin = sdk.NewDecWithPrec(3, 2) // 0.03
mparamsFast.InflationMax = sdk.NewDecWithPrec(7, 2) // 0.07
minterFast.Inflation = sdk.NewDecWithPrec(1, 2) // 0.01
for i := 0; i <= month*6; i++ {
minterFast.Inflation = minterFast.NextInflationRate(mparamsFast, bondedRatio)
}
checkers.RequireDecMaxDiff(t, mparamsFast.InflationMax, minterFast.Inflation,
mparamsFast.InflationRateChange.QuoInt64(10),
"fast minter, afer 6 months should go close enough to max")

//
// test 4 check going from max towards min
//
bondedRatio = sdk.NewDecWithPrec(9, 1) // 0.7
minterFast.Inflation = sdk.NewDecWithPrec(9, 1) // 0.9
mparamsFast.InflationRateChange = fastInflationRateChange(mparamsFast)

ir = minterFast.NextInflationRate(mparamsFast, bondedRatio)
assert.Equal(t, ir, mparamsFast.InflationMax, "initial rate should immediately adjust to InflationMin")

// in 5 months, the fast minter should not reach the min.
for i := 0; i <= month*5; i++ {
minterFast.Inflation = minterFast.NextInflationRate(mparamsFast, bondedRatio)
}
assert.Assert(t, minterFast.Inflation.GT(mparamsFast.InflationMin), "current: %v", minterFast.Inflation)

bondedRatio := sdk.NewDecWithPrec(1, 2)
// after 50 blocks (half the year) inflation will be updated
// every block, inflation = prevInflation + currentInflationRateChange
var ir sdk.Dec
ir = minter.NextInflationRate(mintParams, bondedRatio)
// at initial based on bondedRatio and GoalBonded , the inflation will be at mintParams.InflationMin
assert.Equal(t, ir, mintParams.InflationMin)
for i := 0; i < 50; i++ {
ir = minter.NextInflationRate(mintParams, bondedRatio)
minter.Inflation = ir
// continue one more month
for i := 0; i <= month; i++ {
minterFast.Inflation = minterFast.NextInflationRate(mparamsFast, bondedRatio)
}
// current inflation after the 50 blocks will be increased to MaxInflationRate
nir := minter.NextInflationRate(mintParams, bondedRatio)
assert.Equal(t, nir, mintParams.InflationMax)
checkers.RequireDecMaxDiff(t, mparamsFast.InflationMin, minterFast.Inflation,
mparamsFast.InflationRateChange.QuoInt64(10),
"fast minter, afer 6 months should go close enough to min")

// current bonded ratio =1 then inflation rate change per year will be negative
// so after the 50 blocks inflation will be minimum
minter.Inflation = sdk.NewDecWithPrec(2, 2)
bondedRatio = sdk.NewDec(1)
for i := 0; i < 50; i++ {
ir = minter.NextInflationRate(mintParams, bondedRatio)
minter.Inflation = ir
//
// test 5, when bondedRatio is closer to the goal bonded we should still go fast.
//
bondedRatio = sdk.NewDecWithPrec(7, 1) // 0.7
minterFast.Inflation = sdk.NewDecWithPrec(9, 1) // 0.9
// continue one more month
for i := 0; i <= month*6; i++ {
minterFast.Inflation = minterFast.NextInflationRate(mparamsFast, bondedRatio)
}
// it should be minimum , because inflationRateChangePerYear will be negative
assert.Equal(t, ir, mintParams.InflationMin)
checkers.RequireDecMaxDiff(t, mparamsFast.InflationMin, minterFast.Inflation,
mparamsFast.InflationRateChange.QuoInt64(3), // TODO: the diff should be smaller, but it will require to change the standard cosmos infation rate algorithm
"fast minter, afer 6 months should go close enough to min")
}
7 changes: 7 additions & 0 deletions util/checkers/number.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package checkers

import (
"fmt"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"golang.org/x/exp/constraints"
)

Expand Down Expand Up @@ -33,6 +35,11 @@ func DecMaxDiff(a, b, maxDiff sdk.Dec, note string) error {
return nil
}

func RequireDecMaxDiff(t *testing.T, a, b, maxDiff sdk.Dec, note string) {
err := DecMaxDiff(a, b, maxDiff, note)
require.NoError(t, err)
}

// DecInZeroOne asserts that 0 <= a <= 1 when oneInclusive=True, otherwise asserts
// 0 <= a < 1
func DecInZeroOne(a sdk.Dec, name string, oneInclusive bool) error {
Expand Down