mukan-ibc/modules/apps/transfer/keeper/msg_server_test.go
Mukan Erkin Törük 6852832fe8
Some checks failed
CodeQL / Analyze (push) Waiting to run
Docker Build & Push Simapp (main) / docker-build (push) Waiting to run
golangci-lint / lint (push) Waiting to run
Tests / Code Coverage / build (amd64) (push) Waiting to run
Tests / Code Coverage / build (arm64) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[additional-args:-tags="test_e2e" name:e2e path:./e2e]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:08-wasm path:./modules/light-clients/08-wasm]) (push) Waiting to run
Tests / Code Coverage / unit-tests (map[name:ibc-go path:.]) (push) Waiting to run
Deploy to GitHub Pages / Deploy to GitHub Pages (push) Has been cancelled
Buf-Push / push (push) Has been cancelled
initial: sovereign Mukan Network fork
2026-05-11 03:18:28 +03:00

359 lines
10 KiB
Go

package keeper_test
import (
"errors"
"strings"
"time"
sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
minttypes "github.com/cosmos/cosmos-sdk/x/mint/types"
abci "github.com/cometbft/cometbft/abci/types"
"github.com/cosmos/ibc-go/v10/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v10/modules/core/02-client/types"
clienttypesv2 "github.com/cosmos/ibc-go/v10/modules/core/02-client/v2/types"
ibcerrors "github.com/cosmos/ibc-go/v10/modules/core/errors"
ibctesting "github.com/cosmos/ibc-go/v10/testing"
)
// TestMsgTransfer tests Transfer rpc handler
func (suite *KeeperTestSuite) TestMsgTransfer() {
var msg *types.MsgTransfer
var path *ibctesting.Path
testCases := []struct {
name string
malleate func()
expError error
}{
{
"success",
func() {
msg.Token = ibctesting.TestCoin
},
nil,
},
{
"bank send enabled for denoms",
func() {
err := suite.chainA.GetSimApp().BankKeeper.SetParams(suite.chainA.GetContext(),
banktypes.Params{
SendEnabled: []*banktypes.SendEnabled{
{Denom: sdk.DefaultBondDenom, Enabled: true},
{Denom: ibctesting.SecondaryDenom, Enabled: true},
},
},
)
suite.Require().NoError(err)
},
nil,
},
{
"failure: send transfers disabled",
func() {
suite.chainA.GetSimApp().TransferKeeper.SetParams(suite.chainA.GetContext(),
types.Params{
SendEnabled: false,
},
)
},
types.ErrSendDisabled,
},
{
"failure: zero amount",
func() {
msg.Token = sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)
},
types.ErrInvalidAmount,
},
{
"failure: invalid sender",
func() {
msg.Sender = "address"
},
errors.New("decoding bech32 failed"),
},
{
"failure: sender is a blocked address",
func() {
msg.Sender = suite.chainA.GetSimApp().AccountKeeper.GetModuleAddress(minttypes.ModuleName).String()
},
ibcerrors.ErrUnauthorized,
},
{
"failure: bank send disabled",
func() {
err := suite.chainA.GetSimApp().BankKeeper.SetParams(suite.chainA.GetContext(),
banktypes.Params{
SendEnabled: []*banktypes.SendEnabled{{Denom: sdk.DefaultBondDenom, Enabled: false}},
},
)
suite.Require().NoError(err)
},
types.ErrSendDisabled,
},
{
"failure: channel does not exist",
func() {
msg.SourceChannel = "channel-100"
},
clienttypesv2.ErrCounterpartyNotFound,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
path = ibctesting.NewTransferPath(suite.chainA, suite.chainB)
path.Setup()
msg = types.NewMsgTransfer(
path.EndpointA.ChannelConfig.PortID,
path.EndpointA.ChannelID,
ibctesting.TestCoin,
suite.chainA.SenderAccount.GetAddress().String(),
suite.chainB.SenderAccount.GetAddress().String(),
clienttypes.Height{}, suite.chainB.GetTimeoutTimestamp(), // only use timeout height
"memo",
)
// send some coins of the second denom from bank module to the sender account as well
err := suite.chainA.GetSimApp().BankKeeper.MintCoins(suite.chainA.GetContext(), types.ModuleName, sdk.NewCoins(ibctesting.SecondaryTestCoin))
suite.Require().NoError(err)
err = suite.chainA.GetSimApp().BankKeeper.SendCoinsFromModuleToAccount(suite.chainA.GetContext(), types.ModuleName, suite.chainA.SenderAccount.GetAddress(), sdk.NewCoins(ibctesting.SecondaryTestCoin))
suite.Require().NoError(err)
tc.malleate()
ctx := suite.chainA.GetContext()
token, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(ctx, msg.Token)
suite.Require().NoError(err)
res, err := suite.chainA.GetSimApp().TransferKeeper.Transfer(ctx, msg)
// Verify events
var expEvents []abci.Event
events := ctx.EventManager().Events().ToABCIEvents()
expEvents = sdk.Events{
sdk.NewEvent(types.EventTypeTransfer,
sdk.NewAttribute(types.AttributeKeySender, msg.Sender),
sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver),
sdk.NewAttribute(types.AttributeKeyDenom, token.Denom.Path()),
sdk.NewAttribute(types.AttributeKeyAmount, msg.Token.Amount.String()),
sdk.NewAttribute(types.AttributeKeyMemo, msg.Memo),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
),
}.ToABCIEvents()
if tc.expError == nil {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().NotEqual(res.Sequence, uint64(0))
ibctesting.AssertEvents(&suite.Suite, expEvents, events)
} else {
suite.Require().Nil(res)
suite.Require().True(errors.Is(err, tc.expError) || strings.Contains(err.Error(), tc.expError.Error()), err.Error())
suite.Require().Len(events, 0)
}
})
}
}
// TestMsgTransfer tests Transfer rpc handler with IBC V2 protocol
func (suite *KeeperTestSuite) TestMsgTransferIBCV2() {
var msg *types.MsgTransfer
var path *ibctesting.Path
testCases := []struct {
name string
malleate func()
expError error
}{
{
"success",
func() {
msg.Token = ibctesting.TestCoin
},
nil,
},
{
"bank send enabled for denoms",
func() {
err := suite.chainA.GetSimApp().BankKeeper.SetParams(suite.chainA.GetContext(),
banktypes.Params{
SendEnabled: []*banktypes.SendEnabled{
{Denom: sdk.DefaultBondDenom, Enabled: true},
{Denom: ibctesting.SecondaryDenom, Enabled: true},
},
},
)
suite.Require().NoError(err)
},
nil,
},
{
"failure: send transfers disabled",
func() {
suite.chainA.GetSimApp().TransferKeeper.SetParams(suite.chainA.GetContext(),
types.Params{
SendEnabled: false,
},
)
},
types.ErrSendDisabled,
},
{
"failure: invalid sender",
func() {
msg.Sender = "address"
},
errors.New("decoding bech32 failed"),
},
{
"failure: sender is a blocked address",
func() {
msg.Sender = suite.chainA.GetSimApp().AccountKeeper.GetModuleAddress(minttypes.ModuleName).String()
},
ibcerrors.ErrUnauthorized,
},
{
"failure: bank send disabled",
func() {
err := suite.chainA.GetSimApp().BankKeeper.SetParams(suite.chainA.GetContext(),
banktypes.Params{
SendEnabled: []*banktypes.SendEnabled{{Denom: sdk.DefaultBondDenom, Enabled: false}},
},
)
suite.Require().NoError(err)
},
types.ErrSendDisabled,
},
{
"failure: client does not exist",
func() {
msg.SourceChannel = "07-tendermint-500"
},
clienttypesv2.ErrCounterpartyNotFound,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
path = ibctesting.NewPath(suite.chainA, suite.chainB)
path.SetupV2()
timeoutTimestamp := uint64(suite.chainA.GetContext().BlockTime().Add(time.Hour).Unix())
msg = types.NewMsgTransfer(
types.PortID,
path.EndpointA.ClientID, // use eureka client id
ibctesting.TestCoin,
suite.chainA.SenderAccount.GetAddress().String(),
suite.chainB.SenderAccount.GetAddress().String(),
clienttypes.Height{}, timeoutTimestamp, // only use timeout timestamp
"memo",
)
// send some coins of the second denom from bank module to the sender account as well
err := suite.chainA.GetSimApp().BankKeeper.MintCoins(suite.chainA.GetContext(), types.ModuleName, sdk.NewCoins(ibctesting.SecondaryTestCoin))
suite.Require().NoError(err)
err = suite.chainA.GetSimApp().BankKeeper.SendCoinsFromModuleToAccount(suite.chainA.GetContext(), types.ModuleName, suite.chainA.SenderAccount.GetAddress(), sdk.NewCoins(ibctesting.SecondaryTestCoin))
suite.Require().NoError(err)
tc.malleate()
ctx := suite.chainA.GetContext()
token, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(ctx, msg.Token)
suite.Require().NoError(err)
res, err := suite.chainA.GetSimApp().TransferKeeper.Transfer(ctx, msg)
// Verify events
var expEvents []abci.Event
events := ctx.EventManager().Events().ToABCIEvents()
expEvents = sdk.Events{
sdk.NewEvent(types.EventTypeTransfer,
sdk.NewAttribute(types.AttributeKeySender, msg.Sender),
sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver),
sdk.NewAttribute(types.AttributeKeyDenom, token.Denom.Path()),
sdk.NewAttribute(types.AttributeKeyAmount, msg.Token.Amount.String()),
sdk.NewAttribute(types.AttributeKeyMemo, msg.Memo),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
),
}.ToABCIEvents()
if tc.expError == nil {
suite.Require().NoError(err)
suite.Require().NotNil(res)
suite.Require().NotEqual(res.Sequence, uint64(0))
ibctesting.AssertEvents(&suite.Suite, expEvents, events)
} else {
suite.Require().Nil(res)
suite.Require().True(errors.Is(err, tc.expError) || strings.Contains(err.Error(), tc.expError.Error()), err.Error())
}
})
}
}
// TestUpdateParams tests UpdateParams rpc handler
func (suite *KeeperTestSuite) TestUpdateParams() {
signer := suite.chainA.GetSimApp().TransferKeeper.GetAuthority()
testCases := []struct {
name string
msg *types.MsgUpdateParams
expErr error
}{
{
"success: valid signer and default params",
types.NewMsgUpdateParams(signer, types.DefaultParams()),
nil,
},
{
"failure: malformed signer address",
types.NewMsgUpdateParams(ibctesting.InvalidID, types.DefaultParams()),
ibcerrors.ErrUnauthorized,
},
{
"failure: empty signer address",
types.NewMsgUpdateParams("", types.DefaultParams()),
ibcerrors.ErrUnauthorized,
},
{
"failure: whitespace signer address",
types.NewMsgUpdateParams(" ", types.DefaultParams()),
ibcerrors.ErrUnauthorized,
},
{
"failure: unauthorized signer address",
types.NewMsgUpdateParams(ibctesting.TestAccAddress, types.DefaultParams()),
ibcerrors.ErrUnauthorized,
},
}
for _, tc := range testCases {
suite.Run(tc.name, func() {
suite.SetupTest()
_, err := suite.chainA.GetSimApp().TransferKeeper.UpdateParams(suite.chainA.GetContext(), tc.msg)
if tc.expErr == nil {
suite.Require().NoError(err)
} else {
suite.Require().ErrorIs(err, tc.expErr)
}
})
}
}