mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 04:47:27 +00:00 
			
		
		
		
	Add Init/ExportGenesis for Earn module (#1280)
* Add vault and vault shares to genesis * Fix error and denoms * Update init and export genesis with correct data * Fix total supply genesis check, remove legacy test for enum errors * Add vault slice validate tests * Update denom validation, add additional test
This commit is contained in:
		
							parent
							
								
									82e2f26e14
								
							
						
					
					
						commit
						ed9991d44a
					
				@ -10,16 +10,54 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// InitGenesis initializes genesis state
 | 
			
		||||
func InitGenesis(ctx sdk.Context, k keeper.Keeper, ak types.AccountKeeper, gs types.GenesisState) {
 | 
			
		||||
func InitGenesis(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	k keeper.Keeper,
 | 
			
		||||
	ak types.AccountKeeper,
 | 
			
		||||
	gs types.GenesisState,
 | 
			
		||||
) {
 | 
			
		||||
	if err := gs.Validate(); err != nil {
 | 
			
		||||
		panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Total of all vault share records, vault record total supply should equal this
 | 
			
		||||
	vaultTotalSupplies := sdk.NewCoins()
 | 
			
		||||
 | 
			
		||||
	for _, vaultShareRecord := range gs.VaultShareRecords {
 | 
			
		||||
		if err := vaultShareRecord.Validate(); err != nil {
 | 
			
		||||
			panic(fmt.Sprintf("invalid vault share: %s", err))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		vaultTotalSupplies = vaultTotalSupplies.Add(vaultShareRecord.AmountSupplied...)
 | 
			
		||||
 | 
			
		||||
		k.SetVaultShareRecord(ctx, vaultShareRecord)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, vaultRecord := range gs.VaultRecords {
 | 
			
		||||
		if err := vaultRecord.Validate(); err != nil {
 | 
			
		||||
			panic(fmt.Sprintf("invalid vault record: %s", err))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !vaultRecord.TotalSupply.Amount.Equal(vaultTotalSupplies.AmountOf(vaultRecord.Denom)) {
 | 
			
		||||
			panic(fmt.Sprintf(
 | 
			
		||||
				"invalid vault record total supply for %s, got %s but sum of vault shares is %s",
 | 
			
		||||
				vaultRecord.Denom,
 | 
			
		||||
				vaultRecord.TotalSupply.Amount,
 | 
			
		||||
				vaultTotalSupplies.AmountOf(vaultRecord.Denom),
 | 
			
		||||
			))
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		k.SetVaultRecord(ctx, vaultRecord)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	k.SetParams(ctx, gs.Params)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ExportGenesis returns a GenesisState for a given context and keeper
 | 
			
		||||
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
 | 
			
		||||
	params := k.GetParams(ctx)
 | 
			
		||||
	return types.NewGenesisState(params)
 | 
			
		||||
	vaultRecords := k.GetAllVaultRecords(ctx)
 | 
			
		||||
	vaultShareRecords := k.GetAllVaultShareRecords(ctx)
 | 
			
		||||
 | 
			
		||||
	return types.NewGenesisState(params, vaultRecords, vaultShareRecords)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										145
									
								
								x/earn/genesis_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								x/earn/genesis_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,145 @@
 | 
			
		||||
package earn_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/testutil"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
	"github.com/stretchr/testify/suite"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type genesisTestSuite struct {
 | 
			
		||||
	testutil.Suite
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *genesisTestSuite) Test_InitGenesis_ValidationPanic() {
 | 
			
		||||
	invalidState := types.NewGenesisState(
 | 
			
		||||
		types.Params{
 | 
			
		||||
			AllowedVaults: types.AllowedVaults{
 | 
			
		||||
				types.NewAllowedVault("usdx", types.STRATEGY_TYPE_HARD),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultRecords{
 | 
			
		||||
			{
 | 
			
		||||
				Denom:       "",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultShareRecords{},
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	suite.Panics(func() {
 | 
			
		||||
		earn.InitGenesis(suite.Ctx, suite.Keeper, suite.AccountKeeper, invalidState)
 | 
			
		||||
	}, "expected init genesis to panic with invalid state")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *genesisTestSuite) Test_InitAndExportGenesis() {
 | 
			
		||||
	depositor_1, err := sdk.AccAddressFromBech32("kava1esagqd83rhqdtpy5sxhklaxgn58k2m3s3mnpea")
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	depositor_2, err := sdk.AccAddressFromBech32("kava1mq9qxlhze029lm0frzw2xr6hem8c3k9ts54w0w")
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// slices are sorted by key as stored in the data store, so init and export can be compared with equal
 | 
			
		||||
	state := types.NewGenesisState(
 | 
			
		||||
		types.Params{
 | 
			
		||||
			AllowedVaults: types.AllowedVaults{
 | 
			
		||||
				types.NewAllowedVault("usdx", types.STRATEGY_TYPE_HARD),
 | 
			
		||||
				types.NewAllowedVault("ukava", types.STRATEGY_TYPE_SAVINGS),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultRecords{
 | 
			
		||||
			types.VaultRecord{
 | 
			
		||||
				Denom:       "ukava",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("ukava", 2000000),
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultRecord{
 | 
			
		||||
				Denom:       "usdx",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("usdx", 1000000),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultShareRecords{
 | 
			
		||||
			types.VaultShareRecord{
 | 
			
		||||
				Depositor:      depositor_1,
 | 
			
		||||
				AmountSupplied: sdk.NewCoins(sdk.NewInt64Coin("usdx", 500000), sdk.NewInt64Coin("ukava", 1900000)),
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShareRecord{
 | 
			
		||||
				Depositor:      depositor_2,
 | 
			
		||||
				AmountSupplied: sdk.NewCoins(sdk.NewInt64Coin("usdx", 500000), sdk.NewInt64Coin("ukava", 100000)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	earn.InitGenesis(suite.Ctx, suite.Keeper, suite.AccountKeeper, state)
 | 
			
		||||
	suite.Equal(state.Params, suite.Keeper.GetParams(suite.Ctx))
 | 
			
		||||
 | 
			
		||||
	vaultRecord1, _ := suite.Keeper.GetVaultRecord(suite.Ctx, "ukava")
 | 
			
		||||
	vaultRecord2, _ := suite.Keeper.GetVaultRecord(suite.Ctx, "usdx")
 | 
			
		||||
	suite.Equal(state.VaultRecords[0], vaultRecord1)
 | 
			
		||||
	suite.Equal(state.VaultRecords[1], vaultRecord2)
 | 
			
		||||
 | 
			
		||||
	shareRecord1, _ := suite.Keeper.GetVaultShareRecord(suite.Ctx, depositor_1)
 | 
			
		||||
	shareRecord2, _ := suite.Keeper.GetVaultShareRecord(suite.Ctx, depositor_2)
 | 
			
		||||
 | 
			
		||||
	suite.Equal(state.VaultShareRecords[0], shareRecord1)
 | 
			
		||||
	suite.Equal(state.VaultShareRecords[1], shareRecord2)
 | 
			
		||||
 | 
			
		||||
	exportedState := earn.ExportGenesis(suite.Ctx, suite.Keeper)
 | 
			
		||||
	suite.Equal(state, exportedState)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (suite *genesisTestSuite) Test_Marshall() {
 | 
			
		||||
	depositor_1, err := sdk.AccAddressFromBech32("kava1esagqd83rhqdtpy5sxhklaxgn58k2m3s3mnpea")
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
	depositor_2, err := sdk.AccAddressFromBech32("kava1mq9qxlhze029lm0frzw2xr6hem8c3k9ts54w0w")
 | 
			
		||||
	suite.Require().NoError(err)
 | 
			
		||||
 | 
			
		||||
	// slices are sorted by key as stored in the data store, so init and export can be compared with equal
 | 
			
		||||
	state := types.NewGenesisState(
 | 
			
		||||
		types.Params{
 | 
			
		||||
			AllowedVaults: types.AllowedVaults{
 | 
			
		||||
				types.NewAllowedVault("usdx", types.STRATEGY_TYPE_HARD),
 | 
			
		||||
				types.NewAllowedVault("ukava", types.STRATEGY_TYPE_SAVINGS),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultRecords{
 | 
			
		||||
			types.VaultRecord{
 | 
			
		||||
				Denom:       "ukava",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("ukava", 2000000),
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultRecord{
 | 
			
		||||
				Denom:       "usdx",
 | 
			
		||||
				TotalSupply: sdk.NewInt64Coin("usdx", 1000000),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		types.VaultShareRecords{
 | 
			
		||||
			types.VaultShareRecord{
 | 
			
		||||
				Depositor:      depositor_1,
 | 
			
		||||
				AmountSupplied: sdk.NewCoins(sdk.NewInt64Coin("usdx", 500000), sdk.NewInt64Coin("ukava", 1900000)),
 | 
			
		||||
			},
 | 
			
		||||
			types.VaultShareRecord{
 | 
			
		||||
				Depositor:      depositor_2,
 | 
			
		||||
				AmountSupplied: sdk.NewCoins(sdk.NewInt64Coin("usdx", 500000), sdk.NewInt64Coin("ukava", 100000)),
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	encodingCfg := app.MakeEncodingConfig()
 | 
			
		||||
	cdc := encodingCfg.Marshaler
 | 
			
		||||
 | 
			
		||||
	bz, err := cdc.Marshal(&state)
 | 
			
		||||
	suite.Require().NoError(err, "expected genesis state to marshal without error")
 | 
			
		||||
 | 
			
		||||
	var decodedState types.GenesisState
 | 
			
		||||
	err = cdc.Unmarshal(bz, &decodedState)
 | 
			
		||||
	suite.Require().NoError(err, "expected genesis state to unmarshal without error")
 | 
			
		||||
 | 
			
		||||
	suite.Equal(state, decodedState)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGenesisTestSuite(t *testing.T) {
 | 
			
		||||
	suite.Run(t, new(genesisTestSuite))
 | 
			
		||||
}
 | 
			
		||||
@ -222,3 +222,34 @@ func (k *Keeper) SetVaultShareRecord(
 | 
			
		||||
	bz := k.cdc.MustMarshal(&record)
 | 
			
		||||
	store.Set(types.DepositorVaultSharesKey(record.Depositor), bz)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IterateVaultShareRecords iterates over all vault share objects in the store
 | 
			
		||||
// and performs a callback function.
 | 
			
		||||
func (k Keeper) IterateVaultShareRecords(
 | 
			
		||||
	ctx sdk.Context,
 | 
			
		||||
	cb func(record types.VaultShareRecord) (stop bool),
 | 
			
		||||
) {
 | 
			
		||||
	store := prefix.NewStore(ctx.KVStore(k.key), types.VaultShareRecordKeyPrefix)
 | 
			
		||||
	iterator := sdk.KVStorePrefixIterator(store, []byte{})
 | 
			
		||||
	defer iterator.Close()
 | 
			
		||||
 | 
			
		||||
	for ; iterator.Valid(); iterator.Next() {
 | 
			
		||||
		var record types.VaultShareRecord
 | 
			
		||||
		k.cdc.MustUnmarshal(iterator.Value(), &record)
 | 
			
		||||
		if cb(record) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetAllVaultShareRecords returns all vault share records from the store.
 | 
			
		||||
func (k Keeper) GetAllVaultShareRecords(ctx sdk.Context) types.VaultShareRecords {
 | 
			
		||||
	var records types.VaultShareRecords
 | 
			
		||||
 | 
			
		||||
	k.IterateVaultShareRecords(ctx, func(record types.VaultShareRecord) bool {
 | 
			
		||||
		records = append(records, record)
 | 
			
		||||
		return false
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	return records
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,9 +1,15 @@
 | 
			
		||||
package types
 | 
			
		||||
 | 
			
		||||
// NewGenesisState creates a new genesis state.
 | 
			
		||||
func NewGenesisState(params Params) GenesisState {
 | 
			
		||||
func NewGenesisState(
 | 
			
		||||
	params Params,
 | 
			
		||||
	vaultRecords VaultRecords,
 | 
			
		||||
	vaultShareRecords VaultShareRecords,
 | 
			
		||||
) GenesisState {
 | 
			
		||||
	return GenesisState{
 | 
			
		||||
		Params: params,
 | 
			
		||||
		Params:            params,
 | 
			
		||||
		VaultRecords:      vaultRecords,
 | 
			
		||||
		VaultShareRecords: vaultShareRecords,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,6 +19,14 @@ func (gs GenesisState) Validate() error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := gs.VaultRecords.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := gs.VaultShareRecords.Validate(); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,5 +34,7 @@ func (gs GenesisState) Validate() error {
 | 
			
		||||
func DefaultGenesisState() GenesisState {
 | 
			
		||||
	return NewGenesisState(
 | 
			
		||||
		DefaultParams(),
 | 
			
		||||
		VaultRecords{},
 | 
			
		||||
		VaultShareRecords{},
 | 
			
		||||
	)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NewVaultRecord returns a new VaultRecord with 0 supply.
 | 
			
		||||
@ -14,9 +15,48 @@ func NewVaultRecord(vaultDenom string) VaultRecord {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate returns an error if a VaultRecord is invalid.
 | 
			
		||||
func (vr *VaultRecord) Validate() error {
 | 
			
		||||
	if err := sdk.ValidateDenom(vr.Denom); err != nil {
 | 
			
		||||
		return sdkerrors.Wrap(ErrInvalidVaultDenom, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if vr.TotalSupply.Denom != vr.Denom {
 | 
			
		||||
		return fmt.Errorf(
 | 
			
		||||
			"total supply denom %v does not match vault record denom %v",
 | 
			
		||||
			vr.TotalSupply.Denom,
 | 
			
		||||
			vr.Denom,
 | 
			
		||||
		)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := vr.TotalSupply.Validate(); err != nil {
 | 
			
		||||
		return fmt.Errorf("vault total supply is invalid: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultRecords is a slice of VaultRecord.
 | 
			
		||||
type VaultRecords []VaultRecord
 | 
			
		||||
 | 
			
		||||
type VaultShareRecords []VaultShareRecord
 | 
			
		||||
// Validate returns an error if a slice of VaultRecords is invalid.
 | 
			
		||||
func (vrs VaultRecords) Validate() error {
 | 
			
		||||
	denoms := make(map[string]bool)
 | 
			
		||||
 | 
			
		||||
	for _, vr := range vrs {
 | 
			
		||||
		if err := vr.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if denoms[vr.Denom] {
 | 
			
		||||
			return fmt.Errorf("duplicate vault denom %s", vr.Denom)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		denoms[vr.Denom] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewVaultShareRecord returns a new VaultShareRecord with the provided supplied
 | 
			
		||||
// coins.
 | 
			
		||||
@ -27,6 +67,41 @@ func NewVaultShareRecord(depositor sdk.AccAddress, supplied ...sdk.Coin) VaultSh
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate returns an error if an VaultShareRecord is invalid.
 | 
			
		||||
func (vsr VaultShareRecord) Validate() error {
 | 
			
		||||
	if vsr.Depositor.Empty() {
 | 
			
		||||
		return fmt.Errorf("depositor is empty")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := vsr.AmountSupplied.Validate(); err != nil {
 | 
			
		||||
		return fmt.Errorf("invalid vault share record amount supplied: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// VaultShareRecords is a slice of VaultShareRecord.
 | 
			
		||||
type VaultShareRecords []VaultShareRecord
 | 
			
		||||
 | 
			
		||||
// Validate returns an error if a slice of VaultRecords is invalid.
 | 
			
		||||
func (vsrs VaultShareRecords) Validate() error {
 | 
			
		||||
	addrs := make(map[string]bool)
 | 
			
		||||
 | 
			
		||||
	for _, vr := range vsrs {
 | 
			
		||||
		if err := vr.Validate(); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, found := addrs[vr.Depositor.String()]; found {
 | 
			
		||||
			return fmt.Errorf("duplicate address %s", vr.Depositor.String())
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		addrs[vr.Depositor.String()] = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewAllowedVaults returns a new AllowedVaults with the given denom and strategy type.
 | 
			
		||||
func NewAllowedVault(denom string, strategyType StrategyType) AllowedVault {
 | 
			
		||||
	return AllowedVault{
 | 
			
		||||
@ -55,8 +130,8 @@ func (a AllowedVaults) Validate() error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (a *AllowedVault) Validate() error {
 | 
			
		||||
	if a.Denom == "" {
 | 
			
		||||
		return ErrInvalidVaultDenom
 | 
			
		||||
	if err := sdk.ValidateDenom(a.Denom); err != nil {
 | 
			
		||||
		return sdkerrors.Wrap(ErrInvalidVaultDenom, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if a.VaultStrategy == STRATEGY_TYPE_UNSPECIFIED {
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										310
									
								
								x/earn/types/vault_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								x/earn/types/vault_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,310 @@
 | 
			
		||||
package types_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
 | 
			
		||||
	"github.com/kava-labs/kava/app"
 | 
			
		||||
	"github.com/kava-labs/kava/x/earn/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestVaultRecordValidate(t *testing.T) {
 | 
			
		||||
	type errArgs struct {
 | 
			
		||||
		expectPass bool
 | 
			
		||||
		contains   string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name         string
 | 
			
		||||
		vaultRecords types.VaultRecords
 | 
			
		||||
		errArgs      errArgs
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "valid vault records",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "ukava",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("ukava", 5),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: true,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - duplicate denom",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("usdx", 5),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "duplicate vault denom usdx",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - invalid denom",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("ukava", 0),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "invalid denom",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - mismatch denom",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.NewInt64Coin("ukava", 0),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "total supply denom ukava does not match vault record denom usdx",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - negative",
 | 
			
		||||
			vaultRecords: types.VaultRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:       "usdx",
 | 
			
		||||
					TotalSupply: sdk.Coin{Denom: "usdx", Amount: sdk.NewInt(-1)},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "negative coin amount",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			err := test.vaultRecords.Validate()
 | 
			
		||||
 | 
			
		||||
			if test.errArgs.expectPass {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
				require.Contains(t, err.Error(), test.errArgs.contains)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestVaultShareRecordsValidate(t *testing.T) {
 | 
			
		||||
	_, addrs := app.GeneratePrivKeyAddressPairs(2)
 | 
			
		||||
 | 
			
		||||
	type errArgs struct {
 | 
			
		||||
		expectPass bool
 | 
			
		||||
		contains   string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name         string
 | 
			
		||||
		vaultRecords types.VaultShareRecords
 | 
			
		||||
		errArgs      errArgs
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "valid vault share records",
 | 
			
		||||
			vaultRecords: types.VaultShareRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[0],
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[1],
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
						sdk.NewInt64Coin("ukava", 5),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: true,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - duplicate address",
 | 
			
		||||
			vaultRecords: types.VaultShareRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[0],
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[0],
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
						sdk.NewInt64Coin("ukava", 5),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "duplicate address",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - invalid address",
 | 
			
		||||
			vaultRecords: types.VaultShareRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: sdk.AccAddress{},
 | 
			
		||||
					AmountSupplied: sdk.NewCoins(
 | 
			
		||||
						sdk.NewInt64Coin("usdx", 0),
 | 
			
		||||
					),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "depositor is empty",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - negative",
 | 
			
		||||
			vaultRecords: types.VaultShareRecords{
 | 
			
		||||
				{
 | 
			
		||||
					Depositor: addrs[0],
 | 
			
		||||
					AmountSupplied: sdk.Coins{
 | 
			
		||||
						sdk.Coin{Denom: "ukava", Amount: sdk.NewInt(-1)},
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "amount is not positive",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			err := test.vaultRecords.Validate()
 | 
			
		||||
 | 
			
		||||
			if test.errArgs.expectPass {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
				require.Contains(t, err.Error(), test.errArgs.contains)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestAllowedVaultsValidate(t *testing.T) {
 | 
			
		||||
	type errArgs struct {
 | 
			
		||||
		expectPass bool
 | 
			
		||||
		contains   string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tests := []struct {
 | 
			
		||||
		name         string
 | 
			
		||||
		vaultRecords types.AllowedVaults
 | 
			
		||||
		errArgs      errArgs
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "valid vault share records",
 | 
			
		||||
			vaultRecords: types.AllowedVaults{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:         "usdx",
 | 
			
		||||
					VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Denom:         "busd",
 | 
			
		||||
					VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: true,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - duplicate denom",
 | 
			
		||||
			vaultRecords: types.AllowedVaults{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:         "usdx",
 | 
			
		||||
					VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
				},
 | 
			
		||||
				{
 | 
			
		||||
					Denom:         "usdx",
 | 
			
		||||
					VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "duplicate vault denom usdx",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - invalid denom",
 | 
			
		||||
			vaultRecords: types.AllowedVaults{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:         "",
 | 
			
		||||
					VaultStrategy: types.STRATEGY_TYPE_HARD,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "invalid denom",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "invalid - invalid strategy",
 | 
			
		||||
			vaultRecords: types.AllowedVaults{
 | 
			
		||||
				{
 | 
			
		||||
					Denom:         "usdx",
 | 
			
		||||
					VaultStrategy: types.STRATEGY_TYPE_UNSPECIFIED,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			errArgs: errArgs{
 | 
			
		||||
				expectPass: false,
 | 
			
		||||
				contains:   "invalid vault strategy",
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, test := range tests {
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			err := test.vaultRecords.Validate()
 | 
			
		||||
 | 
			
		||||
			if test.errArgs.expectPass {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
				require.Contains(t, err.Error(), test.errArgs.contains)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNewVaultShareRecord(t *testing.T) {
 | 
			
		||||
	_, addrs := app.GeneratePrivKeyAddressPairs(1)
 | 
			
		||||
 | 
			
		||||
	coins := sdk.NewCoins(
 | 
			
		||||
		sdk.NewInt64Coin("usdx", 10),
 | 
			
		||||
		sdk.NewInt64Coin("ukava", 5),
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	shareRecord := types.NewVaultShareRecord(addrs[0], coins...)
 | 
			
		||||
	require.Equal(t, coins, shareRecord.AmountSupplied)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user