Skip to content

Commit

Permalink
Add SetMetadata to tokenfactory (#963)
Browse files Browse the repository at this point in the history
Co-authored-by: Cyson <[email protected]>
  • Loading branch information
LCyson and Cyson authored Jul 23, 2023
1 parent 8207520 commit 01c89bc
Show file tree
Hide file tree
Showing 6 changed files with 645 additions and 38 deletions.
14 changes: 14 additions & 0 deletions proto/tokenfactory/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package seiprotocol.seichain.tokenfactory;

import "gogoproto/gogo.proto";
import "cosmos/base/v1beta1/coin.proto";
import "cosmos/bank/v1beta1/bank.proto";

option go_package = "github.com/sei-protocol/sei-chain/x/tokenfactory/types";

Expand All @@ -12,6 +13,8 @@ service Msg {
rpc Mint(MsgMint) returns (MsgMintResponse);
rpc Burn(MsgBurn) returns (MsgBurnResponse);
rpc ChangeAdmin(MsgChangeAdmin) returns (MsgChangeAdminResponse);
rpc SetDenomMetadata(MsgSetDenomMetadata)
returns (MsgSetDenomMetadataResponse);

// ForceTransfer is deactivated for now because we need to think through edge
// cases rpc ForceTransfer(MsgForceTransfer) returns
Expand Down Expand Up @@ -89,3 +92,14 @@ message MsgChangeAdminResponse {}
// }

// message MsgForceTransferResponse {}

// MsgSetDenomMetadata is the sdk.Msg type for allowing an admin account to set
// the denom's bank metadata
message MsgSetDenomMetadata {
string sender = 1 [ (gogoproto.moretags) = "yaml:\"sender\"" ];
cosmos.bank.v1beta1.Metadata metadata = 2 [ (gogoproto.moretags) = "yaml:\"metadata\"", (gogoproto.nullable) = false ];
}

// MsgSetDenomMetadataResponse defines the response structure for an executed
// MsgSetDenomMetadata message.
message MsgSetDenomMetadataResponse {}
130 changes: 130 additions & 0 deletions x/tokenfactory/keeper/admins_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/sei-protocol/sei-chain/x/tokenfactory/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

func (suite *KeeperTestSuite) TestAdminMsgs() {
Expand Down Expand Up @@ -164,3 +165,132 @@ func (suite *KeeperTestSuite) TestChangeAdminDenom() {
})
}
}

func (suite *KeeperTestSuite) TestSetDenomMetaData() {

// setup test
suite.SetupTest()
suite.CreateDefaultDenom()

for _, tc := range []struct {
desc string
msgSetDenomMetadata types.MsgSetDenomMetadata
expectedPass bool
}{
{
desc: "successful set denom metadata",
msgSetDenomMetadata: *types.NewMsgSetDenomMetadata(suite.TestAccs[0].String(), banktypes.Metadata{
Description: "test1",
DenomUnits: []*banktypes.DenomUnit{
{
Denom: suite.defaultDenom,
Exponent: 0,
},
{
Denom: "usei",
Exponent: 6,
},
},
Base: suite.defaultDenom,
Display: "usei",
Name: "SEI",
Symbol: "SEI",
}),
expectedPass: true,
},
{
desc: "non existent factory denom name",
msgSetDenomMetadata: *types.NewMsgSetDenomMetadata(suite.TestAccs[0].String(), banktypes.Metadata{
Description: "test2",
DenomUnits: []*banktypes.DenomUnit{
{
Denom: fmt.Sprintf("factory/%s/litecoin", suite.TestAccs[0].String()),
Exponent: 0,
},
{
Denom: "usei",
Exponent: 6,
},
},
Base: fmt.Sprintf("factory/%s/litecoin", suite.TestAccs[0].String()),
Display: "usei",
Name: "SEI",
Symbol: "SEI",
}),
expectedPass: false,
},
{
desc: "non-factory denom",
msgSetDenomMetadata: *types.NewMsgSetDenomMetadata(suite.TestAccs[0].String(), banktypes.Metadata{
Description: "test3",
DenomUnits: []*banktypes.DenomUnit{
{
Denom: "usei",
Exponent: 0,
},
{
Denom: "usei",
Exponent: 6,
},
},
Base: "usei",
Display: "usei",
Name: "SEI",
Symbol: "SEI",
}),
expectedPass: false,
},
{
desc: "wrong admin",
msgSetDenomMetadata: *types.NewMsgSetDenomMetadata(suite.TestAccs[1].String(), banktypes.Metadata{
Description: "test4",
DenomUnits: []*banktypes.DenomUnit{
{
Denom: suite.defaultDenom,
Exponent: 0,
},
{
Denom: "usei",
Exponent: 6,
},
},
Base: suite.defaultDenom,
Display: "usei",
Name: "SEI",
Symbol: "SEI",
}),
expectedPass: false,
},
{
desc: "invalid metadata (missing display denom unit)",
msgSetDenomMetadata: *types.NewMsgSetDenomMetadata(suite.TestAccs[0].String(), banktypes.Metadata{
Description: "test5",
DenomUnits: []*banktypes.DenomUnit{
{
Denom: suite.defaultDenom,
Exponent: 0,
},
},
Base: suite.defaultDenom,
Display: "usei",
Name: "SEI",
Symbol: "SEI",
}),
expectedPass: false,
},
} {
suite.Run(fmt.Sprintf("Case %s", tc.desc), func() {
res, err := suite.msgServer.SetDenomMetadata(sdk.WrapSDKContext(suite.Ctx), &tc.msgSetDenomMetadata)
if tc.expectedPass {
suite.Require().NoError(err)
suite.Require().NotNil(res)

md, found := suite.App.BankKeeper.GetDenomMetaData(suite.Ctx, suite.defaultDenom)
suite.Require().True(found)
suite.Require().Equal(tc.msgSetDenomMetadata.Metadata.Name, md.Name)
} else {
suite.Require().Error(err)
}
})
}
}
31 changes: 31 additions & 0 deletions x/tokenfactory/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,34 @@ func (server msgServer) ChangeAdmin(goCtx context.Context, msg *types.MsgChangeA

return &types.MsgChangeAdminResponse{}, nil
}

