mirror of
https://github.com/0glabs/0g-chain.git
synced 2025-01-12 08:15:18 +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
|
// 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 {
|
if err := gs.Validate(); err != nil {
|
||||||
panic(fmt.Sprintf("failed to validate %s genesis state: %s", types.ModuleName, err))
|
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)
|
k.SetParams(ctx, gs.Params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExportGenesis returns a GenesisState for a given context and keeper
|
// ExportGenesis returns a GenesisState for a given context and keeper
|
||||||
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
|
func ExportGenesis(ctx sdk.Context, k keeper.Keeper) types.GenesisState {
|
||||||
params := k.GetParams(ctx)
|
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)
|
bz := k.cdc.MustMarshal(&record)
|
||||||
store.Set(types.DepositorVaultSharesKey(record.Depositor), bz)
|
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
|
package types
|
||||||
|
|
||||||
// NewGenesisState creates a new genesis state.
|
// NewGenesisState creates a new genesis state.
|
||||||
func NewGenesisState(params Params) GenesisState {
|
func NewGenesisState(
|
||||||
|
params Params,
|
||||||
|
vaultRecords VaultRecords,
|
||||||
|
vaultShareRecords VaultShareRecords,
|
||||||
|
) GenesisState {
|
||||||
return GenesisState{
|
return GenesisState{
|
||||||
Params: params,
|
Params: params,
|
||||||
|
VaultRecords: vaultRecords,
|
||||||
|
VaultShareRecords: vaultShareRecords,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13,6 +19,14 @@ func (gs GenesisState) Validate() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := gs.VaultRecords.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := gs.VaultShareRecords.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,5 +34,7 @@ func (gs GenesisState) Validate() error {
|
|||||||
func DefaultGenesisState() GenesisState {
|
func DefaultGenesisState() GenesisState {
|
||||||
return NewGenesisState(
|
return NewGenesisState(
|
||||||
DefaultParams(),
|
DefaultParams(),
|
||||||
|
VaultRecords{},
|
||||||
|
VaultShareRecords{},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
|
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewVaultRecord returns a new VaultRecord with 0 supply.
|
// 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 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
|
// NewVaultShareRecord returns a new VaultShareRecord with the provided supplied
|
||||||
// coins.
|
// 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.
|
// NewAllowedVaults returns a new AllowedVaults with the given denom and strategy type.
|
||||||
func NewAllowedVault(denom string, strategyType StrategyType) AllowedVault {
|
func NewAllowedVault(denom string, strategyType StrategyType) AllowedVault {
|
||||||
return AllowedVault{
|
return AllowedVault{
|
||||||
@ -55,8 +130,8 @@ func (a AllowedVaults) Validate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *AllowedVault) Validate() error {
|
func (a *AllowedVault) Validate() error {
|
||||||
if a.Denom == "" {
|
if err := sdk.ValidateDenom(a.Denom); err != nil {
|
||||||
return ErrInvalidVaultDenom
|
return sdkerrors.Wrap(ErrInvalidVaultDenom, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.VaultStrategy == STRATEGY_TYPE_UNSPECIFIED {
|
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