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: x/mint/types #322

Merged
merged 7 commits into from
Mar 1, 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
2 changes: 1 addition & 1 deletion x/mint/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ func ExportGenesis(ctx sdk.Context, keeper keeper.Keeper) *types.GenesisState {
minter := keeper.GetMinter(ctx)
params := keeper.GetParams(ctx)
lastReductionEpoch := keeper.GetLastReductionEpochNum(ctx)
return types.NewGenesisState(minter, params, lastReductionEpoch)
return types.NewGenesis(minter, params, lastReductionEpoch)
}
8 changes: 4 additions & 4 deletions x/mint/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ func (b AppModuleBasic) RegisterInterfaces(_ cdctypes.InterfaceRegistry) {}
// DefaultGenesis returns default genesis state as raw bytes for the mint
// module.
func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
return cdc.MustMarshalJSON(types.DefaultGenesisState())
return cdc.MustMarshalJSON(types.DefaultGenesis())
}

// ValidateGenesis performs genesis state validation for the mint module.
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error {
var data types.GenesisState
if err := cdc.UnmarshalJSON(bz, &data); err != nil {
var gs types.GenesisState
if err := cdc.UnmarshalJSON(bz, &gs); err != nil {
return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err)
}

return types.ValidateGenesis(data)
return gs.Validate()
}

// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the mint module.
Expand Down
26 changes: 13 additions & 13 deletions x/mint/types/genesis.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
package types

