Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: make cross-chain token mintable #270

Merged
merged 1 commit into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,042 changes: 1,003 additions & 39 deletions api/cosmos/crosschain/v1/tx.pulsar.go

Large diffs are not rendered by default.

41 changes: 41 additions & 0 deletions api/cosmos/crosschain/v1/tx_grpc.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 26 additions & 1 deletion proto/cosmos/crosschain/v1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ service Msg {
// UpdateChannelPermissions defines a governance operation for updating the channel permissions.
// The authority is defined in the keeper.
rpc UpdateChannelPermissions(MsgUpdateChannelPermissions) returns (MsgUpdateChannelPermissionsResponse);

// MintModuleTokens defines a governance operation for minting tokens for the crosschain module.
// The authority is defined in the keeper.
rpc MintModuleTokens(MsgMintModuleTokens) returns (MsgMintModuleTokensResponse);
}

// MsgUpdateParams is the Msg/UpdateParams request type.
Expand Down Expand Up @@ -55,4 +59,25 @@ message MsgUpdateChannelPermissions {

// MsgUpdateChannelPermissionsResponse defines the response structure for executing a
// MsgUpdateChannelPermissions message.
message MsgUpdateChannelPermissionsResponse {}
message MsgUpdateChannelPermissionsResponse {}

// MsgMintModuleTokens is the Msg/MintModuleTokens request type.
// The Msg is used to mint tokens for the crosschain module.
// This Only permitted to be called by the authority(gov).
message MsgMintModuleTokens {
option (cosmos.msg.v1.signer) = "authority";

// authority is the address that controls the module (defaults to x/gov unless overwritten).
string authority = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];

// initial balance to mint for crosschain module when the chain starts
string amount = 2 [
(cosmos_proto.scalar) = "math.Int",
(gogoproto.customtype) = "cosmossdk.io/math.Int",
(gogoproto.nullable) = false
];
}

// MsgMintModuleTokensResponse defines the response structure for executing a
// MsgMintModuleTokens message.
message MsgMintModuleTokensResponse {}
28 changes: 24 additions & 4 deletions x/crosschain/keeper/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"math/big"

"cosmossdk.io/math"
"github.com/cometbft/cometbft/libs/log"

"github.com/cosmos/cosmos-sdk/codec"
Expand All @@ -22,17 +23,24 @@ type Keeper struct {
storeKey storetypes.StoreKey

authority string

stakingKeeper types.StakingKeeper
bankKeeper types.BankKeeper
}

// NewKeeper creates a new mint Keeper instance
func NewKeeper(
cdc codec.BinaryCodec, key storetypes.StoreKey, authority string,
stakingKeeper types.StakingKeeper,
bankKeeper types.BankKeeper,
) Keeper {
return Keeper{
cdc: cdc,
storeKey: key,
cfg: newCrossChainCfg(),
authority: authority,
cdc: cdc,
storeKey: key,
cfg: newCrossChainCfg(),
authority: authority,
stakingKeeper: stakingKeeper,
bankKeeper: bankKeeper,
}
}

