From 7536aee0d8f84e5dfb11d26d3819289c45a2013f Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Thu, 16 May 2024 14:01:34 +0200 Subject: [PATCH] feat(vesting): update to align with cosmos-sdk v0.50.4 This commit updates the vesting module to match the changes introduced in cosmos-sdk v0.50.4. --- x/vesting/client/cli/tx.go | 62 ++++--- x/vesting/module.go | 67 +++++-- x/vesting/msg_server.go | 182 +++++++++++------- x/vesting/types/codec.go | 5 +- x/vesting/types/constants.go | 3 - x/vesting/types/genesis_test.go | 3 +- x/vesting/types/msgs.go | 24 +-- x/vesting/types/period.go | 8 - x/vesting/types/vesting_account.go | 223 ++++++---------------- x/vesting/types/vesting_account_test.go | 235 +++++++++++++++++------- 10 files changed, 434 insertions(+), 378 deletions(-) diff --git a/x/vesting/client/cli/tx.go b/x/vesting/client/cli/tx.go index 4050c897..3fcc45e2 100644 --- a/x/vesting/client/cli/tx.go +++ b/x/vesting/client/cli/tx.go @@ -2,12 +2,15 @@ package cli import ( "encoding/json" + "errors" "fmt" "os" "strconv" "github.com/spf13/cobra" + "cosmossdk.io/core/address" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/tx" @@ -16,13 +19,13 @@ import ( "github.com/axone-protocol/axoned/v8/x/vesting/types" ) -// FlagDelayed Transaction command flags. +// Transaction command flags. const ( FlagDelayed = "delayed" ) // GetTxCmd returns vesting module's transaction commands. -func GetTxCmd() *cobra.Command { +func GetTxCmd(ac address.Codec) *cobra.Command { txCmd := &cobra.Command{ Use: types.ModuleName, Short: "Vesting transaction subcommands", @@ -32,10 +35,10 @@ func GetTxCmd() *cobra.Command { } txCmd.AddCommand( - NewMsgCreateVestingAccountCmd(), - NewMsgCreatePermanentLockedAccountCmd(), - NewMsgCreatePeriodicVestingAccountCmd(), - NewMsgCreateCliffVestingAccountCmd(), + NewMsgCreateVestingAccountCmd(ac), + NewMsgCreatePermanentLockedAccountCmd(ac), + NewMsgCreatePeriodicVestingAccountCmd(ac), + NewMsgCreateCliffVestingAccountCmd(ac), ) return txCmd @@ -43,7 +46,7 @@ func GetTxCmd() *cobra.Command { // NewMsgCreateVestingAccountCmd returns a CLI command handler for creating a // MsgCreateVestingAccount transaction. -func NewMsgCreateVestingAccountCmd() *cobra.Command { +func NewMsgCreateVestingAccountCmd(ac address.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "create-vesting-account [to_address] [amount] [end_time]", Short: "Create a new vesting account funded with an allocation of tokens.", @@ -58,11 +61,15 @@ timestamp.`, if err != nil { return err } - toAddr, err := sdk.AccAddressFromBech32(args[0]) + toAddr, err := ac.StringToBytes(args[0]) if err != nil { return err } + if args[1] == "" { + return errors.New("amount is empty") + } + amount, err := sdk.ParseCoinsNormalized(args[1]) if err != nil { return err @@ -76,7 +83,6 @@ timestamp.`, delayed, _ := cmd.Flags().GetBool(FlagDelayed) msg := types.NewMsgCreateVestingAccount(clientCtx.GetFromAddress(), toAddr, amount, endTime, delayed) - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } @@ -89,7 +95,7 @@ timestamp.`, // NewMsgCreatePermanentLockedAccountCmd returns a CLI command handler for creating a // MsgCreatePermanentLockedAccount transaction. -func NewMsgCreatePermanentLockedAccountCmd() *cobra.Command { +func NewMsgCreatePermanentLockedAccountCmd(ac address.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "create-permanent-locked-account [to_address] [amount]", Short: "Create a new permanently locked account funded with an allocation of tokens.", @@ -102,18 +108,21 @@ tokens.`, if err != nil { return err } - toAddr, err := sdk.AccAddressFromBech32(args[0]) + toAddr, err := ac.StringToBytes(args[0]) if err != nil { return err } + if args[1] == "" { + return errors.New("amount is empty") + } + amount, err := sdk.ParseCoinsNormalized(args[1]) if err != nil { return err } msg := types.NewMsgCreatePermanentLockedAccount(clientCtx.GetFromAddress(), toAddr, amount) - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } @@ -129,15 +138,15 @@ type VestingData struct { } type InputPeriod struct { - Coins string `json:"coins"` - LengthSeconds int64 `json:"length_seconds"` + Coins string `json:"coins"` + Length int64 `json:"length_seconds"` //nolint:tagliatelle } // NewMsgCreatePeriodicVestingAccountCmd returns a CLI command handler for creating a // MsgCreatePeriodicVestingAccountCmd transaction. // //nolint:funlen,lll -func NewMsgCreatePeriodicVestingAccountCmd() *cobra.Command { +func NewMsgCreatePeriodicVestingAccountCmd(ac address.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "create-periodic-vesting-account [to_address] [periods_json_file]", Short: "Create a new vesting account funded with an allocation of tokens.", @@ -146,7 +155,7 @@ func NewMsgCreatePeriodicVestingAccountCmd() *cobra.Command { An array of coin strings and unix epoch times for coins to vest { "start_time": 1625204910, -"period":[ +"periods":[ { "coins": "10test", "length_seconds":2592000 //30 days @@ -165,7 +174,7 @@ func NewMsgCreatePeriodicVestingAccountCmd() *cobra.Command { return err } - toAddr, err := sdk.AccAddressFromBech32(args[0]) + toAddr, err := ac.StringToBytes(args[0]) if err != nil { return err } @@ -190,15 +199,15 @@ func NewMsgCreatePeriodicVestingAccountCmd() *cobra.Command { return err } - if p.LengthSeconds < 0 { - return fmt.Errorf("invalid period length of %d in period %d, length must be greater than 0", p.LengthSeconds, i) + if p.Length < 0 { + return fmt.Errorf("invalid period length of %d in period %d, length must be greater than 0", p.Length, i) } - period := types.Period{Length: p.LengthSeconds, Amount: amount} + + period := types.Period{Length: p.Length, Amount: amount} periods = append(periods, period) } msg := types.NewMsgCreatePeriodicVestingAccount(clientCtx.GetFromAddress(), toAddr, vestingData.StartTime, periods) - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } @@ -210,11 +219,11 @@ func NewMsgCreatePeriodicVestingAccountCmd() *cobra.Command { // NewMsgCreateCliffVestingAccountCmd returns a CLI command handler for creating a // MsgCreateCliffVestingAccount transaction. -func NewMsgCreateCliffVestingAccountCmd() *cobra.Command { +func NewMsgCreateCliffVestingAccountCmd(ac address.Codec) *cobra.Command { cmd := &cobra.Command{ Use: "create-cliff-vesting-account [to_address] [amount] [cliff_time] [end_time]", Short: "Create a new vesting account funded with an allocation of tokens with cliff.", - Long: `Create a new vesting account funded with an allocation of tokens. The + Long: `Create a new vesting account funded with an allocation of tokens with cliff. The tokens allowed will be start vested but the token will be released only after the cliff time. All vesting accounts created will have their start time set by the committed block's time. The end_time and cliff_time must be provided as a UNIX epoch @@ -225,11 +234,15 @@ timestamp.`, if err != nil { return err } - toAddr, err := sdk.AccAddressFromBech32(args[0]) + toAddr, err := ac.StringToBytes(args[0]) if err != nil { return err } + if args[1] == "" { + return errors.New("amount is empty") + } + amount, err := sdk.ParseCoinsNormalized(args[1]) if err != nil { return err @@ -246,7 +259,6 @@ timestamp.`, } msg := types.NewMsgCreateCliffVestingAccount(clientCtx.GetFromAddress(), toAddr, amount, endTime, cliffTime) - return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, } diff --git a/x/vesting/module.go b/x/vesting/module.go index e84e4284..96f48f0e 100644 --- a/x/vesting/module.go +++ b/x/vesting/module.go @@ -3,13 +3,16 @@ package vesting import ( "encoding/json" - "github.com/grpc-ecosystem/grpc-gateway/runtime" + gwruntime "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/spf13/cobra" "google.golang.org/grpc" abci "github.com/cometbft/cometbft/abci/types" + modulev1 "cosmossdk.io/api/cosmos/vesting/module/v1" + "cosmossdk.io/core/address" "cosmossdk.io/core/appmodule" + "cosmossdk.io/depinject" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" @@ -23,22 +26,25 @@ import ( ) var ( + _ module.AppModuleBasic = AppModule{} + _ appmodule.AppModule = AppModule{} _ appmodule.HasServices = AppModule{} - _ module.AppModuleBasic = AppModuleBasic{} ) // AppModuleBasic defines the basic application module used by the sub-vesting // module. The module itself contain no special logic or state other than message // handling. -type AppModuleBasic struct{} +type AppModuleBasic struct { + ac address.Codec +} // Name returns the module's name. func (AppModuleBasic) Name() string { return types.ModuleName } -// RegisterLegacyAminoCodec registers the module's types with the given codec. +// RegisterCodec registers the module's types with the given codec. func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { types.RegisterLegacyAminoCodec(cdc) } @@ -61,16 +67,11 @@ func (AppModuleBasic) ValidateGenesis(_ codec.JSONCodec, _ client.TxEncodingConf // RegisterGRPCGatewayRoutes registers the module's gRPC Gateway routes. Currently, this // is a no-op. -func (a AppModuleBasic) RegisterGRPCGatewayRoutes(_ client.Context, _ *runtime.ServeMux) {} +func (AppModuleBasic) RegisterGRPCGatewayRoutes(_ client.Context, _ *gwruntime.ServeMux) {} // GetTxCmd returns the root tx command for the auth module. -func (AppModuleBasic) GetTxCmd() *cobra.Command { - return cli.GetTxCmd() -} - -// GetQueryCmd returns the module's root query command. Currently, this is a no-op. -func (AppModuleBasic) GetQueryCmd() *cobra.Command { - return nil +func (ab AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.GetTxCmd(ab.ac) } // AppModule extends the AppModuleBasic implementation by implementing the @@ -82,20 +83,19 @@ type AppModule struct { bankKeeper types.BankKeeper } -func (am AppModule) IsOnePerModuleType() {} - -func (am AppModule) IsAppModule() {} - func NewAppModule(ak keeper.AccountKeeper, bk types.BankKeeper) AppModule { return AppModule{ - AppModuleBasic: AppModuleBasic{}, + AppModuleBasic: AppModuleBasic{ac: ak.AddressCodec()}, accountKeeper: ak, bankKeeper: bk, } } -// RegisterInvariants performs a no-op; there are no invariants to enforce. -func (AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} +// IsOnePerModuleType implements the depinject.OnePerModuleType interface. +func (am AppModule) IsOnePerModuleType() {} + +// IsAppModule implements the appmodule.AppModule interface. +func (am AppModule) IsAppModule() {} // RegisterServices registers module services. func (am AppModule) RegisterServices(registrar grpc.ServiceRegistrar) error { @@ -115,3 +115,32 @@ func (am AppModule) ExportGenesis(_ sdk.Context, cdc codec.JSONCodec) json.RawMe // ConsensusVersion implements AppModule/ConsensusVersion. func (AppModule) ConsensusVersion() uint64 { return 1 } + +// +// App Wiring Setup +// + +func init() { + appmodule.Register(&modulev1.Module{}, + appmodule.Provide(ProvideModule), + ) +} + +type ModuleInputs struct { + depinject.In + + AccountKeeper keeper.AccountKeeper + BankKeeper types.BankKeeper +} + +type ModuleOutputs struct { + depinject.Out + + Module appmodule.AppModule +} + +func ProvideModule(in ModuleInputs) ModuleOutputs { + m := NewAppModule(in.AccountKeeper, in.BankKeeper) + + return ModuleOutputs{Module: m} +} diff --git a/x/vesting/msg_server.go b/x/vesting/msg_server.go index f96f0a7a..20c0d83c 100644 --- a/x/vesting/msg_server.go +++ b/x/vesting/msg_server.go @@ -29,37 +29,47 @@ func NewMsgServerImpl(k keeper.AccountKeeper, bk types.BankKeeper) types.MsgServ var _ types.MsgServer = msgServer{} +//nolint:funlen func (s msgServer) CreateVestingAccount(goCtx context.Context, msg *types.MsgCreateVestingAccount, ) (*types.MsgCreateVestingAccountResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - ak := s.AccountKeeper - bk := s.BankKeeper - - if err := bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil { - return nil, err + from, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.FromAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'from' address: %s", err) } - from, err := sdk.AccAddressFromBech32(msg.FromAddress) + to, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.ToAddress) if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'to' address: %s", err) + } + + if err := validateAmount(msg.Amount); err != nil { return nil, err } - to, err := sdk.AccAddressFromBech32(msg.ToAddress) - if err != nil { + + if msg.EndTime <= 0 { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid end time") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := s.BankKeeper.IsSendEnabledCoins(ctx, msg.Amount...); err != nil { return nil, err } - if bk.BlockedAddr(to) { + if s.BankKeeper.BlockedAddr(to) { return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress) } - if acc := ak.GetAccount(ctx, to); acc != nil { + if acc := s.AccountKeeper.GetAccount(ctx, to); acc != nil { return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress) } baseAccount := authtypes.NewBaseAccountWithAddress(to) - baseAccount = ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) - baseVestingAccount := types.NewBaseVestingAccount(baseAccount, msg.Amount.Sort(), msg.EndTime) + baseAccount = s.AccountKeeper.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) + baseVestingAccount, err := types.NewBaseVestingAccount(baseAccount, msg.Amount.Sort(), msg.EndTime) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } var vestingAccount sdk.AccountI if msg.Delayed { @@ -68,7 +78,7 @@ func (s msgServer) CreateVestingAccount(goCtx context.Context, vestingAccount = types.NewContinuousVestingAccountRaw(baseVestingAccount, ctx.BlockTime().Unix()) } - ak.SetAccount(ctx, vestingAccount) + s.AccountKeeper.SetAccount(ctx, vestingAccount) defer func() { telemetry.IncrCounter(1, "new", "account") @@ -84,8 +94,7 @@ func (s msgServer) CreateVestingAccount(goCtx context.Context, } }() - err = bk.SendCoins(ctx, from, to, msg.Amount) - if err != nil { + if err = s.BankKeeper.SendCoins(ctx, from, to, msg.Amount); err != nil { return nil, err } @@ -95,36 +104,41 @@ func (s msgServer) CreateVestingAccount(goCtx context.Context, func (s msgServer) CreatePermanentLockedAccount(goCtx context.Context, msg *types.MsgCreatePermanentLockedAccount, ) (*types.MsgCreatePermanentLockedAccountResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - ak := s.AccountKeeper - bk := s.BankKeeper - - if err := bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil { - return nil, err + from, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.FromAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'from' address: %s", err) } - from, err := sdk.AccAddressFromBech32(msg.FromAddress) + to, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.ToAddress) if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'to' address: %s", err) + } + + if err := validateAmount(msg.Amount); err != nil { return nil, err } - to, err := sdk.AccAddressFromBech32(msg.ToAddress) - if err != nil { + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := s.BankKeeper.IsSendEnabledCoins(ctx, msg.Amount...); err != nil { return nil, err } - if bk.BlockedAddr(to) { + if s.BankKeeper.BlockedAddr(to) { return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress) } - if acc := ak.GetAccount(ctx, to); acc != nil { + if acc := s.AccountKeeper.GetAccount(ctx, to); acc != nil { return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress) } baseAccount := authtypes.NewBaseAccountWithAddress(to) - baseAccount = ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) - vestingAccount := types.NewPermanentLockedAccount(baseAccount, msg.Amount) + baseAccount = s.AccountKeeper.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) + vestingAccount, err := types.NewPermanentLockedAccount(baseAccount, msg.Amount) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } - ak.SetAccount(ctx, vestingAccount) + s.AccountKeeper.SetAccount(ctx, vestingAccount) defer func() { telemetry.IncrCounter(1, "new", "account") @@ -140,50 +154,66 @@ func (s msgServer) CreatePermanentLockedAccount(goCtx context.Context, } }() - err = bk.SendCoins(ctx, from, to, msg.Amount) - if err != nil { + if err = s.BankKeeper.SendCoins(ctx, from, to, msg.Amount); err != nil { return nil, err } return &types.MsgCreatePermanentLockedAccountResponse{}, nil } +//nolint:funlen func (s msgServer) CreatePeriodicVestingAccount(goCtx context.Context, msg *types.MsgCreatePeriodicVestingAccount, ) (*types.MsgCreatePeriodicVestingAccountResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - ak := s.AccountKeeper - bk := s.BankKeeper - - from, err := sdk.AccAddressFromBech32(msg.FromAddress) + from, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.FromAddress) if err != nil { - return nil, err + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'from' address: %s", err) } - to, err := sdk.AccAddressFromBech32(msg.ToAddress) + + to, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.ToAddress) if err != nil { - return nil, err + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'to' address: %s", err) } - if acc := ak.GetAccount(ctx, to); acc != nil { - return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress) + if msg.StartTime < 1 { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "invalid start time of %d, length must be greater than 0", msg.StartTime) } var totalCoins sdk.Coins + for i, period := range msg.VestingPeriods { + if period.Length < 1 { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, + "invalid period length of %d in period %d, length must be greater than 0", period.Length, i) + } + + if err := validateAmount(period.Amount); err != nil { + return nil, err + } - for _, period := range msg.VestingPeriods { totalCoins = totalCoins.Add(period.Amount...) } - if err := bk.IsSendEnabledCoins(ctx, totalCoins...); err != nil { + if s.BankKeeper.BlockedAddr(to) { + return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress) + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if acc := s.AccountKeeper.GetAccount(ctx, to); acc != nil { + return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress) + } + + if err := s.BankKeeper.IsSendEnabledCoins(ctx, totalCoins...); err != nil { return nil, err } baseAccount := authtypes.NewBaseAccountWithAddress(to) - baseAccount = ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) - vestingAccount := types.NewPeriodicVestingAccount(baseAccount, totalCoins.Sort(), msg.StartTime, msg.VestingPeriods) + baseAccount = s.AccountKeeper.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) + vestingAccount, err := types.NewPeriodicVestingAccount(baseAccount, totalCoins.Sort(), msg.StartTime, msg.VestingPeriods) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } - ak.SetAccount(ctx, vestingAccount) + s.AccountKeeper.SetAccount(ctx, vestingAccount) defer func() { telemetry.IncrCounter(1, "new", "account") @@ -199,49 +229,58 @@ func (s msgServer) CreatePeriodicVestingAccount(goCtx context.Context, } }() - err = bk.SendCoins(ctx, from, to, totalCoins) - if err != nil { + if err = s.BankKeeper.SendCoins(ctx, from, to, totalCoins); err != nil { return nil, err } return &types.MsgCreatePeriodicVestingAccountResponse{}, nil } +//nolint:funlen func (s msgServer) CreateCliffVestingAccount(goCtx context.Context, msg *types.MsgCreateCliffVestingAccount, ) (*types.MsgCreateCliffVestingAccountResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - ak := s.AccountKeeper - bk := s.BankKeeper - - if err := bk.IsSendEnabledCoins(ctx, msg.Amount...); err != nil { - return nil, err + from, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.FromAddress) + if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'from' address: %s", err) } - from, err := sdk.AccAddressFromBech32(msg.FromAddress) + to, err := s.AccountKeeper.AddressCodec().StringToBytes(msg.ToAddress) if err != nil { + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid 'to' address: %s", err) + } + + if err := validateAmount(msg.Amount); err != nil { return nil, err } - to, err := sdk.AccAddressFromBech32(msg.ToAddress) - if err != nil { + + if msg.EndTime <= 0 { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, "invalid end time") + } + + ctx := sdk.UnwrapSDKContext(goCtx) + if err := s.BankKeeper.IsSendEnabledCoins(ctx, msg.Amount...); err != nil { return nil, err } - if bk.BlockedAddr(to) { + if s.BankKeeper.BlockedAddr(to) { return nil, errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "%s is not allowed to receive funds", msg.ToAddress) } - if acc := ak.GetAccount(ctx, to); acc != nil { + if acc := s.AccountKeeper.GetAccount(ctx, to); acc != nil { return nil, errorsmod.Wrapf(sdkerrors.ErrInvalidRequest, "account %s already exists", msg.ToAddress) } baseAccount := authtypes.NewBaseAccountWithAddress(to) - baseAccount = ak.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) - baseVestingAccount := types.NewBaseVestingAccount(baseAccount, msg.Amount.Sort(), msg.EndTime) + baseAccount = s.AccountKeeper.NewAccount(ctx, baseAccount).(*authtypes.BaseAccount) + baseVestingAccount, err := types.NewBaseVestingAccount(baseAccount, msg.Amount.Sort(), msg.EndTime) + if err != nil { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidRequest, err.Error()) + } vestingAccount := types.NewCliffVestingAccountRaw(baseVestingAccount, ctx.BlockTime().Unix(), msg.CliffTime) - ak.SetAccount(ctx, vestingAccount) + s.AccountKeeper.SetAccount(ctx, vestingAccount) defer func() { telemetry.IncrCounter(1, "new", "account") @@ -257,10 +296,21 @@ func (s msgServer) CreateCliffVestingAccount(goCtx context.Context, } }() - err = bk.SendCoins(ctx, from, to, msg.Amount) - if err != nil { + if err = s.BankKeeper.SendCoins(ctx, from, to, msg.Amount); err != nil { return nil, err } return &types.MsgCreateCliffVestingAccountResponse{}, nil } + +func validateAmount(amount sdk.Coins) error { + if !amount.IsValid() { + return sdkerrors.ErrInvalidCoins.Wrap(amount.String()) + } + + if !amount.IsAllPositive() { + return sdkerrors.ErrInvalidCoins.Wrap(amount.String()) + } + + return nil +} diff --git a/x/vesting/types/codec.go b/x/vesting/types/codec.go index 72802262..407c894f 100644 --- a/x/vesting/types/codec.go +++ b/x/vesting/types/codec.go @@ -16,13 +16,15 @@ import ( func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { cdc.RegisterInterface((*exported.VestingAccount)(nil), nil) cdc.RegisterConcrete(&BaseVestingAccount{}, "cosmos-sdk/BaseVestingAccount", nil) - cdc.RegisterConcrete(&CliffVestingAccount{}, "cosmos-sdk/CliffVestingAccount", nil) cdc.RegisterConcrete(&ContinuousVestingAccount{}, "cosmos-sdk/ContinuousVestingAccount", nil) cdc.RegisterConcrete(&DelayedVestingAccount{}, "cosmos-sdk/DelayedVestingAccount", nil) cdc.RegisterConcrete(&PeriodicVestingAccount{}, "cosmos-sdk/PeriodicVestingAccount", nil) cdc.RegisterConcrete(&PermanentLockedAccount{}, "cosmos-sdk/PermanentLockedAccount", nil) + cdc.RegisterConcrete(&CliffVestingAccount{}, "cosmos-sdk/CliffVestingAccount", nil) legacy.RegisterAminoMsg(cdc, &MsgCreateVestingAccount{}, "cosmos-sdk/MsgCreateVestingAccount") legacy.RegisterAminoMsg(cdc, &MsgCreatePermanentLockedAccount{}, "cosmos-sdk/MsgCreatePermLockedAccount") + legacy.RegisterAminoMsg(cdc, &MsgCreatePeriodicVestingAccount{}, "cosmos-sdk/MsgCreatePeriodVestAccount") + legacy.RegisterAminoMsg(cdc, &MsgCreateCliffVestingAccount{}, "cosmos-sdk/MsgCreateCliffVestingAccount") } // RegisterInterface associates protoName with AccountI and VestingAccount @@ -62,6 +64,7 @@ func RegisterInterfaces(registry types.InterfaceRegistry) { (*sdk.Msg)(nil), &MsgCreateVestingAccount{}, &MsgCreatePermanentLockedAccount{}, + &MsgCreateCliffVestingAccount{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) diff --git a/x/vesting/types/constants.go b/x/vesting/types/constants.go index 5fd3ce15..3562a80e 100644 --- a/x/vesting/types/constants.go +++ b/x/vesting/types/constants.go @@ -4,9 +4,6 @@ const ( // ModuleName defines the module's name. ModuleName = "vesting" - // AttributeValueCategory is an alias for the message event value. - AttributeValueCategory = ModuleName - // RouterKey defines the module's message routing key. RouterKey = ModuleName ) diff --git a/x/vesting/types/genesis_test.go b/x/vesting/types/genesis_test.go index d8b8d6d9..74d6c49a 100644 --- a/x/vesting/types/genesis_test.go +++ b/x/vesting/types/genesis_test.go @@ -21,7 +21,8 @@ var ( func TestValidateGenesisInvalidAccounts(t *testing.T) { acc1 := authtypes.NewBaseAccountWithAddress(sdk.AccAddress(addr1)) acc1Balance := sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 150)) - baseVestingAcc := NewBaseVestingAccount(acc1, acc1Balance, 1548775410) + baseVestingAcc, err := NewBaseVestingAccount(acc1, acc1Balance, 1548775410) + require.NoError(t, err) // invalid delegated vesting baseVestingAcc.DelegatedVesting = acc1Balance.Add(acc1Balance...) diff --git a/x/vesting/types/msgs.go b/x/vesting/types/msgs.go index 15e7e8a7..67d00091 100644 --- a/x/vesting/types/msgs.go +++ b/x/vesting/types/msgs.go @@ -4,17 +4,14 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -var _ sdk.Msg = &MsgCreateVestingAccount{} - -var _ sdk.Msg = &MsgCreatePermanentLockedAccount{} - -var _ sdk.Msg = &MsgCreatePeriodicVestingAccount{} - -var _ sdk.Msg = &MsgCreateCliffVestingAccount{} +var ( + _ sdk.Msg = &MsgCreateVestingAccount{} + _ sdk.Msg = &MsgCreatePermanentLockedAccount{} + _ sdk.Msg = &MsgCreatePeriodicVestingAccount{} + _ sdk.Msg = &MsgCreateCliffVestingAccount{} +) // NewMsgCreateVestingAccount returns a reference to a new MsgCreateVestingAccount. -// -//nolint:interfacer func NewMsgCreateVestingAccount(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins, @@ -31,8 +28,6 @@ func NewMsgCreateVestingAccount(fromAddr, } // NewMsgCreatePermanentLockedAccount returns a reference to a new MsgCreatePermanentLockedAccount. -// -//nolint:interfacer func NewMsgCreatePermanentLockedAccount(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins) *MsgCreatePermanentLockedAccount { return &MsgCreatePermanentLockedAccount{ FromAddress: fromAddr.String(), @@ -42,10 +37,7 @@ func NewMsgCreatePermanentLockedAccount(fromAddr, toAddr sdk.AccAddress, amount } // NewMsgCreatePeriodicVestingAccount returns a reference to a new MsgCreatePeriodicVestingAccount. -// -//nolint:interfacer -func NewMsgCreatePeriodicVestingAccount(fromAddr, - toAddr sdk.AccAddress, +func NewMsgCreatePeriodicVestingAccount(fromAddr, toAddr sdk.AccAddress, startTime int64, periods []Period, ) *MsgCreatePeriodicVestingAccount { @@ -58,8 +50,6 @@ func NewMsgCreatePeriodicVestingAccount(fromAddr, } // NewMsgCreateCliffVestingAccount returns a reference to a new MsgCreateCliffVestingAccount. -// -//nolint:interfacer func NewMsgCreateCliffVestingAccount(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins, diff --git a/x/vesting/types/period.go b/x/vesting/types/period.go index d733e639..a1ac78f5 100644 --- a/x/vesting/types/period.go +++ b/x/vesting/types/period.go @@ -5,8 +5,6 @@ import ( "strings" "time" - "sigs.k8s.io/yaml" - sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -18,12 +16,6 @@ func (p Period) Duration() time.Duration { return time.Duration(p.Length) * time.Second } -// String implements the fmt.Stringer interface. -func (p Period) String() string { - out, _ := yaml.Marshal(p) - return string(out) -} - // TotalLength return the total length in seconds for a period. func (p Periods) TotalLength() int64 { var total int64 diff --git a/x/vesting/types/vesting_account.go b/x/vesting/types/vesting_account.go index c8c420e4..d08c6189 100644 --- a/x/vesting/types/vesting_account.go +++ b/x/vesting/types/vesting_account.go @@ -2,13 +2,11 @@ package types import ( "errors" + "fmt" "time" - "sigs.k8s.io/yaml" - "cosmossdk.io/math" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -29,14 +27,16 @@ var ( // NewBaseVestingAccount creates a new BaseVestingAccount object. It is the // callers responsibility to ensure the base account has sufficient funds with // regards to the original vesting amount. -func NewBaseVestingAccount(baseAccount *authtypes.BaseAccount, originalVesting sdk.Coins, endTime int64) *BaseVestingAccount { - return &BaseVestingAccount{ +func NewBaseVestingAccount(baseAccount *authtypes.BaseAccount, originalVesting sdk.Coins, endTime int64) (*BaseVestingAccount, error) { + baseVestingAccount := &BaseVestingAccount{ BaseAccount: baseAccount, OriginalVesting: originalVesting, DelegatedFree: sdk.NewCoins(), DelegatedVesting: sdk.NewCoins(), EndTime: endTime, } + + return baseVestingAccount, baseVestingAccount.Validate() } // LockedCoinsFromVesting returns all the coins that are not spendable (i.e. locked) @@ -149,51 +149,19 @@ func (bva BaseVestingAccount) GetEndTime() int64 { // Validate checks for errors on the account fields. func (bva BaseVestingAccount) Validate() error { - if !(bva.DelegatedVesting.IsAllLTE(bva.OriginalVesting)) { - return errors.New("delegated vesting amount cannot be greater than original vesting amount") + if bva.EndTime < 0 { + return errors.New("end time cannot be negative") } - return bva.BaseAccount.Validate() -} - -type vestingAccountYAML struct { - Address sdk.AccAddress `json:"address"` - PublicKey string `json:"public_key"` - AccountNumber uint64 `json:"account_number"` - Sequence uint64 `json:"sequence"` - OriginalVesting sdk.Coins `json:"original_vesting"` - DelegatedFree sdk.Coins `json:"delegated_free"` - DelegatedVesting sdk.Coins `json:"delegated_vesting"` - EndTime int64 `json:"end_time"` - - // custom fields based on concrete vesting type which can be omitted - StartTime int64 `json:"start_time,omitempty"` - CliffTime int64 `json:"cliff_time,omitempty"` - VestingPeriods Periods `json:"vesting_periods,omitempty"` -} -func (bva BaseVestingAccount) String() string { - out, _ := bva.MarshalYAML() - return out.(string) -} - -// MarshalYAML returns the YAML representation of a BaseVestingAccount. -func (bva BaseVestingAccount) MarshalYAML() (interface{}, error) { - accAddr, err := sdk.AccAddressFromBech32(bva.Address) - if err != nil { - return nil, err + if !bva.OriginalVesting.IsValid() || !bva.OriginalVesting.IsAllPositive() { + return fmt.Errorf("invalid coins: %s", bva.OriginalVesting.String()) } - out := vestingAccountYAML{ - Address: accAddr, - AccountNumber: bva.AccountNumber, - PublicKey: getPKString(bva), - Sequence: bva.Sequence, - OriginalVesting: bva.OriginalVesting, - DelegatedFree: bva.DelegatedFree, - DelegatedVesting: bva.DelegatedVesting, - EndTime: bva.EndTime, + if !(bva.DelegatedVesting.IsAllLTE(bva.OriginalVesting)) { + return errors.New("delegated vesting amount cannot be greater than original vesting amount") } - return marshalYaml(out) + + return bva.BaseAccount.Validate() } // Continuous Vesting Account @@ -215,17 +183,19 @@ func NewContinuousVestingAccountRaw(bva *BaseVestingAccount, startTime int64) *C func NewContinuousVestingAccount(baseAcc *authtypes.BaseAccount, originalVesting sdk.Coins, startTime, endTime int64, -) *ContinuousVestingAccount { +) (*ContinuousVestingAccount, error) { baseVestingAcc := &BaseVestingAccount{ BaseAccount: baseAcc, OriginalVesting: originalVesting, EndTime: endTime, } - return &ContinuousVestingAccount{ + continuousVestingAccount := &ContinuousVestingAccount{ StartTime: startTime, BaseVestingAccount: baseVestingAcc, } + + return continuousVestingAccount, continuousVestingAccount.Validate() } // GetVestedCoins returns the total number of vested coins. If no coins are vested, @@ -289,32 +259,6 @@ func (cva ContinuousVestingAccount) Validate() error { return cva.BaseVestingAccount.Validate() } -func (cva ContinuousVestingAccount) String() string { - out, _ := cva.MarshalYAML() - return out.(string) -} - -// MarshalYAML returns the YAML representation of a ContinuousVestingAccount. -func (cva ContinuousVestingAccount) MarshalYAML() (interface{}, error) { - accAddr, err := sdk.AccAddressFromBech32(cva.Address) - if err != nil { - return nil, err - } - - out := vestingAccountYAML{ - Address: accAddr, - AccountNumber: cva.AccountNumber, - PublicKey: getPKString(cva), - Sequence: cva.Sequence, - OriginalVesting: cva.OriginalVesting, - DelegatedFree: cva.DelegatedFree, - DelegatedVesting: cva.DelegatedVesting, - EndTime: cva.EndTime, - StartTime: cva.StartTime, - } - return marshalYaml(out) -} - // Periodic Vesting Account var ( @@ -336,22 +280,25 @@ func NewPeriodicVestingAccount(baseAcc *authtypes.BaseAccount, originalVesting sdk.Coins, startTime int64, periods Periods, -) *PeriodicVestingAccount { +) (*PeriodicVestingAccount, error) { endTime := startTime for _, p := range periods { endTime += p.Length } + baseVestingAcc := &BaseVestingAccount{ BaseAccount: baseAcc, OriginalVesting: originalVesting, EndTime: endTime, } - return &PeriodicVestingAccount{ + periodicVestingAccount := &PeriodicVestingAccount{ BaseVestingAccount: baseVestingAcc, StartTime: startTime, VestingPeriods: periods, } + + return periodicVestingAccount, periodicVestingAccount.Validate() } // GetVestedCoins returns the total number of vested coins. If no coins are vested, @@ -424,47 +371,32 @@ func (pva PeriodicVestingAccount) Validate() error { } endTime := pva.StartTime originalVesting := sdk.NewCoins() - for _, p := range pva.VestingPeriods { + for i, p := range pva.VestingPeriods { + if p.Length < 0 { + return fmt.Errorf("period #%d has a negative length: %d", i, p.Length) + } endTime += p.Length + + if !p.Amount.IsValid() || !p.Amount.IsAllPositive() { + return fmt.Errorf("period #%d has invalid coins: %s", i, p.Amount.String()) + } + originalVesting = originalVesting.Add(p.Amount...) } if endTime != pva.EndTime { return errors.New("vesting end time does not match length of all vesting periods") } + if endTime < pva.GetStartTime() { + return errors.New("cumulative endTime overflowed, and/or is less than startTime") + } if !originalVesting.Equal(pva.OriginalVesting) { - return errors.New("original vesting coins does not match the sum of all coins in vesting periods") + return fmt.Errorf("original vesting coins (%v) does not match the sum of all coins in vesting periods (%v)", + pva.OriginalVesting, originalVesting) } return pva.BaseVestingAccount.Validate() } -func (pva PeriodicVestingAccount) String() string { - out, _ := pva.MarshalYAML() - return out.(string) -} - -// MarshalYAML returns the YAML representation of a PeriodicVestingAccount. -func (pva PeriodicVestingAccount) MarshalYAML() (interface{}, error) { - accAddr, err := sdk.AccAddressFromBech32(pva.Address) - if err != nil { - return nil, err - } - - out := vestingAccountYAML{ - Address: accAddr, - AccountNumber: pva.AccountNumber, - PublicKey: getPKString(pva), - Sequence: pva.Sequence, - OriginalVesting: pva.OriginalVesting, - DelegatedFree: pva.DelegatedFree, - DelegatedVesting: pva.DelegatedVesting, - EndTime: pva.EndTime, - StartTime: pva.StartTime, - VestingPeriods: pva.VestingPeriods, - } - return marshalYaml(out) -} - // Delayed Vesting Account var ( @@ -480,14 +412,19 @@ func NewDelayedVestingAccountRaw(bva *BaseVestingAccount) *DelayedVestingAccount } // NewDelayedVestingAccount returns a DelayedVestingAccount. -func NewDelayedVestingAccount(baseAcc *authtypes.BaseAccount, originalVesting sdk.Coins, endTime int64) *DelayedVestingAccount { +func NewDelayedVestingAccount(baseAcc *authtypes.BaseAccount, + originalVesting sdk.Coins, + endTime int64, +) (*DelayedVestingAccount, error) { baseVestingAcc := &BaseVestingAccount{ BaseAccount: baseAcc, OriginalVesting: originalVesting, EndTime: endTime, } - return &DelayedVestingAccount{baseVestingAcc} + delayedVestingAccount := &DelayedVestingAccount{baseVestingAcc} + + return delayedVestingAccount, delayedVestingAccount.Validate() } // GetVestedCoins returns the total amount of vested coins for a delayed vesting @@ -529,11 +466,6 @@ func (dva DelayedVestingAccount) Validate() error { return dva.BaseVestingAccount.Validate() } -func (dva DelayedVestingAccount) String() string { - out, _ := dva.MarshalYAML() - return out.(string) -} - //----------------------------------------------------------------------------- // Permanent Locked Vesting Account @@ -543,14 +475,16 @@ var ( ) // NewPermanentLockedAccount returns a PermanentLockedAccount. -func NewPermanentLockedAccount(baseAcc *authtypes.BaseAccount, coins sdk.Coins) *PermanentLockedAccount { +func NewPermanentLockedAccount(baseAcc *authtypes.BaseAccount, coins sdk.Coins) (*PermanentLockedAccount, error) { baseVestingAcc := &BaseVestingAccount{ BaseAccount: baseAcc, OriginalVesting: coins, EndTime: 0, // ensure EndTime is set to 0, as PermanentLockedAccount's do not have an EndTime } - return &PermanentLockedAccount{baseVestingAcc} + permanentLockedAccount := &PermanentLockedAccount{baseVestingAcc} + + return permanentLockedAccount, permanentLockedAccount.Validate() } // GetVestedCoins returns the total amount of vested coins for a permanent locked vesting @@ -598,11 +532,6 @@ func (plva PermanentLockedAccount) Validate() error { return plva.BaseVestingAccount.Validate() } -func (plva PermanentLockedAccount) String() string { - out, _ := plva.MarshalYAML() - return out.(string) -} - // Cliff Vesting Account var ( @@ -611,7 +540,7 @@ var ( ) // NewCliffVestingAccountRaw creates a new CliffVestingAccount object from BaseVestingAccount. -func NewCliffVestingAccountRaw(bva *BaseVestingAccount, startTime int64, cliffTime int64) *CliffVestingAccount { +func NewCliffVestingAccountRaw(bva *BaseVestingAccount, startTime, cliffTime int64) *CliffVestingAccount { return &CliffVestingAccount{ BaseVestingAccount: bva, StartTime: startTime, @@ -623,18 +552,20 @@ func NewCliffVestingAccountRaw(bva *BaseVestingAccount, startTime int64, cliffTi func NewCliffVestingAccount(baseAcc *authtypes.BaseAccount, originalVesting sdk.Coins, startTime, cliffTime, endTime int64, -) *CliffVestingAccount { +) (*CliffVestingAccount, error) { baseVestingAcc := &BaseVestingAccount{ BaseAccount: baseAcc, OriginalVesting: originalVesting, EndTime: endTime, } - return &CliffVestingAccount{ + cliffVestingAccount := &CliffVestingAccount{ StartTime: startTime, CliffTime: cliffTime, BaseVestingAccount: baseVestingAcc, } + + return cliffVestingAccount, cliffVestingAccount.Validate() } // GetVestedCoins returns the total number of vested coins. If no coins are vested, @@ -683,7 +614,7 @@ func (cva *CliffVestingAccount) TrackDelegation(blockTime time.Time, balance, am cva.BaseVestingAccount.TrackDelegation(balance, cva.GetVestingCoins(blockTime), amount) } -// GetStartTime returns the time when vesting starts for a cliff vesting +// GetStartTime returns the time when vesting starts for a continuous vesting // account. func (cva CliffVestingAccount) GetStartTime() int64 { return cva.StartTime @@ -698,7 +629,7 @@ func (cva CliffVestingAccount) GetCliffTime() int64 { // Validate checks for errors on the account fields. func (cva CliffVestingAccount) Validate() error { if cva.GetStartTime() >= cva.GetEndTime() { - return errors.New("vesting start-time cannot be after end-time") + return errors.New("vesting start-time cannot be before end-time") } if cva.GetStartTime() >= cva.GetCliffTime() { return errors.New("vesting start-time cannot be after cliff-time") @@ -709,49 +640,3 @@ func (cva CliffVestingAccount) Validate() error { return cva.BaseVestingAccount.Validate() } - -func (cva CliffVestingAccount) String() string { - out, _ := cva.MarshalYAML() - return out.(string) -} - -// MarshalYAML returns the YAML representation of a ContinuousVestingAccount. -func (cva CliffVestingAccount) MarshalYAML() (interface{}, error) { - accAddr, err := sdk.AccAddressFromBech32(cva.Address) - if err != nil { - return nil, err - } - - out := vestingAccountYAML{ - Address: accAddr, - AccountNumber: cva.AccountNumber, - PublicKey: getPKString(cva), - Sequence: cva.Sequence, - OriginalVesting: cva.OriginalVesting, - DelegatedFree: cva.DelegatedFree, - DelegatedVesting: cva.DelegatedVesting, - EndTime: cva.EndTime, - StartTime: cva.StartTime, - CliffTime: cva.CliffTime, - } - return marshalYaml(out) -} - -type getPK interface { - GetPubKey() cryptotypes.PubKey -} - -func getPKString(g getPK) string { - if pk := g.GetPubKey(); pk != nil { - return pk.String() - } - return "" -} - -func marshalYaml(i interface{}) (interface{}, error) { - bz, err := yaml.Marshal(i) - if err != nil { - return nil, err - } - return string(bz), nil -} diff --git a/x/vesting/types/vesting_account_test.go b/x/vesting/types/vesting_account_test.go index 1581b343..6a5e40d2 100644 --- a/x/vesting/types/vesting_account_test.go +++ b/x/vesting/types/vesting_account_test.go @@ -1,3 +1,4 @@ +//nolint:lll package types_test import ( @@ -7,9 +8,9 @@ import ( "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" - cmtproto "github.com/cometbft/cometbft/proto/tendermint/types" tmtime "github.com/cometbft/cometbft/types/time" + "cosmossdk.io/core/header" storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" @@ -43,8 +44,9 @@ func (s *VestingAccountTestSuite) SetupTest() { encCfg := moduletestutil.MakeTestEncodingConfig(vesting.AppModuleBasic{}) key := storetypes.NewKVStoreKey(authtypes.StoreKey) + storeService := runtime.NewKVStoreService(key) testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test")) - s.ctx = testCtx.Ctx.WithBlockHeader(cmtproto.Header{}) + s.ctx = testCtx.Ctx.WithHeaderInfo(header.Info{}) maccPerms := map[string][]string{ "fee_collector": nil, @@ -57,7 +59,7 @@ func (s *VestingAccountTestSuite) SetupTest() { s.accountKeeper = keeper.NewAccountKeeper( encCfg.Codec, - runtime.NewKVStoreService(key), + storeService, authtypes.ProtoBaseAccount, maccPerms, authcodec.NewBech32Codec("cosmos"), @@ -71,7 +73,8 @@ func TestGetVestedCoinsContVestingAcc(t *testing.T) { endTime := now.Add(24 * time.Hour) bacc, origCoins := initBaseAccount() - cva := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) // require no coins vested in the very beginning of the vesting schedule vestedCoins := cva.GetVestedCoins(now) @@ -95,7 +98,8 @@ func TestGetVestingCoinsContVestingAcc(t *testing.T) { endTime := now.Add(24 * time.Hour) bacc, origCoins := initBaseAccount() - cva := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) // require all coins vesting in the beginning of the vesting schedule vestingCoins := cva.GetVestingCoins(now) @@ -115,7 +119,8 @@ func TestSpendableCoinsContVestingAcc(t *testing.T) { endTime := now.Add(24 * time.Hour) bacc, origCoins := initBaseAccount() - cva := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) // require that all original coins are locked at the end of the vesting // schedule @@ -138,19 +143,22 @@ func TestTrackDelegationContVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require the ability to delegate all vesting coins - cva := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) cva.TrackDelegation(now, origCoins, origCoins) require.Equal(t, origCoins, cva.DelegatedVesting) require.Nil(t, cva.DelegatedFree) // require the ability to delegate all vested coins - cva = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) cva.TrackDelegation(endTime, origCoins, origCoins) require.Nil(t, cva.DelegatedVesting) require.Equal(t, origCoins, cva.DelegatedFree) // require the ability to delegate all vesting coins (50%) and all vested coins (50%) - cva = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) cva.TrackDelegation(now.Add(12*time.Hour), origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) require.Equal(t, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}, cva.DelegatedVesting) require.Nil(t, cva.DelegatedFree) @@ -160,7 +168,8 @@ func TestTrackDelegationContVestingAcc(t *testing.T) { require.Equal(t, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}, cva.DelegatedFree) // require no modifications when delegation amount is zero or not enough funds - cva = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) require.Panics(t, func() { cva.TrackDelegation(endTime, origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 1000000)}) }) @@ -175,23 +184,24 @@ func TestTrackUndelegationContVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require the ability to undelegate all vesting coins - cva := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err := types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) cva.TrackDelegation(now, origCoins, origCoins) cva.TrackUndelegation(origCoins) require.Nil(t, cva.DelegatedFree) require.Equal(t, emptyCoins, cva.DelegatedVesting) // require the ability to undelegate all vested coins - cva = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) - + cva, err = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) cva.TrackDelegation(endTime, origCoins, origCoins) cva.TrackUndelegation(origCoins) require.Equal(t, emptyCoins, cva.DelegatedFree) require.Nil(t, cva.DelegatedVesting) // require no modifications when the undelegation amount is zero - cva = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) - + cva, err = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) require.Panics(t, func() { cva.TrackUndelegation(sdk.Coins{sdk.NewInt64Coin(stakeDenom, 0)}) }) @@ -199,7 +209,8 @@ func TestTrackUndelegationContVestingAcc(t *testing.T) { require.Nil(t, cva.DelegatedVesting) // vest 50% and delegate to two validators - cva = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + cva, err = types.NewContinuousVestingAccount(bacc, origCoins, now.Unix(), endTime.Unix()) + require.NoError(t, err) cva.TrackDelegation(now.Add(12*time.Hour), origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) cva.TrackDelegation(now.Add(12*time.Hour), origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) @@ -221,7 +232,8 @@ func TestGetVestedCoinsDelVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require no coins are vested until schedule maturation - dva := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) vestedCoins := dva.GetVestedCoins(now) require.Nil(t, vestedCoins) @@ -237,7 +249,8 @@ func TestGetVestingCoinsDelVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require all coins vesting at the beginning of the schedule - dva := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) vestingCoins := dva.GetVestingCoins(now) require.Equal(t, origCoins, vestingCoins) @@ -254,7 +267,8 @@ func TestSpendableCoinsDelVestingAcc(t *testing.T) { // require that all coins are locked in the beginning of the vesting // schedule - dva := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) lockedCoins := dva.LockedCoins(now) require.True(t, lockedCoins.Equal(origCoins)) @@ -282,27 +296,30 @@ func TestTrackDelegationDelVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require the ability to delegate all vesting coins - dva := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) dva.TrackDelegation(now, origCoins, origCoins) require.Equal(t, origCoins, dva.DelegatedVesting) require.Nil(t, dva.DelegatedFree) // require the ability to delegate all vested coins - dva = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) dva.TrackDelegation(endTime, origCoins, origCoins) require.Nil(t, dva.DelegatedVesting) require.Equal(t, origCoins, dva.DelegatedFree) // require the ability to delegate all coins half way through the vesting // schedule - dva = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) dva.TrackDelegation(now.Add(12*time.Hour), origCoins, origCoins) require.Equal(t, origCoins, dva.DelegatedVesting) require.Nil(t, dva.DelegatedFree) // require no modifications when delegation amount is zero or not enough funds - dva = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) - + dva, err = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) require.Panics(t, func() { dva.TrackDelegation(endTime, origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 1000000)}) }) @@ -317,22 +334,24 @@ func TestTrackUndelegationDelVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require the ability to undelegate all vesting coins - dva := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err := types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) dva.TrackDelegation(now, origCoins, origCoins) dva.TrackUndelegation(origCoins) require.Nil(t, dva.DelegatedFree) require.Equal(t, emptyCoins, dva.DelegatedVesting) // require the ability to undelegate all vested coins - dva = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) dva.TrackDelegation(endTime, origCoins, origCoins) dva.TrackUndelegation(origCoins) require.Equal(t, emptyCoins, dva.DelegatedFree) require.Nil(t, dva.DelegatedVesting) // require no modifications when the undelegation amount is zero - dva = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) - + dva, err = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) require.Panics(t, func() { dva.TrackUndelegation(sdk.Coins{sdk.NewInt64Coin(stakeDenom, 0)}) }) @@ -340,7 +359,8 @@ func TestTrackUndelegationDelVestingAcc(t *testing.T) { require.Nil(t, dva.DelegatedVesting) // vest 50% and delegate to two validators - dva = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + dva, err = types.NewDelayedVestingAccount(bacc, origCoins, endTime.Unix()) + require.NoError(t, err) dva.TrackDelegation(now.Add(12*time.Hour), origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) dva.TrackDelegation(now.Add(12*time.Hour), origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) @@ -366,7 +386,8 @@ func TestGetVestedCoinsPeriodicVestingAcc(t *testing.T) { } bacc, origCoins := initBaseAccount() - pva := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) // require no coins vested at the beginning of the vesting schedule vestedCoins := pva.GetVestedCoins(now) @@ -400,6 +421,57 @@ func TestGetVestedCoinsPeriodicVestingAcc(t *testing.T) { require.Equal(t, origCoins, vestedCoins) } +func TestOverflowAndNegativeVestedCoinsPeriods(t *testing.T) { + now := tmtime.Now() + tests := []struct { + name string + periods []types.Period + wantErr string + }{ + { + "negative .Length", + types.Periods{ + types.Period{Length: -1, Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 500), sdk.NewInt64Coin(stakeDenom, 50)}}, + types.Period{Length: 6 * 60 * 60, Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 250), sdk.NewInt64Coin(stakeDenom, 25)}}, + }, + "period #0 has a negative length: -1", + }, + { + "overflow after .Length additions", + types.Periods{ + types.Period{Length: 9223372036854775108, Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 500), sdk.NewInt64Coin(stakeDenom, 50)}}, + types.Period{Length: 6 * 60 * 60, Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 250), sdk.NewInt64Coin(stakeDenom, 25)}}, + }, + "vesting start-time cannot be before end-time", // it overflow to a negative number, making start-time > end-time + }, + { + "good periods that are not negative nor overflow", + types.Periods{ + types.Period{Length: now.Unix() - 1000, Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 500), sdk.NewInt64Coin(stakeDenom, 50)}}, + types.Period{Length: 60, Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 250), sdk.NewInt64Coin(stakeDenom, 25)}}, + types.Period{Length: 30, Amount: sdk.Coins{sdk.NewInt64Coin(feeDenom, 250), sdk.NewInt64Coin(stakeDenom, 25)}}, + }, + "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + bacc, origCoins := initBaseAccount() + pva, err := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), tt.periods) + if tt.wantErr != "" { + require.ErrorContains(t, err, tt.wantErr) + return + } + + require.NoError(t, err) + if pbva := pva.BaseVestingAccount; pbva.EndTime < 0 { + t.Fatalf("Unfortunately we still have negative .EndTime :-(: %d", pbva.EndTime) + } + }) + } +} + func TestGetVestingCoinsPeriodicVestingAcc(t *testing.T) { now := tmtime.Now() endTime := now.Add(24 * time.Hour) @@ -410,7 +482,8 @@ func TestGetVestingCoinsPeriodicVestingAcc(t *testing.T) { } bacc, origCoins := initBaseAccount() - pva := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) // require all coins vesting at the beginning of the vesting schedule vestingCoins := pva.GetVestingCoins(now) @@ -447,7 +520,8 @@ func TestSpendableCoinsPeriodicVestingAcc(t *testing.T) { } bacc, origCoins := initBaseAccount() - pva := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) // require that there exist no spendable coins at the beginning of the // vesting schedule @@ -476,33 +550,38 @@ func TestTrackDelegationPeriodicVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require the ability to delegate all vesting coins - pva := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(now, origCoins, origCoins) require.Equal(t, origCoins, pva.DelegatedVesting) require.Nil(t, pva.DelegatedFree) // require the ability to delegate all vested coins - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(endTime, origCoins, origCoins) require.Nil(t, pva.DelegatedVesting) require.Equal(t, origCoins, pva.DelegatedFree) // delegate half of vesting coins - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(now, origCoins, periods[0].Amount) // require that all delegated coins are delegated vesting require.Equal(t, pva.DelegatedVesting, periods[0].Amount) require.Nil(t, pva.DelegatedFree) // delegate 75% of coins, split between vested and vesting - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(now.Add(12*time.Hour), origCoins, periods[0].Amount.Add(periods[1].Amount...)) // require that the maximum possible amount of vesting coins are chosen for delegation. require.Equal(t, pva.DelegatedFree, periods[1].Amount) require.Equal(t, pva.DelegatedVesting, periods[0].Amount) // require the ability to delegate all vesting coins (50%) and all vested coins (50%) - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(now.Add(12*time.Hour), origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) require.Equal(t, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}, pva.DelegatedVesting) require.Nil(t, pva.DelegatedFree) @@ -512,7 +591,8 @@ func TestTrackDelegationPeriodicVestingAcc(t *testing.T) { require.Equal(t, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}, pva.DelegatedFree) // require no modifications when delegation amount is zero or not enough funds - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) require.Panics(t, func() { pva.TrackDelegation(endTime, origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 1000000)}) }) @@ -532,30 +612,32 @@ func TestTrackUndelegationPeriodicVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require the ability to undelegate all vesting coins at the beginning of vesting - pva := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err := types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(now, origCoins, origCoins) pva.TrackUndelegation(origCoins) require.Nil(t, pva.DelegatedFree) require.Equal(t, emptyCoins, pva.DelegatedVesting) // require the ability to undelegate all vested coins at the end of vesting - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) - + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(endTime, origCoins, origCoins) pva.TrackUndelegation(origCoins) require.Equal(t, emptyCoins, pva.DelegatedFree) require.Nil(t, pva.DelegatedVesting) // require the ability to undelegate half of coins - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(endTime, origCoins, periods[0].Amount) pva.TrackUndelegation(periods[0].Amount) require.Equal(t, emptyCoins, pva.DelegatedFree) require.Nil(t, pva.DelegatedVesting) // require no modifications when the undelegation amount is zero - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) - + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) require.Panics(t, func() { pva.TrackUndelegation(sdk.Coins{sdk.NewInt64Coin(stakeDenom, 0)}) }) @@ -563,7 +645,8 @@ func TestTrackUndelegationPeriodicVestingAcc(t *testing.T) { require.Nil(t, pva.DelegatedVesting) // vest 50% and delegate to two validators - pva = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + pva, err = types.NewPeriodicVestingAccount(bacc, origCoins, now.Unix(), periods) + require.NoError(t, err) pva.TrackDelegation(now.Add(12*time.Hour), origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) pva.TrackDelegation(now.Add(12*time.Hour), origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) @@ -585,7 +668,8 @@ func TestGetVestedCoinsPermLockedVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require no coins are vested - plva := types.NewPermanentLockedAccount(bacc, origCoins) + plva, err := types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) vestedCoins := plva.GetVestedCoins(now) require.Nil(t, vestedCoins) @@ -601,7 +685,8 @@ func TestGetVestingCoinsPermLockedVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require all coins vesting at the beginning of the schedule - plva := types.NewPermanentLockedAccount(bacc, origCoins) + plva, err := types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) vestingCoins := plva.GetVestingCoins(now) require.Equal(t, origCoins, vestingCoins) @@ -618,7 +703,8 @@ func TestSpendableCoinsPermLockedVestingAcc(t *testing.T) { // require that all coins are locked in the beginning of the vesting // schedule - plva := types.NewPermanentLockedAccount(bacc, origCoins) + plva, err := types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) lockedCoins := plva.LockedCoins(now) require.True(t, lockedCoins.Equal(origCoins)) @@ -641,20 +727,22 @@ func TestTrackDelegationPermLockedVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require the ability to delegate all vesting coins - plva := types.NewPermanentLockedAccount(bacc, origCoins) + plva, err := types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) plva.TrackDelegation(now, origCoins, origCoins) require.Equal(t, origCoins, plva.DelegatedVesting) require.Nil(t, plva.DelegatedFree) // require the ability to delegate all vested coins at endTime - plva = types.NewPermanentLockedAccount(bacc, origCoins) + plva, err = types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) plva.TrackDelegation(endTime, origCoins, origCoins) require.Equal(t, origCoins, plva.DelegatedVesting) require.Nil(t, plva.DelegatedFree) // require no modifications when delegation amount is zero or not enough funds - plva = types.NewPermanentLockedAccount(bacc, origCoins) - + plva, err = types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) require.Panics(t, func() { plva.TrackDelegation(endTime, origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 1000000)}) }) @@ -669,21 +757,24 @@ func TestTrackUndelegationPermLockedVestingAcc(t *testing.T) { bacc, origCoins := initBaseAccount() // require the ability to undelegate all vesting coins - plva := types.NewPermanentLockedAccount(bacc, origCoins) + plva, err := types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) plva.TrackDelegation(now, origCoins, origCoins) plva.TrackUndelegation(origCoins) require.Nil(t, plva.DelegatedFree) require.Equal(t, emptyCoins, plva.DelegatedVesting) // require the ability to undelegate all vesting coins at endTime - plva = types.NewPermanentLockedAccount(bacc, origCoins) + plva, err = types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) plva.TrackDelegation(endTime, origCoins, origCoins) plva.TrackUndelegation(origCoins) require.Nil(t, plva.DelegatedFree) require.Equal(t, emptyCoins, plva.DelegatedVesting) // require no modifications when the undelegation amount is zero - plva = types.NewPermanentLockedAccount(bacc, origCoins) + plva, err = types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) require.Panics(t, func() { plva.TrackUndelegation(sdk.Coins{sdk.NewInt64Coin(stakeDenom, 0)}) }) @@ -691,7 +782,8 @@ func TestTrackUndelegationPermLockedVestingAcc(t *testing.T) { require.Nil(t, plva.DelegatedVesting) // delegate to two validators - plva = types.NewPermanentLockedAccount(bacc, origCoins) + plva, err = types.NewPermanentLockedAccount(bacc, origCoins) + require.NoError(t, err) plva.TrackDelegation(now, origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) plva.TrackDelegation(now, origCoins, sdk.Coins{sdk.NewInt64Coin(stakeDenom, 50)}) @@ -712,7 +804,8 @@ func TestGenesisAccountValidate(t *testing.T) { addr := sdk.AccAddress(pubkey.Address()) baseAcc := authtypes.NewBaseAccount(addr, pubkey, 0, 0) initialVesting := sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 50)) - baseVestingWithCoins := types.NewBaseVestingAccount(baseAcc, initialVesting, 100) + baseVestingWithCoins, err := types.NewBaseVestingAccount(baseAcc, initialVesting, 100) + require.NoError(t, err) tests := []struct { name string acc authtypes.GenesisAccount @@ -735,25 +828,26 @@ func TestGenesisAccountValidate(t *testing.T) { }, { "valid continuous vesting account", - types.NewContinuousVestingAccount(baseAcc, initialVesting, 100, 200), + func() authtypes.GenesisAccount { + acc, _ := types.NewContinuousVestingAccount(baseAcc, initialVesting, 100, 200) + return acc + }(), false, }, { "invalid vesting times", - types.NewContinuousVestingAccount(baseAcc, initialVesting, 1654668078, 1554668078), + func() authtypes.GenesisAccount { + acc, _ := types.NewContinuousVestingAccount(baseAcc, initialVesting, 1654668078, 1554668078) + return acc + }(), true, }, { "valid periodic vesting account", - types.NewPeriodicVestingAccount(baseAcc, - initialVesting, - 0, - types.Periods{ - types.Period{ - Length: int64(100), - Amount: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 50)}, - }, - }), + func() authtypes.GenesisAccount { + acc, _ := types.NewPeriodicVestingAccount(baseAcc, initialVesting, 0, types.Periods{types.Period{Length: int64(100), Amount: sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 50)}}}) + return acc + }(), false, }, { @@ -772,7 +866,10 @@ func TestGenesisAccountValidate(t *testing.T) { }, { "valid permanent locked vesting account", - types.NewPermanentLockedAccount(baseAcc, initialVesting), + func() authtypes.GenesisAccount { + acc, _ := types.NewPermanentLockedAccount(baseAcc, initialVesting) + return acc + }(), false, }, {