// NewGenesisState creates a new GenesisState object.
func NewGenesisState(minter Minter, params Params, reductionStartedEpoch int64) *GenesisState {
// NewGenesis creates a new Genesis object.
func NewGenesis(minter Minter, params Params, reductionStartedEpoch int64) *GenesisState {
return &GenesisState{
Minter: minter,
Params: params,
ReductionStartedEpoch: reductionStartedEpoch,
}
}

// DefaultGenesisState creates a default GenesisState object.
func DefaultGenesisState() *GenesisState {
return &GenesisState{
Minter: DefaultInitialMinter(),
Params: DefaultParams(),
ReductionStartedEpoch: 0,
}
// DefaultGenesis creates a default GenesisState object.
func DefaultGenesis() *GenesisState {
return NewGenesis(
DefaultInitialMinter(),
DefaultParams(),
0,
)
}

// ValidateGenesis validates the provided genesis state to ensure the
// Validate validates the provided genesis state to ensure the
// expected invariants holds.
func ValidateGenesis(data GenesisState) error {
if err := data.Params.Validate(); err != nil {
func (gs GenesisState) Validate() error {
if err := gs.Params.Validate(); err != nil {
return err
}

return ValidateMinter(data.Minter)
return gs.Minter.Validate()
}
50 changes: 50 additions & 0 deletions x/mint/types/genesis_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package types_test

import (
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"

"github.com/ingenuity-build/quicksilver/x/mint/types"
)

func TestGenesisValidate(t *testing.T) {
invalidParams := types.DefaultGenesis()
invalidParams.Params.MintDenom = "" // cannot be empty

invalidMinter := types.DefaultGenesis()
invalidMinter.Minter.EpochProvisions = sdk.NewDec(-1) // cannot be empty

tests := []struct {
name string
genesis *types.GenesisState
isValid bool
}{
{
name: "valid genesis",
genesis: types.DefaultGenesis(),
isValid: true,
},
{
name: "invalid params",
genesis: invalidParams,
isValid: false,
},
{
name: "invalid minter",
genesis: invalidMinter,
isValid: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
err := tc.genesis.Validate()
if !tc.isValid {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}
18 changes: 16 additions & 2 deletions x/mint/types/minter.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package types

import (
"errors"

sdk "github.com/cosmos/cosmos-sdk/types"
)

var (
errNilEpochProvisions = errors.New("epoch provisions was nil in genesis")
errNegativeEpochProvisions = errors.New("epoch provisions should be non-negative")
)

// NewMinter returns a new Minter object with the given epoch
// provisions values.
func NewMinter(epochProvisions sdk.Dec) Minter {
Expand All @@ -22,8 +29,15 @@ func DefaultInitialMinter() Minter {
return InitialMinter()
}

// validate minter.
func ValidateMinter(minter Minter) error {
// Validate checks if minter epoch provisions are valid.
func (m Minter) Validate() error {
if m.EpochProvisions.IsNil() {
return errNilEpochProvisions
}

if m.EpochProvisions.IsNegative() {
return errNegativeEpochProvisions
}
return nil
}

Expand Down
60 changes: 55 additions & 5 deletions x/mint/types/minter_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package types
package types_test

import (
"math/rand"
"testing"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"

"github.com/ingenuity-build/quicksilver/x/mint/types"
)

// Benchmarking :)
Expand All @@ -15,8 +18,8 @@ import (
// BenchmarkEpochProvision-4 3000000 429 ns/op
func BenchmarkEpochProvision(b *testing.B) {
b.ReportAllocs()
minter := InitialMinter()
params := DefaultParams()
minter := types.InitialMinter()
params := types.DefaultParams()

s1 := rand.NewSource(100)
r1 := rand.New(s1)
Expand All @@ -32,11 +35,58 @@ func BenchmarkEpochProvision(b *testing.B) {
// BenchmarkNextEpochProvisions-4 5000000 251 ns/op
func BenchmarkNextEpochProvisions(b *testing.B) {
b.ReportAllocs()
minter := InitialMinter()
params := DefaultParams()
minter := types.InitialMinter()
params := types.DefaultParams()

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

func TestEpochProvision(t *testing.T) {
params := types.DefaultParams()
minter := types.DefaultInitialMinter()
minter.EpochProvisions = sdk.NewDecWithPrec(75, 2)

actual := minter.NextEpochProvisions(params)
require.Equal(t, sdk.NewDecWithPrec(5625, 4), actual)
require.Equal(t, sdk.NewCoin(params.MintDenom, actual.TruncateInt()), minter.EpochProvision(params))
}

func TestMinterValidate(t *testing.T) {
testcases := []struct {
name string
minter types.Minter
isValid bool
}{
{
"valid",
types.InitialMinter(),
true,
},
{
"negative",
types.Minter{
EpochProvisions: sdk.NewDec(-1),
},
false,
},
{
"nil",
types.Minter{},
false,
},
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
err := tc.minter.Validate()
if !tc.isValid {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}
41 changes: 21 additions & 20 deletions x/mint/types/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import (
"fmt"
"strings"

sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
yaml "gopkg.in/yaml.v2"

epochtypes "github.com/ingenuity-build/quicksilver/x/epochs/types"

sdk "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
)

// Parameter store keys.
Expand All @@ -21,19 +20,18 @@ var (
KeyReductionPeriodInEpochs = []byte("ReductionPeriodInEpochs")
KeyReductionFactor = []byte("ReductionFactor")
KeyPoolAllocationRatio = []byte("PoolAllocationRatio")
KeyDeveloperRewardsReceiver = []byte("DeveloperRewardsReceiver")
KeyMintingRewardsDistributionStartEpoch = []byte("MintingRewardsDistributionStartEpoch")
)

// ParamTable for minting module.
// ParamKeyTable returns ParamTable for minting module.
func ParamKeyTable() paramtypes.KeyTable {
return paramtypes.NewKeyTable().RegisterParamSet(&Params{})
}

func NewParams(
mintDenom string, genesisEpochProvisions sdk.Dec, epochIdentifier string,
reductionFactor sdk.Dec, reductionPeriodInEpochs int64, distrProportions DistributionProportions,
mintingRewardsDistributionStartEpoch int64,
reductionPeriodInEpochs int64, reductionFactor sdk.Dec,
distrProportions DistributionProportions, mintingRewardsDistributionStartEpoch int64,
) Params {
return Params{
MintDenom: mintDenom,
Expand All @@ -46,22 +44,22 @@ func NewParams(
}
}

// default minting module parameters.
// DefaultParams returns default minting module parameters.
func DefaultParams() Params {
return Params{
MintDenom: sdk.DefaultBondDenom,
GenesisEpochProvisions: sdk.NewDec(200000000 / 122),
EpochIdentifier: "day", // 1 day
ReductionPeriodInEpochs: 365, // 1 years
ReductionFactor: sdk.NewDecWithPrec(75, 2), // 0.75
DistributionProportions: DistributionProportions{
return NewParams(
sdk.DefaultBondDenom,
sdk.NewDec(200000000/122),
"day",
365,
sdk.NewDecWithPrec(75, 2),
DistributionProportions{
Staking: sdk.NewDecWithPrec(3, 1), // 0.3
PoolIncentives: sdk.NewDecWithPrec(3, 1), // 0.3
ParticipationRewards: sdk.NewDecWithPrec(3, 1), // 0.3
CommunityPool: sdk.NewDecWithPrec(1, 1), // 0.1
},
MintingRewardsDistributionStartEpoch: 0,
}
0,
)
}

// validate params.
Expand Down Expand Up @@ -158,7 +156,7 @@ func validateReductionFactor(i interface{}) error {
return fmt.Errorf("invalid parameter type: %T", i)
}

if v.GT(sdk.NewDec(1)) {
if v.GT(sdk.OneDec()) {
return errors.New("reduction factor cannot be greater than 1")
}

Expand All @@ -183,13 +181,16 @@ func validateDistributionProportions(i interface{}) error {
return errors.New("pool incentives distribution ratio should not be negative")
}

if v.ParticipationRewards.IsNegative() {
return errors.New("participation rewards distribution ratio should not be negative")
}

if v.CommunityPool.IsNegative() {
return errors.New("community pool distribution ratio should not be negative")
}

totalProportions := v.Staking.Add(v.PoolIncentives).Add(v.CommunityPool).Add(v.ParticipationRewards)

if !totalProportions.Equal(sdk.NewDec(1)) {
if !totalProportions.Equal(sdk.OneDec()) {
return errors.New("total distributions ratio should be 1")
}

Expand Down
Loading