From 7fe1154e41ac4f2d2817cac6a398bbce34b93458 Mon Sep 17 00:00:00 2001 From: Raul Bernal Date: Thu, 21 Mar 2024 13:55:01 +0100 Subject: [PATCH 1/7] Add param burn_denom to module --- docs/static/openapi.yml | 12 +++++++ proto/bcna/burn/params.proto | 1 + x/burn/keeper/params.go | 5 +-- x/burn/types/params.go | 49 ++++++++++++++++++++----- x/burn/types/params.pb.go | 69 +++++++++++++++++++++++++++++++----- 5 files changed, 118 insertions(+), 18 deletions(-) diff --git a/docs/static/openapi.yml b/docs/static/openapi.yml index 5e8022e5..aaf88995 100644 --- a/docs/static/openapi.yml +++ b/docs/static/openapi.yml @@ -17,6 +17,10 @@ paths: params: description: params holds all the parameters of this module. type: object + properties: + burn_denom: + type: string + title: denom allowed to be burned description: >- QueryParamsResponse is response type for the Query/Params RPC method. @@ -46923,6 +46927,10 @@ definitions: type: object bcna.burn.Params: type: object + properties: + burn_denom: + type: string + title: denom allowed to be burned description: Params defines the parameters for the module. bcna.burn.QueryParamsResponse: type: object @@ -46930,6 +46938,10 @@ definitions: params: description: params holds all the parameters of this module. type: object + properties: + burn_denom: + type: string + title: denom allowed to be burned description: QueryParamsResponse is response type for the Query/Params RPC method. cosmos.base.v1beta1.Coin: type: object diff --git a/proto/bcna/burn/params.proto b/proto/bcna/burn/params.proto index a4483e81..af588ef4 100644 --- a/proto/bcna/burn/params.proto +++ b/proto/bcna/burn/params.proto @@ -8,5 +8,6 @@ option go_package = "github.com/BitCannaGlobal/bcna/x/burn/types"; // Params defines the parameters for the module. message Params { option (gogoproto.goproto_stringer) = false; + string burn_denom = 1; // denom allowed to be burned } diff --git a/x/burn/keeper/params.go b/x/burn/keeper/params.go index a4078815..5fa339a2 100644 --- a/x/burn/keeper/params.go +++ b/x/burn/keeper/params.go @@ -6,8 +6,9 @@ import ( ) // GetParams get all parameters as types.Params -func (k Keeper) GetParams(ctx sdk.Context) types.Params { - return types.NewParams() +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + k.paramstore.GetParamSet(ctx, ¶ms) + return params } // SetParams set the params diff --git a/x/burn/types/params.go b/x/burn/types/params.go index 357196ad..25d4458a 100644 --- a/x/burn/types/params.go +++ b/x/burn/types/params.go @@ -1,34 +1,67 @@ package types import ( + "fmt" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" "gopkg.in/yaml.v2" ) var _ paramtypes.ParamSet = (*Params)(nil) -// ParamKeyTable the param key table for launch module -func ParamKeyTable() paramtypes.KeyTable { - return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) -} +// Keys for parameter access +var ( + KeyBurnDenom = []byte("BurnDenom") +) + +// // Params defines the parameters for the module. +// type Params struct { +// BurnDenom string `json:"burn_denom" yaml:"burn_denom"` +// } // NewParams creates a new Params instance -func NewParams() Params { - return Params{} +func NewParams(burnDenom string) Params { + return Params{ + BurnDenom: burnDenom, + } } // DefaultParams returns a default set of parameters func DefaultParams() Params { - return NewParams() + return Params{ + BurnDenom: "ubcna", + } +} + +// ParamKeyTable the param key table for the module +func ParamKeyTable() paramtypes.KeyTable { + return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) } // ParamSetPairs get the params.ParamSet func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { - return paramtypes.ParamSetPairs{} + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair(KeyBurnDenom, &p.BurnDenom, validateBurnDenom), + } } // Validate validates the set of params func (p Params) Validate() error { + if err := validateBurnDenom(p.BurnDenom); err != nil { + return err + } + return nil +} + +// ValidateBurnDenom validates the BurnDenom parameter +func validateBurnDenom(i interface{}) error { + v, ok := i.(string) + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + if v == "" { + return fmt.Errorf("burn denom cannot be empty") + } return nil } diff --git a/x/burn/types/params.pb.go b/x/burn/types/params.pb.go index 4a71eb5e..f231d374 100644 --- a/x/burn/types/params.pb.go +++ b/x/burn/types/params.pb.go @@ -25,6 +25,7 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package // Params defines the parameters for the module. type Params struct { + BurnDenom string `protobuf:"bytes,1,opt,name=burn_denom,json=burnDenom,proto3" json:"burn_denom,omitempty"` } func (m *Params) Reset() { *m = Params{} } @@ -59,6 +60,13 @@ func (m *Params) XXX_DiscardUnknown() { var xxx_messageInfo_Params proto.InternalMessageInfo +func (m *Params) GetBurnDenom() string { + if m != nil { + return m.BurnDenom + } + return "" +} + func init() { proto.RegisterType((*Params)(nil), "bcna.burn.Params") } @@ -66,17 +74,19 @@ func init() { func init() { proto.RegisterFile("bcna/burn/params.proto", fileDescriptor_93e0b1c02465615e) } var fileDescriptor_93e0b1c02465615e = []byte{ - // 152 bytes of a gzipped FileDescriptorProto + // 177 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4b, 0x4a, 0xce, 0x4b, 0xd4, 0x4f, 0x2a, 0x2d, 0xca, 0xd3, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x04, 0x89, 0xeb, 0x81, 0xc4, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, - 0xa2, 0xfa, 0x20, 0x16, 0x44, 0x81, 0x12, 0x1f, 0x17, 0x5b, 0x00, 0x58, 0x83, 0x15, 0xcb, 0x8c, - 0x05, 0xf2, 0x0c, 0x4e, 0xae, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, 0xf8, 0xe0, 0x91, - 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, - 0x9d, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0xef, 0x94, 0x59, 0xe2, 0x9c, - 0x98, 0x97, 0x97, 0xe8, 0x9e, 0x93, 0x9f, 0x94, 0x98, 0xa3, 0x0f, 0xb6, 0xbc, 0x02, 0x62, 0x7d, - 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x74, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, - 0x8f, 0x08, 0x19, 0xb2, 0x98, 0x00, 0x00, 0x00, + 0xa2, 0xfa, 0x20, 0x16, 0x44, 0x81, 0x92, 0x2e, 0x17, 0x5b, 0x00, 0x58, 0x83, 0x90, 0x2c, 0x17, + 0x17, 0x48, 0x5d, 0x7c, 0x4a, 0x6a, 0x5e, 0x7e, 0xae, 0x04, 0xa3, 0x02, 0xa3, 0x06, 0x67, 0x10, + 0x27, 0x48, 0xc4, 0x05, 0x24, 0x60, 0xc5, 0x32, 0x63, 0x81, 0x3c, 0x83, 0x93, 0xeb, 0x89, 0x47, + 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, + 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa7, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, + 0x25, 0xe7, 0xe7, 0xea, 0x3b, 0x65, 0x96, 0x38, 0x27, 0xe6, 0xe5, 0x25, 0xba, 0xe7, 0xe4, 0x27, + 0x25, 0xe6, 0xe8, 0x83, 0xdd, 0x56, 0x01, 0x71, 0x5d, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, + 0xd8, 0x72, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x83, 0x1f, 0xae, 0x50, 0xb7, 0x00, 0x00, + 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -99,6 +109,13 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.BurnDenom) > 0 { + i -= len(m.BurnDenom) + copy(dAtA[i:], m.BurnDenom) + i = encodeVarintParams(dAtA, i, uint64(len(m.BurnDenom))) + i-- + dAtA[i] = 0xa + } return len(dAtA) - i, nil } @@ -119,6 +136,10 @@ func (m *Params) Size() (n int) { } var l int _ = l + l = len(m.BurnDenom) + if l > 0 { + n += 1 + l + sovParams(uint64(l)) + } return n } @@ -157,6 +178,38 @@ func (m *Params) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field BurnDenom", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.BurnDenom = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) From a3a54ebac97edce34a9ae0202e9d489554509306 Mon Sep 17 00:00:00 2001 From: Raul Bernal Date: Fri, 22 Mar 2024 10:27:59 +0100 Subject: [PATCH 2/7] Remove deprecation in App.go --- app/app.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/app.go b/app/app.go index f530b1a5..d31fc190 100644 --- a/app/app.go +++ b/app/app.go @@ -67,7 +67,6 @@ import ( govclient "github.com/cosmos/cosmos-sdk/x/gov/client" govkeeper "github.com/cosmos/cosmos-sdk/x/gov/keeper" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" - govv1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1" govv1beta1 "github.com/cosmos/cosmos-sdk/x/gov/types/v1beta1" "github.com/cosmos/cosmos-sdk/x/group" groupkeeper "github.com/cosmos/cosmos-sdk/x/group/keeper" @@ -956,7 +955,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(minttypes.ModuleName) paramsKeeper.Subspace(distrtypes.ModuleName) paramsKeeper.Subspace(slashingtypes.ModuleName) - paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1.ParamKeyTable()) //nolint:staticcheck + paramsKeeper.Subspace(govtypes.ModuleName) //.WithKeyTable(govv1.ParamKeyTable()) //nolint: staticcheck // SA1019 //https://github.com/cosmos/cosmos-sdk/discussions/19832 paramsKeeper.Subspace(crisistypes.ModuleName) paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(ibcexported.ModuleName) From 5368c1dd5ca1a7fca7f5e4baadaebcbf5ff965f2 Mon Sep 17 00:00:00 2001 From: Raul Bernal Date: Fri, 22 Mar 2024 10:29:19 +0100 Subject: [PATCH 3/7] Allow 1 denom in place of list of denoms --- proto/bcna/burn/tx.proto | 4 +- x/burn/client/cli/tx_burn_coins_action.go | 9 ++- x/burn/keeper/msg_server_burn_coins_action.go | 34 ++++---- x/burn/types/message_burn_coins_action.go | 9 ++- .../types/message_burn_coins_action_test.go | 4 +- x/burn/types/tx.pb.go | 79 ++++++++----------- 6 files changed, 66 insertions(+), 73 deletions(-) diff --git a/proto/bcna/burn/tx.proto b/proto/bcna/burn/tx.proto index 9b962cd0..b521defb 100644 --- a/proto/bcna/burn/tx.proto +++ b/proto/bcna/burn/tx.proto @@ -12,8 +12,8 @@ service Msg { rpc BurnCoinsAction (MsgBurnCoinsAction) returns (MsgBurnCoinsActionResponse); } message MsgBurnCoinsAction { - string creator = 1; - repeated cosmos.base.v1beta1.Coin coins = 2 [(gogoproto.nullable) = false]; + string creator = 1; + cosmos.base.v1beta1.Coin amount = 2 [(gogoproto.nullable) = false]; // Now is only one coin not a list of coins } message MsgBurnCoinsActionResponse {} diff --git a/x/burn/client/cli/tx_burn_coins_action.go b/x/burn/client/cli/tx_burn_coins_action.go index 33f8515d..d727c1c2 100644 --- a/x/burn/client/cli/tx_burn_coins_action.go +++ b/x/burn/client/cli/tx_burn_coins_action.go @@ -1,6 +1,7 @@ package cli import ( + "fmt" "strconv" "github.com/BitCannaGlobal/bcna/x/burn/types" @@ -19,14 +20,14 @@ func CmdBurnCoinsAction() *cobra.Command { Short: "Broadcast message BurnCoinsAction", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) (err error) { - argCoins, err := sdk.ParseCoinsNormalized(args[0]) + argCoins, err := sdk.ParseCoinNormalized(args[0]) if err != nil { - return err + return fmt.Errorf("failed to parse coin: %w", err) } clientCtx, err := client.GetClientTxContext(cmd) if err != nil { - return err + return fmt.Errorf("failed to get client context: %w", err) } msg := types.NewMsgBurnCoinsAction( @@ -34,7 +35,7 @@ func CmdBurnCoinsAction() *cobra.Command { argCoins, ) if err := msg.ValidateBasic(); err != nil { - return err + return fmt.Errorf("message validation failed: %w", err) } return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) }, diff --git a/x/burn/keeper/msg_server_burn_coins_action.go b/x/burn/keeper/msg_server_burn_coins_action.go index 754752ed..d74205b4 100644 --- a/x/burn/keeper/msg_server_burn_coins_action.go +++ b/x/burn/keeper/msg_server_burn_coins_action.go @@ -16,34 +16,32 @@ func (k msgServer) BurnCoinsAction(goCtx context.Context, msg *types.MsgBurnCoin if err != nil { return nil, fmt.Errorf("the address is not valid") } - - // Check nulls and valid amounts - if msg.Coins == nil || len(msg.Coins) == 0 { - return nil, fmt.Errorf("no coins specified or the amount is not valid") + // Get the module's params to verify the allowed denom + params := k.GetParams(ctx) + if msg.Amount.Denom != params.BurnDenom { + return nil, fmt.Errorf("denomination mismatch: expected %s, got %s", params.BurnDenom, msg.Amount.Denom) } - for _, coin := range msg.Coins { - if coin.Amount.LTE(sdk.ZeroInt()) { // Comprueba si la cantidad es menor o igual a cero. - return nil, fmt.Errorf("invalid amount for coin %s, amount must be positive", coin.Denom) - } + // Check if it is a valid amount + if msg.Amount.IsZero() || msg.Amount.IsNegative() { + return nil, fmt.Errorf("invalid amount: %s", msg.Amount.String()) } // Gets the balance of the sender to check if are there enough coins. - for _, coin := range msg.Coins { - balance := k.bankKeeper.GetBalance(ctx, creatorAddr, coin.Denom) - if balance.Amount.LT(coin.Amount) { - return nil, fmt.Errorf("insufficient balance for coin %s", coin.Denom) - } + balance := k.bankKeeper.GetBalance(ctx, creatorAddr, msg.Amount.Denom) + if balance.Amount.LT(msg.Amount.Amount) { + return nil, fmt.Errorf("insufficient balance for %s", msg.Amount.Denom) } - if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, creatorAddr, types.ModuleName, msg.Coins); err != nil { - return nil, err + // Send the coins from the creator to the module and later it burns + if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, creatorAddr, types.ModuleName, sdk.NewCoins(msg.Amount)); err != nil { + return nil, fmt.Errorf("failed to send coins from account to module: %v", err) } - if err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, msg.Coins); err != nil { - return nil, err + if err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(msg.Amount)); err != nil { + return nil, fmt.Errorf("failed to burn coins: %v", err) } // Log the successful burn operation - k.Logger(ctx).Info("Burning coins!! ", "signer", msg.Creator, "amount", msg.Coins) + k.Logger(ctx).Info("Burning coins!! ", "signer", msg.Creator, "amount", msg.Amount) return &types.MsgBurnCoinsActionResponse{}, nil } diff --git a/x/burn/types/message_burn_coins_action.go b/x/burn/types/message_burn_coins_action.go index f5c700e8..ac36fa6b 100644 --- a/x/burn/types/message_burn_coins_action.go +++ b/x/burn/types/message_burn_coins_action.go @@ -11,10 +11,10 @@ const TypeMsgBurnCoinsAction = "burn_coins_action" var _ sdk.Msg = &MsgBurnCoinsAction{} -func NewMsgBurnCoinsAction(creator string, coins sdk.Coins) *MsgBurnCoinsAction { +func NewMsgBurnCoinsAction(creator string, amount sdk.Coin) *MsgBurnCoinsAction { return &MsgBurnCoinsAction{ Creator: creator, - Coins: coins, + Amount: amount, } } @@ -39,10 +39,13 @@ func (msg *MsgBurnCoinsAction) GetSignBytes() []byte { return sdk.MustSortJSON(bz) } -func (msg *MsgBurnCoinsAction) ValidateBasic() error { +func (msg *MsgBurnCoinsAction) ValidateBasic() error { // TODO call IsValid and IsAllPositive _, err := sdk.AccAddressFromBech32(msg.Creator) if err != nil { return fmt.Errorf("invalid creator address: %v: %w", err, errors.New("invalid address")) } + if msg.Amount.IsNegative() || msg.Amount.IsZero() { + return fmt.Errorf("amount must be positive") + } return nil } diff --git a/x/burn/types/message_burn_coins_action_test.go b/x/burn/types/message_burn_coins_action_test.go index b1e0b534..12ecb21e 100644 --- a/x/burn/types/message_burn_coins_action_test.go +++ b/x/burn/types/message_burn_coins_action_test.go @@ -19,14 +19,14 @@ func TestMsgBurnCoinsAction_ValidateBasic(t *testing.T) { name: "invalid address", msg: MsgBurnCoinsAction{ Creator: "invalid_address", - Coins: sdk.Coins{sdk.NewInt64Coin("testcoin", 1000)}, + Amount: sdk.NewInt64Coin("testcoin", 1000), }, err: sdkerrors.ErrInvalidAddress, }, { name: "valid address", msg: MsgBurnCoinsAction{ Creator: sample.AccAddress(), - Coins: sdk.Coins{sdk.NewInt64Coin("testcoin", 1000)}, + Amount: sdk.NewInt64Coin("testcoin", 1000), }, }, } diff --git a/x/burn/types/tx.pb.go b/x/burn/types/tx.pb.go index 389b01ad..16831910 100644 --- a/x/burn/types/tx.pb.go +++ b/x/burn/types/tx.pb.go @@ -30,8 +30,8 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type MsgBurnCoinsAction struct { - Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` - Coins []types.Coin `protobuf:"bytes,2,rep,name=coins,proto3" json:"coins"` + Creator string `protobuf:"bytes,1,opt,name=creator,proto3" json:"creator,omitempty"` + Amount types.Coin `protobuf:"bytes,2,opt,name=amount,proto3" json:"amount"` } func (m *MsgBurnCoinsAction) Reset() { *m = MsgBurnCoinsAction{} } @@ -74,11 +74,11 @@ func (m *MsgBurnCoinsAction) GetCreator() string { return "" } -func (m *MsgBurnCoinsAction) GetCoins() []types.Coin { +func (m *MsgBurnCoinsAction) GetAmount() types.Coin { if m != nil { - return m.Coins + return m.Amount } - return nil + return types.Coin{} } type MsgBurnCoinsActionResponse struct { @@ -126,24 +126,24 @@ func init() { proto.RegisterFile("bcna/burn/tx.proto", fileDescriptor_7b8a0e462b var fileDescriptor_7b8a0e462b5fa7e6 = []byte{ // 281 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0x4f, 0x4b, 0xc3, 0x30, - 0x18, 0xc6, 0x5b, 0xe7, 0x1f, 0x16, 0x0f, 0x42, 0xf0, 0x50, 0x8b, 0xc6, 0x31, 0x10, 0x06, 0x42, - 0xc2, 0x26, 0x7e, 0x00, 0x3b, 0xc4, 0xd3, 0x2e, 0xbd, 0x08, 0x1e, 0x84, 0x24, 0x84, 0x5a, 0xd8, - 0xf2, 0x96, 0xbe, 0xa9, 0xcc, 0x6f, 0xe1, 0xc7, 0xda, 0x71, 0x47, 0x4f, 0x22, 0xed, 0x17, 0x91, - 0xb4, 0x9b, 0x07, 0x07, 0xbb, 0x25, 0xcf, 0xf3, 0xe4, 0x97, 0xf7, 0x7d, 0x08, 0x55, 0xda, 0x4a, - 0xa1, 0xaa, 0xd2, 0x0a, 0xb7, 0xe4, 0x45, 0x09, 0x0e, 0x68, 0xdf, 0x6b, 0xdc, 0x6b, 0xf1, 0x79, - 0x06, 0x19, 0xb4, 0xaa, 0xf0, 0xa7, 0x2e, 0x10, 0x33, 0x0d, 0xb8, 0x00, 0x14, 0x4a, 0xa2, 0x11, - 0xef, 0x63, 0x65, 0x9c, 0x1c, 0x0b, 0x0d, 0xb9, 0xed, 0xfc, 0xa1, 0x21, 0x74, 0x86, 0x59, 0x52, - 0x95, 0x76, 0x0a, 0xb9, 0xc5, 0x07, 0xed, 0x72, 0xb0, 0x34, 0x22, 0x27, 0xba, 0x34, 0xd2, 0x41, - 0x19, 0x85, 0x83, 0x70, 0xd4, 0x4f, 0xb7, 0x57, 0x7a, 0x4f, 0x8e, 0xfc, 0x6b, 0x8c, 0x0e, 0x06, - 0xbd, 0xd1, 0xe9, 0xe4, 0x82, 0x77, 0x7c, 0xee, 0xf9, 0x7c, 0xc3, 0xe7, 0x1e, 0x95, 0x1c, 0xae, - 0xbe, 0xaf, 0x83, 0xb4, 0x4b, 0x0f, 0x2f, 0x49, 0xbc, 0xfb, 0x4d, 0x6a, 0xb0, 0x00, 0x8b, 0x66, - 0xf2, 0x4a, 0x7a, 0x33, 0xcc, 0xe8, 0x33, 0x39, 0xfb, 0x3f, 0xc8, 0x15, 0xff, 0x5b, 0x90, 0xef, - 0x02, 0xe2, 0x9b, 0xbd, 0xf6, 0x96, 0x9f, 0x3c, 0xae, 0x6a, 0x16, 0xae, 0x6b, 0x16, 0xfe, 0xd4, - 0x2c, 0xfc, 0x6c, 0x58, 0xb0, 0x6e, 0x58, 0xf0, 0xd5, 0xb0, 0xe0, 0xe5, 0x36, 0xcb, 0xdd, 0x5b, - 0xa5, 0xb8, 0x86, 0x85, 0x48, 0x72, 0x37, 0x95, 0xd6, 0xca, 0xa7, 0x39, 0x28, 0x39, 0x17, 0x6d, - 0xdb, 0xcb, 0x4d, 0xdf, 0x1f, 0x85, 0x41, 0x75, 0xdc, 0x56, 0x76, 0xf7, 0x1b, 0x00, 0x00, 0xff, - 0xff, 0x6b, 0x2b, 0xe4, 0xa4, 0x89, 0x01, 0x00, 0x00, + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0x41, 0x4b, 0xc3, 0x30, + 0x1c, 0xc5, 0x1b, 0x95, 0xc9, 0xe2, 0x41, 0x08, 0x1e, 0x66, 0xd1, 0x38, 0x06, 0xc2, 0x40, 0x48, + 0xd8, 0x3c, 0x78, 0xb6, 0x43, 0x3c, 0xed, 0xd2, 0x8b, 0xe0, 0x41, 0x48, 0x42, 0x88, 0x85, 0x35, + 0xff, 0xd2, 0xa4, 0x32, 0xbf, 0x85, 0x1f, 0x6b, 0xc7, 0x1d, 0x3d, 0x89, 0xb4, 0x5f, 0x44, 0xd2, + 0x76, 0x1e, 0x1c, 0x78, 0x4b, 0xde, 0x7b, 0xbc, 0x5f, 0xf2, 0x30, 0x91, 0xca, 0x0a, 0x2e, 0xab, + 0xd2, 0x72, 0xbf, 0x66, 0x45, 0x09, 0x1e, 0xc8, 0x30, 0x68, 0x2c, 0x68, 0xf1, 0x99, 0x01, 0x03, + 0xad, 0xca, 0xc3, 0xa9, 0x0b, 0xc4, 0x54, 0x81, 0xcb, 0xc1, 0x71, 0x29, 0x9c, 0xe6, 0x6f, 0x33, + 0xa9, 0xbd, 0x98, 0x71, 0x05, 0x99, 0xed, 0xfc, 0x89, 0xc1, 0x64, 0xe9, 0x4c, 0x52, 0x95, 0x76, + 0x01, 0x99, 0x75, 0xf7, 0xca, 0x67, 0x60, 0xc9, 0x08, 0x1f, 0xab, 0x52, 0x0b, 0x0f, 0xe5, 0x08, + 0x8d, 0xd1, 0x74, 0x98, 0xee, 0xae, 0xe4, 0x0e, 0x0f, 0x44, 0x0e, 0x95, 0xf5, 0xa3, 0x83, 0x31, + 0x9a, 0x9e, 0xcc, 0xcf, 0x59, 0x07, 0x60, 0x01, 0xc0, 0x7a, 0x00, 0x0b, 0x5d, 0xc9, 0xd1, 0xe6, + 0xeb, 0x2a, 0x4a, 0xfb, 0xf8, 0xe4, 0x02, 0xc7, 0xfb, 0xa0, 0x54, 0xbb, 0x02, 0xac, 0xd3, 0xf3, + 0x17, 0x7c, 0xb8, 0x74, 0x86, 0x3c, 0xe1, 0xd3, 0xbf, 0x4f, 0xb9, 0x64, 0xbf, 0x5f, 0x64, 0xfb, + 0x05, 0xf1, 0xf5, 0xbf, 0xf6, 0xae, 0x3f, 0x79, 0xd8, 0xd4, 0x14, 0x6d, 0x6b, 0x8a, 0xbe, 0x6b, + 0x8a, 0x3e, 0x1a, 0x1a, 0x6d, 0x1b, 0x1a, 0x7d, 0x36, 0x34, 0x7a, 0xbe, 0x31, 0x99, 0x7f, 0xad, + 0x24, 0x53, 0x90, 0xf3, 0x24, 0xf3, 0x0b, 0x61, 0xad, 0x78, 0x5c, 0x81, 0x14, 0x2b, 0xde, 0xee, + 0xbd, 0xee, 0x17, 0x7f, 0x2f, 0xb4, 0x93, 0x83, 0x76, 0xb4, 0xdb, 0x9f, 0x00, 0x00, 0x00, 0xff, + 0xff, 0x9c, 0xf7, 0x78, 0x24, 0x8b, 0x01, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -246,20 +246,16 @@ func (m *MsgBurnCoinsAction) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.Coins) > 0 { - for iNdEx := len(m.Coins) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Coins[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 + { + size, err := m.Amount.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } + i -= size + i = encodeVarintTx(dAtA, i, uint64(size)) } + i-- + dAtA[i] = 0x12 if len(m.Creator) > 0 { i -= len(m.Creator) copy(dAtA[i:], m.Creator) @@ -314,12 +310,8 @@ func (m *MsgBurnCoinsAction) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if len(m.Coins) > 0 { - for _, e := range m.Coins { - l = e.Size() - n += 1 + l + sovTx(uint64(l)) - } - } + l = m.Amount.Size() + n += 1 + l + sovTx(uint64(l)) return n } @@ -401,7 +393,7 @@ func (m *MsgBurnCoinsAction) Unmarshal(dAtA []byte) error { iNdEx = postIndex case 2: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Coins", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Amount", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -428,8 +420,7 @@ func (m *MsgBurnCoinsAction) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Coins = append(m.Coins, types.Coin{}) - if err := m.Coins[len(m.Coins)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Amount.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex From 6a7d28019520be6bff3c29d051dac3302b9770ac Mon Sep 17 00:00:00 2001 From: Raul Bernal Date: Fri, 22 Mar 2024 13:13:52 +0100 Subject: [PATCH 4/7] Fix permissions for Burn module --- app/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.go b/app/app.go index d31fc190..c5b65fc3 100644 --- a/app/app.go +++ b/app/app.go @@ -191,7 +191,7 @@ var ( stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - burnmoduletypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + burnmoduletypes.ModuleName: {authtypes.Burner}, // nft.ModuleName: nil, } ) From c2e1b34abbd5c9bfb008ddf9b11e76034bf46dc5 Mon Sep 17 00:00:00 2001 From: Raul Bernal Date: Fri, 22 Mar 2024 16:19:13 +0100 Subject: [PATCH 5/7] fix error message --- x/burn/keeper/msg_server_burn_coins_action.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/burn/keeper/msg_server_burn_coins_action.go b/x/burn/keeper/msg_server_burn_coins_action.go index d74205b4..2406caf9 100644 --- a/x/burn/keeper/msg_server_burn_coins_action.go +++ b/x/burn/keeper/msg_server_burn_coins_action.go @@ -29,7 +29,7 @@ func (k msgServer) BurnCoinsAction(goCtx context.Context, msg *types.MsgBurnCoin // Gets the balance of the sender to check if are there enough coins. balance := k.bankKeeper.GetBalance(ctx, creatorAddr, msg.Amount.Denom) if balance.Amount.LT(msg.Amount.Amount) { - return nil, fmt.Errorf("insufficient balance for %s", msg.Amount.Denom) + return nil, fmt.Errorf("insufficient balance for %s", creatorAddr) } // Send the coins from the creator to the module and later it burns From 905d8f1b9b00427086ad040c19150b8a18c6e392 Mon Sep 17 00:00:00 2001 From: Raul Bernal Date: Fri, 22 Mar 2024 16:19:48 +0100 Subject: [PATCH 6/7] Include more validations --- x/burn/types/message_burn_coins_action.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x/burn/types/message_burn_coins_action.go b/x/burn/types/message_burn_coins_action.go index ac36fa6b..638dbaca 100644 --- a/x/burn/types/message_burn_coins_action.go +++ b/x/burn/types/message_burn_coins_action.go @@ -39,13 +39,13 @@ func (msg *MsgBurnCoinsAction) GetSignBytes() []byte { return sdk.MustSortJSON(bz) } -func (msg *MsgBurnCoinsAction) ValidateBasic() error { // TODO call IsValid and IsAllPositive +func (msg *MsgBurnCoinsAction) ValidateBasic() error { _, err := sdk.AccAddressFromBech32(msg.Creator) if err != nil { return fmt.Errorf("invalid creator address: %v: %w", err, errors.New("invalid address")) } - if msg.Amount.IsNegative() || msg.Amount.IsZero() { - return fmt.Errorf("amount must be positive") + if msg.Amount.IsNegative() || msg.Amount.IsZero() || !msg.Amount.IsValid() { + return fmt.Errorf("amount must be positive or valid") } return nil } From 4227bdda673480b2585a8d5dc2f64a0417c0a09c Mon Sep 17 00:00:00 2001 From: Raul Bernal Date: Fri, 22 Mar 2024 17:00:54 +0100 Subject: [PATCH 7/7] More checks in keeper and use sdkerrors --- x/burn/keeper/msg_server_burn_coins_action.go | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/x/burn/keeper/msg_server_burn_coins_action.go b/x/burn/keeper/msg_server_burn_coins_action.go index 2406caf9..36e2b3df 100644 --- a/x/burn/keeper/msg_server_burn_coins_action.go +++ b/x/burn/keeper/msg_server_burn_coins_action.go @@ -2,10 +2,11 @@ package keeper import ( "context" - "fmt" + errorsmod "cosmossdk.io/errors" "github.com/BitCannaGlobal/bcna/x/burn/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" ) // Move coins from sender to Bank account module and then the module burns the coins. @@ -14,31 +15,38 @@ func (k msgServer) BurnCoinsAction(goCtx context.Context, msg *types.MsgBurnCoin creatorAddr, err := sdk.AccAddressFromBech32(msg.Creator) if err != nil { - return nil, fmt.Errorf("the address is not valid") + return nil, sdkerrors.ErrInvalidAddress.Wrapf("invalid creator address: %s", err) } + + // Validate the coins + coins := sdk.NewCoins(msg.Amount) + if !coins.IsValid() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, coins.String()) + } + // Get the module's params to verify the allowed denom params := k.GetParams(ctx) if msg.Amount.Denom != params.BurnDenom { - return nil, fmt.Errorf("denomination mismatch: expected %s, got %s", params.BurnDenom, msg.Amount.Denom) + return nil, sdkerrors.ErrInvalidAddress.Wrapf("denomination mismatch: expected %s, got %s", params.BurnDenom, msg.Amount.Denom) } - // Check if it is a valid amount - if msg.Amount.IsZero() || msg.Amount.IsNegative() { - return nil, fmt.Errorf("invalid amount: %s", msg.Amount.String()) + // Ensure coins are positive + if !coins.IsAllPositive() { + return nil, errorsmod.Wrap(sdkerrors.ErrInvalidCoins, coins.String()) } // Gets the balance of the sender to check if are there enough coins. balance := k.bankKeeper.GetBalance(ctx, creatorAddr, msg.Amount.Denom) if balance.Amount.LT(msg.Amount.Amount) { - return nil, fmt.Errorf("insufficient balance for %s", creatorAddr) + return nil, sdkerrors.ErrInvalidAddress.Wrapf("insufficient balance for %s", creatorAddr) } // Send the coins from the creator to the module and later it burns if err := k.bankKeeper.SendCoinsFromAccountToModule(ctx, creatorAddr, types.ModuleName, sdk.NewCoins(msg.Amount)); err != nil { - return nil, fmt.Errorf("failed to send coins from account to module: %v", err) + return nil, sdkerrors.ErrInvalidAddress.Wrapf("failed to send coins from account to module: %v", err) } if err := k.bankKeeper.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(msg.Amount)); err != nil { - return nil, fmt.Errorf("failed to burn coins: %v", err) + return nil, sdkerrors.ErrInvalidAddress.Wrapf("failed to burn coins: %v", err) } // Log the successful burn operation k.Logger(ctx).Info("Burning coins!! ", "signer", msg.Creator, "amount", msg.Amount)