Expand Down Expand Up @@ -293,3 +301,15 @@ func (k Keeper) incrSequence(ctx sdk.Context, destChainID sdk.ChainID, channelID
func (k Keeper) GetCrossChainApp(channelID sdk.ChannelID) sdk.CrossChainApplication {
return k.cfg.channelIDToApp[channelID]
}

func (k Keeper) MintModuleAccountTokens(ctx sdk.Context, amount math.Int) error {
bondDenom := k.stakingKeeper.BondDenom(ctx)
err := k.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.Coins{sdk.Coin{
Denom: bondDenom,
Amount: amount,
}})
if err != nil {
return fmt.Errorf("mint cross chain module amount error, err=%s", err.Error())
}
return nil
}
12 changes: 10 additions & 2 deletions x/crosschain/keeper/keeper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package keeper_test
import (
"testing"

"github.com/golang/mock/gomock"
"github.com/stretchr/testify/suite"

"github.com/cosmos/cosmos-sdk/baseapp"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
"github.com/cosmos/cosmos-sdk/testutil"
Expand All @@ -12,8 +15,8 @@ import (
"github.com/cosmos/cosmos-sdk/x/crosschain/keeper"
testutil2 "github.com/cosmos/cosmos-sdk/x/crosschain/testutil"
"github.com/cosmos/cosmos-sdk/x/crosschain/types"
govtestutil "github.com/cosmos/cosmos-sdk/x/gov/testutil"
"github.com/cosmos/cosmos-sdk/x/mint"
"github.com/stretchr/testify/suite"
)

type TestSuite struct {
Expand All @@ -31,11 +34,16 @@ func (s *TestSuite) SetupTest() {
key := storetypes.NewKVStoreKey(types.StoreKey)
testCtx := testutil.DefaultContextWithDB(s.T(), key, storetypes.NewTransientStoreKey("transient_test"))
s.ctx = testCtx.Ctx

// gomock initializations
ctrl := gomock.NewController(s.T())
bankKeeper := govtestutil.NewMockBankKeeper(ctrl)
stakingKeeper := govtestutil.NewMockStakingKeeper(ctrl)
s.crossChainKeeper = keeper.NewKeeper(
encCfg.Codec,
key,
authtypes.NewModuleAddress(types.ModuleName).String(),
stakingKeeper,
bankKeeper,
)

err := s.crossChainKeeper.SetParams(s.ctx, types.DefaultParams())
Expand Down
13 changes: 13 additions & 0 deletions x/crosschain/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,16 @@ func (k msgServer) UpdateChannelPermissions(goCtx context.Context, req *types.Ms

return &types.MsgUpdateChannelPermissionsResponse{}, nil
}

func (k msgServer) MintModuleTokens(goCtx context.Context, req *types.MsgMintModuleTokens) (*types.MsgMintModuleTokensResponse, error) {
if k.GetAuthority() != req.Authority {
return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", k.GetAuthority(), req.Authority)
}

ctx := sdk.UnwrapSDKContext(goCtx)
if err := k.MintModuleAccountTokens(ctx, req.Amount); err != nil {
return nil, err
}

return &types.MsgMintModuleTokensResponse{}, nil
}
2 changes: 2 additions & 0 deletions x/crosschain/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ func ProvideModule(in CrossChainInputs) CrossChainOutputs {
in.Cdc,
in.Key,
authority.String(),
in.StakingKeeper,
in.BankKeeper,
)

m := NewAppModule(k, in.BankKeeper, in.StakingKeeper)
Expand Down
30 changes: 29 additions & 1 deletion x/crosschain/types/msgs.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
)

var _ sdk.Msg = &MsgUpdateParams{}
var (
_ sdk.Msg = &MsgUpdateParams{}
_ sdk.Msg = &MsgUpdateChannelPermissions{}
_ sdk.Msg = &MsgMintModuleTokens{}
)

// GetSignBytes implements the LegacyMsg interface.
func (m MsgUpdateParams) GetSignBytes() []byte {
Expand Down Expand Up @@ -58,3 +62,27 @@ func (m *MsgUpdateChannelPermissions) ValidateBasic() error {

return nil
}

// GetSignBytes implements the LegacyMsg interface.
func (m MsgMintModuleTokens) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m))
}

// GetSigners returns the expected signers for a MsgMintModuleTokens message.
func (m *MsgMintModuleTokens) GetSigners() []sdk.AccAddress {
addr, _ := sdk.AccAddressFromHexUnsafe(m.Authority)
return []sdk.AccAddress{addr}
}

// ValidateBasic does a sanity check on the provided data.
func (m *MsgMintModuleTokens) ValidateBasic() error {
if _, err := sdk.AccAddressFromHexUnsafe(m.Authority); err != nil {
return errorsmod.Wrap(err, "invalid authority address")
}

if m.Amount.LTE(sdk.ZeroInt()) {
return fmt.Errorf("amount must be positive, is %s", m.Amount)
}

return nil
}
Loading