Some checks failed
CodeQL / Analyze (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
Docker Build & Push Simapp (main) / docker-build (push) Has been cancelled
656 lines
20 KiB
Go
656 lines
20 KiB
Go
package transfer_test
|
|
|
|
import (
|
|
"errors"
|
|
"math"
|
|
|
|
sdkmath "cosmossdk.io/math"
|
|
|
|
"git.cw.tr/mukan-network/mukan-sdk/crypto/keys/secp256k1"
|
|
sdk "git.cw.tr/mukan-network/mukan-sdk/types"
|
|
|
|
"git.cw.tr/mukan-network/mukan-ibc/modules/apps/transfer"
|
|
"git.cw.tr/mukan-network/mukan-ibc/modules/apps/transfer/types"
|
|
clienttypes "git.cw.tr/mukan-network/mukan-ibc/modules/core/02-client/types"
|
|
channeltypes "git.cw.tr/mukan-network/mukan-ibc/modules/core/04-channel/types"
|
|
porttypes "git.cw.tr/mukan-network/mukan-ibc/modules/core/05-port/types"
|
|
ibcerrors "git.cw.tr/mukan-network/mukan-ibc/modules/core/errors"
|
|
"git.cw.tr/mukan-network/mukan-ibc/modules/core/exported"
|
|
ibctesting "git.cw.tr/mukan-network/mukan-ibc/testing"
|
|
)
|
|
|
|
func (suite *TransferTestSuite) TestOnChanOpenInit() {
|
|
var (
|
|
channel *channeltypes.Channel
|
|
path *ibctesting.Path
|
|
counterparty channeltypes.Counterparty
|
|
)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
malleate func()
|
|
expError error
|
|
expVersion string
|
|
}{
|
|
{
|
|
"success", func() {}, nil, types.V1,
|
|
},
|
|
{
|
|
// connection hops is not used in the transfer application callback,
|
|
"success: invalid connection hops", func() {
|
|
path.EndpointA.ConnectionID = ibctesting.InvalidID
|
|
}, nil, types.V1,
|
|
},
|
|
{
|
|
"success: empty version string", func() {
|
|
channel.Version = ""
|
|
}, nil, types.V1,
|
|
},
|
|
{
|
|
"success: ics20-1", func() {
|
|
channel.Version = types.V1
|
|
}, nil, types.V1,
|
|
},
|
|
{
|
|
"max channels reached", func() {
|
|
path.EndpointA.ChannelID = channeltypes.FormatChannelIdentifier(math.MaxUint32 + 1)
|
|
}, types.ErrMaxTransferChannels, "",
|
|
},
|
|
{
|
|
"invalid order - ORDERED", func() {
|
|
channel.Ordering = channeltypes.ORDERED
|
|
}, channeltypes.ErrInvalidChannelOrdering, "",
|
|
},
|
|
{
|
|
"invalid port ID", func() {
|
|
path.EndpointA.ChannelConfig.PortID = ibctesting.MockPort
|
|
}, porttypes.ErrInvalidPort, "",
|
|
},
|
|
{
|
|
"invalid version", func() {
|
|
channel.Version = "version" //nolint:goconst
|
|
}, types.ErrInvalidVersion, "",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.SetupTest() // reset
|
|
path = ibctesting.NewTransferPath(suite.chainA, suite.chainB)
|
|
path.SetupConnections()
|
|
path.EndpointA.ChannelID = ibctesting.FirstChannelID
|
|
|
|
counterparty = channeltypes.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
|
|
channel = &channeltypes.Channel{
|
|
State: channeltypes.INIT,
|
|
Ordering: channeltypes.UNORDERED,
|
|
Counterparty: counterparty,
|
|
ConnectionHops: []string{path.EndpointA.ConnectionID},
|
|
Version: types.V1,
|
|
}
|
|
|
|
tc.malleate() // explicitly change fields in channel and testChannel
|
|
|
|
transferModule := transfer.NewIBCModule(suite.chainA.GetSimApp().TransferKeeper)
|
|
version, err := transferModule.OnChanOpenInit(suite.chainA.GetContext(), channel.Ordering, channel.ConnectionHops,
|
|
path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, counterparty, channel.Version,
|
|
)
|
|
|
|
if tc.expError == nil {
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(tc.expVersion, version)
|
|
} else {
|
|
suite.Require().Error(err)
|
|
suite.Require().Contains(err.Error(), tc.expError.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *TransferTestSuite) TestOnChanOpenTry() {
|
|
var (
|
|
channel *channeltypes.Channel
|
|
path *ibctesting.Path
|
|
counterparty channeltypes.Counterparty
|
|
counterpartyVersion string
|
|
)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
malleate func()
|
|
expError error
|
|
expVersion string
|
|
}{
|
|
{
|
|
"success", func() {}, nil, types.V1,
|
|
},
|
|
{
|
|
"success: counterparty version is ics20-1", func() {
|
|
counterpartyVersion = types.V1
|
|
}, nil, types.V1,
|
|
},
|
|
{
|
|
"success: invalid counterparty version, we propose new version", func() {
|
|
// transfer module will propose the default version
|
|
counterpartyVersion = "version"
|
|
}, nil, types.V1,
|
|
},
|
|
{
|
|
"failure: max channels reached", func() {
|
|
path.EndpointA.ChannelID = channeltypes.FormatChannelIdentifier(math.MaxUint32 + 1)
|
|
}, types.ErrMaxTransferChannels, "",
|
|
},
|
|
{
|
|
"failure: invalid order - ORDERED", func() {
|
|
channel.Ordering = channeltypes.ORDERED
|
|
}, channeltypes.ErrInvalidChannelOrdering, "",
|
|
},
|
|
{
|
|
"failure: invalid port ID", func() {
|
|
path.EndpointA.ChannelConfig.PortID = ibctesting.MockPort
|
|
}, porttypes.ErrInvalidPort, "",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.SetupTest() // reset
|
|
|
|
path = ibctesting.NewTransferPath(suite.chainA, suite.chainB)
|
|
path.SetupConnections()
|
|
path.EndpointA.ChannelID = ibctesting.FirstChannelID
|
|
|
|
counterparty = channeltypes.NewCounterparty(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)
|
|
channel = &channeltypes.Channel{
|
|
State: channeltypes.TRYOPEN,
|
|
Ordering: channeltypes.UNORDERED,
|
|
Counterparty: counterparty,
|
|
ConnectionHops: []string{path.EndpointA.ConnectionID},
|
|
Version: types.V1,
|
|
}
|
|
counterpartyVersion = types.V1
|
|
|
|
cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort)
|
|
suite.Require().True(ok)
|
|
|
|
tc.malleate() // explicitly change fields in channel and testChannel
|
|
|
|
version, err := cbs.OnChanOpenTry(suite.chainA.GetContext(), channel.Ordering, channel.ConnectionHops,
|
|
path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, channel.Counterparty, counterpartyVersion,
|
|
)
|
|
if tc.expError == nil {
|
|
suite.Require().NoError(err)
|
|
suite.Require().Equal(tc.expVersion, version)
|
|
} else {
|
|
suite.Require().Error(err)
|
|
suite.Require().Contains(err.Error(), tc.expError.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *TransferTestSuite) TestOnChanOpenAck() {
|
|
var counterpartyVersion string
|
|
|
|
testCases := []struct {
|
|
name string
|
|
malleate func()
|
|
expError error
|
|
}{
|
|
{
|
|
"success", func() {}, nil,
|
|
},
|
|
{
|
|
"invalid counterparty version",
|
|
func() {
|
|
counterpartyVersion = "version"
|
|
},
|
|
types.ErrInvalidVersion,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.SetupTest() // reset
|
|
|
|
path := ibctesting.NewTransferPath(suite.chainA, suite.chainB)
|
|
path.SetupConnections()
|
|
path.EndpointA.ChannelID = ibctesting.FirstChannelID
|
|
counterpartyVersion = types.V1
|
|
|
|
cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort)
|
|
suite.Require().True(ok)
|
|
|
|
tc.malleate() // explicitly change fields in channel and testChannel
|
|
|
|
err := cbs.OnChanOpenAck(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointA.Counterparty.ChannelID, counterpartyVersion)
|
|
|
|
if tc.expError == nil {
|
|
suite.Require().NoError(err)
|
|
} else {
|
|
suite.Require().Error(err)
|
|
suite.Require().Contains(err.Error(), tc.expError.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *TransferTestSuite) TestOnRecvPacket() {
|
|
// This test suite mostly covers the top-level logic of the ibc module OnRecvPacket function
|
|
// The core logic is covered in keeper OnRecvPacket
|
|
var (
|
|
packet channeltypes.Packet
|
|
expectedAttributes []sdk.Attribute
|
|
path *ibctesting.Path
|
|
)
|
|
testCases := []struct {
|
|
name string
|
|
malleate func()
|
|
expAck exported.Acknowledgement
|
|
expEventErrorMsg string
|
|
}{
|
|
{
|
|
"success", func() {}, channeltypes.NewResultAcknowledgement([]byte{byte(1)}), "",
|
|
},
|
|
{
|
|
"failure: invalid packet data bytes",
|
|
func() {
|
|
packet.Data = []byte("invalid data")
|
|
|
|
// Override expected attributes because this fails on unmarshaling packet data (so can't get the attributes)
|
|
expectedAttributes = []sdk.Attribute{
|
|
sdk.NewAttribute(types.AttributeKeySender, ""),
|
|
sdk.NewAttribute(types.AttributeKeyReceiver, ""),
|
|
sdk.NewAttribute(types.AttributeKeyDenom, ""),
|
|
sdk.NewAttribute(types.AttributeKeyAmount, ""),
|
|
sdk.NewAttribute(types.AttributeKeyMemo, ""),
|
|
sdk.NewAttribute(types.AttributeKeyAckSuccess, "false"),
|
|
sdk.NewAttribute(types.AttributeKeyAckError, "cannot unmarshal ICS20-V1 transfer packet data: invalid character 'i' looking for beginning of value: invalid type"),
|
|
}
|
|
},
|
|
channeltypes.NewErrorAcknowledgement(ibcerrors.ErrInvalidType),
|
|
"cannot unmarshal ICS20-V1 transfer packet data: invalid character 'i' looking for beginning of value: invalid type",
|
|
},
|
|
{
|
|
"failure: receive disabled",
|
|
func() {
|
|
suite.chainB.GetSimApp().TransferKeeper.SetParams(suite.chainB.GetContext(), types.Params{ReceiveEnabled: false})
|
|
},
|
|
channeltypes.NewErrorAcknowledgement(types.ErrReceiveDisabled),
|
|
"fungible token transfers to this chain are disabled",
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.SetupTest() // reset
|
|
|
|
path = ibctesting.NewTransferPath(suite.chainA, suite.chainB)
|
|
path.Setup()
|
|
|
|
token := types.Token{
|
|
Denom: types.NewDenom(sdk.DefaultBondDenom),
|
|
Amount: sdkmath.NewInt(100).String(),
|
|
}
|
|
packetData := types.NewFungibleTokenPacketData(
|
|
token.Denom.Path(),
|
|
token.Amount,
|
|
suite.chainA.SenderAccount.GetAddress().String(),
|
|
suite.chainB.SenderAccount.GetAddress().String(),
|
|
"",
|
|
)
|
|
|
|
expectedAttributes = []sdk.Attribute{
|
|
sdk.NewAttribute(types.AttributeKeySender, packetData.Sender),
|
|
sdk.NewAttribute(types.AttributeKeyReceiver, packetData.Receiver),
|
|
sdk.NewAttribute(types.AttributeKeyDenom, packetData.Denom),
|
|
sdk.NewAttribute(types.AttributeKeyAmount, packetData.Amount),
|
|
sdk.NewAttribute(types.AttributeKeyMemo, packetData.Memo),
|
|
}
|
|
if tc.expAck == nil || tc.expAck.Success() {
|
|
expectedAttributes = append(expectedAttributes, sdk.NewAttribute(types.AttributeKeyAckSuccess, "true"))
|
|
} else {
|
|
expectedAttributes = append(expectedAttributes,
|
|
sdk.NewAttribute(types.AttributeKeyAckSuccess, "false"),
|
|
sdk.NewAttribute(types.AttributeKeyAckError, tc.expEventErrorMsg),
|
|
)
|
|
}
|
|
|
|
seq := uint64(1)
|
|
packet = channeltypes.NewPacket(packetData.GetBytes(), seq, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.ZeroHeight(), suite.chainA.GetTimeoutTimestamp())
|
|
|
|
ctx := suite.chainB.GetContext()
|
|
cbs, ok := suite.chainB.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort)
|
|
suite.Require().True(ok)
|
|
|
|
tc.malleate() // change fields in packet
|
|
|
|
ack := cbs.OnRecvPacket(ctx, path.EndpointB.GetChannel().Version, packet, suite.chainB.SenderAccount.GetAddress())
|
|
|
|
suite.Require().Equal(tc.expAck, ack)
|
|
|
|
expectedEvents := sdk.Events{
|
|
sdk.NewEvent(
|
|
types.EventTypePacket,
|
|
expectedAttributes...,
|
|
),
|
|
}.ToABCIEvents()
|
|
|
|
expectedEvents = sdk.MarkEventsToIndex(expectedEvents, map[string]struct{}{})
|
|
ibctesting.AssertEvents(&suite.Suite, expectedEvents, ctx.EventManager().Events().ToABCIEvents())
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *TransferTestSuite) TestOnAcknowledgePacket() {
|
|
var (
|
|
path *ibctesting.Path
|
|
packet channeltypes.Packet
|
|
ack []byte
|
|
)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
malleate func()
|
|
expError error
|
|
expRefund bool
|
|
}{
|
|
{
|
|
"success",
|
|
func() {},
|
|
nil,
|
|
false,
|
|
},
|
|
{
|
|
"success: refund coins",
|
|
func() {
|
|
ack = channeltypes.NewErrorAcknowledgement(ibcerrors.ErrInsufficientFunds).Acknowledgement()
|
|
},
|
|
nil,
|
|
true,
|
|
},
|
|
{
|
|
"cannot refund ack on non-existent channel",
|
|
func() {
|
|
ack = channeltypes.NewErrorAcknowledgement(ibcerrors.ErrInsufficientFunds).Acknowledgement()
|
|
|
|
packet.SourceChannel = "channel-100"
|
|
},
|
|
errors.New("unable to unescrow tokens"),
|
|
false,
|
|
},
|
|
{
|
|
"invalid packet data",
|
|
func() {
|
|
packet.Data = []byte("invalid data")
|
|
},
|
|
ibcerrors.ErrInvalidType,
|
|
false,
|
|
},
|
|
{
|
|
"invalid acknowledgement",
|
|
func() {
|
|
ack = []byte("invalid ack")
|
|
},
|
|
ibcerrors.ErrUnknownRequest,
|
|
false,
|
|
},
|
|
{
|
|
"cannot refund already acknowledged packet",
|
|
func() {
|
|
ack = channeltypes.NewErrorAcknowledgement(ibcerrors.ErrInsufficientFunds).Acknowledgement()
|
|
|
|
cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort)
|
|
suite.Require().True(ok)
|
|
|
|
suite.Require().NoError(cbs.OnAcknowledgementPacket(suite.chainA.GetContext(), path.EndpointA.GetChannel().Version, packet, ack, suite.chainA.SenderAccount.GetAddress()))
|
|
},
|
|
errors.New("unable to unescrow tokens"),
|
|
false,
|
|
},
|
|
{
|
|
// See https://github.com/cosmos/ibc-go/security/advisories/GHSA-jg6f-48ff-5xrw
|
|
"non-deterministic JSON ack serialization should return an error",
|
|
func() {
|
|
// Create a valid acknowledgement using deterministic serialization.
|
|
ack = channeltypes.NewResultAcknowledgement([]byte{byte(1)}).Acknowledgement()
|
|
// Introduce non-determinism: insert an extra space after the first character '{'
|
|
// This will deserialize correctly but fail to re-serialize to the expected bytes.
|
|
if len(ack) > 0 && ack[0] == '{' {
|
|
ack = []byte("{ " + string(ack[1:]))
|
|
}
|
|
},
|
|
errors.New("acknowledgement did not marshal to expected bytes"),
|
|
false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.SetupTest() // reset
|
|
|
|
path = ibctesting.NewTransferPath(suite.chainA, suite.chainB)
|
|
path.Setup()
|
|
|
|
timeoutHeight := suite.chainA.GetTimeoutHeight()
|
|
msg := types.NewMsgTransfer(
|
|
path.EndpointA.ChannelConfig.PortID,
|
|
path.EndpointA.ChannelID,
|
|
ibctesting.TestCoin,
|
|
suite.chainA.SenderAccount.GetAddress().String(),
|
|
suite.chainB.SenderAccount.GetAddress().String(),
|
|
timeoutHeight,
|
|
0,
|
|
"",
|
|
)
|
|
res, err := suite.chainA.SendMsgs(msg)
|
|
suite.Require().NoError(err) // message committed
|
|
|
|
packet, err = ibctesting.ParseV1PacketFromEvents(res.Events)
|
|
suite.Require().NoError(err)
|
|
|
|
cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort)
|
|
suite.Require().True(ok)
|
|
|
|
ack = channeltypes.NewResultAcknowledgement([]byte{byte(1)}).Acknowledgement()
|
|
|
|
tc.malleate() // change fields in packet
|
|
|
|
err = cbs.OnAcknowledgementPacket(suite.chainA.GetContext(), path.EndpointA.GetChannel().Version, packet, ack, suite.chainA.SenderAccount.GetAddress())
|
|
|
|
if tc.expError == nil {
|
|
suite.Require().NoError(err)
|
|
|
|
if tc.expRefund {
|
|
escrowAddress := types.GetEscrowAddress(packet.GetSourcePort(), packet.GetSourceChannel())
|
|
escrowBalanceAfter := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, sdk.DefaultBondDenom)
|
|
suite.Require().Equal(sdkmath.NewInt(0), escrowBalanceAfter.Amount)
|
|
}
|
|
} else {
|
|
suite.Require().Error(err)
|
|
suite.Require().Contains(err.Error(), tc.expError.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *TransferTestSuite) TestOnTimeoutPacket() {
|
|
var path *ibctesting.Path
|
|
var packet channeltypes.Packet
|
|
|
|
testCases := []struct {
|
|
name string
|
|
coinsToSendToB sdk.Coin
|
|
malleate func()
|
|
expError error
|
|
}{
|
|
{
|
|
"success",
|
|
ibctesting.TestCoin,
|
|
func() {},
|
|
nil,
|
|
},
|
|
{
|
|
"non-existent channel",
|
|
ibctesting.TestCoin,
|
|
func() {
|
|
packet.SourceChannel = "channel-100"
|
|
},
|
|
errors.New("unable to unescrow tokens"),
|
|
},
|
|
{
|
|
"invalid packet data",
|
|
ibctesting.TestCoin,
|
|
func() {
|
|
packet.Data = []byte("invalid data")
|
|
},
|
|
ibcerrors.ErrInvalidType,
|
|
},
|
|
{
|
|
"already timed-out packet",
|
|
ibctesting.TestCoin,
|
|
func() {
|
|
cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort)
|
|
suite.Require().True(ok)
|
|
|
|
suite.Require().NoError(cbs.OnTimeoutPacket(suite.chainA.GetContext(), path.EndpointA.GetChannel().Version, packet, suite.chainA.SenderAccount.GetAddress()))
|
|
},
|
|
errors.New("unable to unescrow tokens"),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
suite.SetupTest() // reset
|
|
|
|
path = ibctesting.NewTransferPath(suite.chainA, suite.chainB)
|
|
path.Setup()
|
|
|
|
timeoutHeight := suite.chainA.GetTimeoutHeight()
|
|
msg := types.NewMsgTransfer(
|
|
path.EndpointA.ChannelConfig.PortID,
|
|
path.EndpointA.ChannelID,
|
|
tc.coinsToSendToB,
|
|
suite.chainA.SenderAccount.GetAddress().String(),
|
|
suite.chainB.SenderAccount.GetAddress().String(),
|
|
timeoutHeight,
|
|
0,
|
|
"",
|
|
)
|
|
res, err := suite.chainA.SendMsgs(msg)
|
|
suite.Require().NoError(err) // message committed
|
|
|
|
packet, err = ibctesting.ParseV1PacketFromEvents(res.Events)
|
|
suite.Require().NoError(err)
|
|
|
|
cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort)
|
|
suite.Require().True(ok)
|
|
|
|
tc.malleate() // change fields in packet
|
|
|
|
err = cbs.OnTimeoutPacket(suite.chainA.GetContext(), path.EndpointA.GetChannel().Version, packet, suite.chainA.SenderAccount.GetAddress())
|
|
|
|
if tc.expError == nil {
|
|
suite.Require().NoError(err)
|
|
|
|
escrowAddress := types.GetEscrowAddress(packet.GetSourcePort(), packet.GetSourceChannel())
|
|
escrowBalanceAfter := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, sdk.DefaultBondDenom)
|
|
suite.Require().Equal(sdkmath.NewInt(0), escrowBalanceAfter.Amount)
|
|
} else {
|
|
suite.Require().Error(err)
|
|
suite.Require().Contains(err.Error(), tc.expError.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (suite *TransferTestSuite) TestPacketDataUnmarshalerInterface() {
|
|
var (
|
|
sender = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String()
|
|
receiver = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String()
|
|
|
|
data []byte
|
|
initialPacketData any
|
|
)
|
|
|
|
testCases := []struct {
|
|
name string
|
|
malleate func()
|
|
expError error
|
|
}{
|
|
{
|
|
"success: valid packet data with memo",
|
|
func() {
|
|
initialPacketData = types.FungibleTokenPacketData{
|
|
Denom: ibctesting.TestCoin.Denom,
|
|
Amount: ibctesting.TestCoin.Amount.String(),
|
|
Sender: sender,
|
|
Receiver: receiver,
|
|
Memo: "some memo",
|
|
}
|
|
data = initialPacketData.(types.FungibleTokenPacketData).GetBytes()
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"success: valid packet data denom with trace",
|
|
func() {
|
|
initialPacketData = types.FungibleTokenPacketData{
|
|
Denom: "transfer/channel-0/atom",
|
|
Amount: ibctesting.TestCoin.Amount.String(),
|
|
Sender: sender,
|
|
Receiver: receiver,
|
|
Memo: "",
|
|
}
|
|
|
|
data = initialPacketData.(types.FungibleTokenPacketData).GetBytes()
|
|
},
|
|
nil,
|
|
},
|
|
{
|
|
"failure: invalid packet data",
|
|
func() {
|
|
data = []byte("invalid packet data")
|
|
},
|
|
errors.New("cannot unmarshal ICS20-V1 transfer packet data: invalid character 'i' looking for beginning of value: invalid type"),
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
suite.Run(tc.name, func() {
|
|
tc.malleate()
|
|
|
|
path := ibctesting.NewTransferPath(suite.chainA, suite.chainB)
|
|
path.Setup()
|
|
|
|
transferStack, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(types.ModuleName)
|
|
suite.Require().True(ok)
|
|
|
|
unmarshalerStack, ok := transferStack.(porttypes.PacketDataUnmarshaler)
|
|
suite.Require().True(ok)
|
|
|
|
packetData, version, err := unmarshalerStack.UnmarshalPacketData(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, data)
|
|
|
|
if tc.expError == nil {
|
|
suite.Require().NoError(err)
|
|
|
|
v2PacketData, ok := packetData.(types.InternalTransferRepresentation)
|
|
suite.Require().True(ok)
|
|
suite.Require().Equal(path.EndpointA.ChannelConfig.Version, version)
|
|
|
|
if v1PacketData, ok := initialPacketData.(types.FungibleTokenPacketData); ok {
|
|
// Note: testing of the denom trace parsing/conversion should be done as part of testing internal conversion functions
|
|
suite.Require().Equal(v1PacketData.Amount, v2PacketData.Token.Amount)
|
|
suite.Require().Equal(v1PacketData.Sender, v2PacketData.Sender)
|
|
suite.Require().Equal(v1PacketData.Receiver, v2PacketData.Receiver)
|
|
suite.Require().Equal(v1PacketData.Memo, v2PacketData.Memo)
|
|
} else {
|
|
suite.Require().Equal(initialPacketData.(types.InternalTransferRepresentation), v2PacketData)
|
|
}
|
|
} else {
|
|
suite.Require().Error(err)
|
|
suite.Require().Contains(err.Error(), tc.expError.Error())
|
|
}
|
|
})
|
|
}
|
|
}
|