func (server msgServer) SetDenomMetadata(goCtx context.Context, msg *types.MsgSetDenomMetadata) (*types.MsgSetDenomMetadataResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)

// Defense in depth validation of metadata
err := msg.Metadata.Validate()
if err != nil {
return nil, err
}

authorityMetadata, err := server.Keeper.GetAuthorityMetadata(ctx, msg.Metadata.Base)
if err != nil {
return nil, err
}

if msg.Sender != authorityMetadata.GetAdmin() {
return nil, types.ErrUnauthorized
}

server.Keeper.bankKeeper.SetDenomMetaData(ctx, msg.Metadata)

ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.TypeMsgSetDenomMetadata,
sdk.NewAttribute(types.AttributeDenom, msg.Metadata.Base),
sdk.NewAttribute(types.AttributeDenomMetadata, msg.Metadata.String()),
),
})

return &types.MsgSetDenomMetadataResponse{}, nil
}
1 change: 1 addition & 0 deletions x/tokenfactory/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ const (
AttributeTransferToAddress = "transfer_to_address"
AttributeDenom = "denom"
AttributeNewAdmin = "new_admin"
AttributeDenomMetadata = "denom_metadata"
)
52 changes: 47 additions & 5 deletions x/tokenfactory/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,17 @@ package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
)

// constants
const (
TypeMsgCreateDenom = "create_denom"
TypeMsgMint = "mint"
TypeMsgBurn = "burn"
TypeMsgForceTransfer = "force_transfer"
TypeMsgChangeAdmin = "change_admin"
TypeMsgCreateDenom = "create_denom"
TypeMsgMint = "mint"
TypeMsgBurn = "burn"
TypeMsgForceTransfer = "force_transfer"
TypeMsgChangeAdmin = "change_admin"
TypeMsgSetDenomMetadata = "set_denom_metadata"
)

var _ sdk.Msg = &MsgCreateDenom{}
Expand Down Expand Up @@ -202,3 +204,43 @@ func (m MsgChangeAdmin) GetSigners() []sdk.AccAddress {
sender, _ := sdk.AccAddressFromBech32(m.Sender)
return []sdk.AccAddress{sender}
}

var _ sdk.Msg = &MsgSetDenomMetadata{}

// NewMsgChangeAdmin creates a message to burn tokens
func NewMsgSetDenomMetadata(sender string, metadata banktypes.Metadata) *MsgSetDenomMetadata {
return &MsgSetDenomMetadata{
Sender: sender,
Metadata: metadata,
}
}

func (m MsgSetDenomMetadata) Route() string { return RouterKey }
func (m MsgSetDenomMetadata) Type() string { return TypeMsgSetDenomMetadata }
func (m MsgSetDenomMetadata) ValidateBasic() error {
_, err := sdk.AccAddressFromBech32(m.Sender)
if err != nil {
return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address (%s)", err)
}

err = m.Metadata.Validate()
if err != nil {
return err
}

_, _, err = DeconstructDenom(m.Metadata.Base)
if err != nil {
return err
}

return nil
}

func (m MsgSetDenomMetadata) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m))
}

func (m MsgSetDenomMetadata) GetSigners() []sdk.AccAddress {
sender, _ := sdk.AccAddressFromBech32(m.Sender)
return []sdk.AccAddress{sender}
}
Loading

0 comments on commit 01c89bc

Please sign in to comment.