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

chore(wormchain): ibc composability mw testing #77

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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
45 changes: 45 additions & 0 deletions wormchain/x/ibc-composability-mw/keeper/genesis_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package keeper_test

import (
"testing"

"github.com/stretchr/testify/require"
keepertest "github.com/wormhole-foundation/wormchain/testutil/keeper"
"github.com/wormhole-foundation/wormchain/x/ibc-composability-mw/types"
)

// TestGenesis ensures genesis state can be initialiazed and exported correctly
joelsmith-2019 marked this conversation as resolved.
Show resolved Hide resolved
func TestGenesis(t *testing.T) {
for _, tc := range []struct {
dataInFlight map[string][]byte
}{
{
dataInFlight: map[string][]byte{},
},
{
dataInFlight: map[string][]byte{
"key1": []byte("value1"),
},
},
{
dataInFlight: map[string][]byte{
"key1": []byte("value1"),
"key2": []byte("value2"),
"key3": []byte("value3"),
},
},
} {
genesisState := types.GenesisState{
TransposedDataInFlight: tc.dataInFlight,
}

app, ctx := keepertest.SetupWormchainAndContext(t)
keeper := app.IbcComposabilityMwKeeper

keeper.InitGenesis(ctx, genesisState)

outputState := keeper.ExportGenesis(ctx)

require.Equal(t, genesisState, *outputState)
}
}
118 changes: 118 additions & 0 deletions wormchain/x/ibc-composability-mw/keeper/keeper_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package keeper_test

import (
_ "embed"
"encoding/json"
"testing"

transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types"
channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
"github.com/stretchr/testify/require"
keepertest "github.com/wormhole-foundation/wormchain/testutil/keeper"
"github.com/wormhole-foundation/wormchain/x/ibc-composability-mw/types"
wormholetypes "github.com/wormhole-foundation/wormchain/x/wormhole/types"
)

// TestPackets ensure that packets are handled correctly by the ibc composability middleware.
// This test will only be able to process IBC hooks messages and not PFM because the test
// requires a full chain setup with interchaintest.
func TestPackets(t *testing.T) {
// setup app & get keepers & ctx
app, ctx := keepertest.SetupWormchainAndContext(t)
whKeeper := app.WormholeKeeper
keeper := app.IbcComposabilityMwKeeper

// set ibc composability contract
whKeeper.StoreIbcComposabilityMwContract(ctx, wormholetypes.IbcComposabilityMwContract{
ContractAddress: "wormhole1du4amsmvx8yqr8whw7qc5m3c0zpwknmzelwqy6",
})

// define a packet with no ibc token bridge payload
packetDataNoPayload, err := json.Marshal(transfertypes.FungibleTokenPacketData{
Denom: "uworm",
Amount: "100",
Sender: "sender",
Receiver: "receiver",
Memo: "",
})
require.NoError(t, err)

// define gateway payload for packet
gatewayTBPayload, err := json.Marshal(types.GatewayIbcTokenBridgePayload{
GatewayIbcTokenBridgePayloadObj: types.GatewayIbcTokenBridgePayloadObj{
Transfer: types.GatewayTransfer{
Chain: 1,
Recipient: []byte("recipient"),
Fee: "0uworm",
Nonce: 1,
},
},
})
require.NoError(t, err)

// define a packet with a valid ibc token bridge payload
packetDataWithPayload, err := json.Marshal(transfertypes.FungibleTokenPacketData{
Denom: "uworm",
Amount: "100",
Sender: "sender",
Receiver: "receiver",
Memo: string(gatewayTBPayload),
})
require.NoError(t, err)

for _, tc := range []struct {
testName string
packet channeltypes.Packet
shouldErr bool
}{
{
testName: "empty packet - expect error",
shouldErr: true,
},
{
testName: "packet with no data - expect error",
packet: channeltypes.Packet{
Data: []byte("wrong data format"),
},
shouldErr: true,
},
{
testName: "packet with no memo in data - expect error",
packet: channeltypes.Packet{
Data: packetDataNoPayload,
},
shouldErr: true,
},
{
testName: "packet with payload - expect success",
packet: channeltypes.Packet{
Sequence: 1,
SourcePort: "transfer",
SourceChannel: "channel-0",
DestinationPort: "transfer",
DestinationChannel: "channel-0",
Data: packetDataWithPayload,
},
shouldErr: false,
},
} {

packet, ack := keeper.OnRecvPacket(ctx, tc.packet)

t.Run(tc.testName, func(t *testing.T) {

if tc.shouldErr {
require.NotNil(t, ack)
return
joelsmith-2019 marked this conversation as resolved.
Show resolved Hide resolved
} else {
require.NotNil(t, packet)
require.Nil(t, ack)
}

// Should return nil because the packet is not transposed (it is an ibc hooks packet)
res := keeper.GetAndClearTransposedData(ctx, tc.packet.DestinationChannel, tc.packet.DestinationPort, tc.packet.Sequence)
require.Nil(t, res)
})

}
}
85 changes: 85 additions & 0 deletions wormchain/x/ibc-composability-mw/types/gateway_payload_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package types_test

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
"github.com/wormhole-foundation/wormchain/x/ibc-composability-mw/types"
)

func TestGatewayPayloads(t *testing.T) {

joelsmith-2019 marked this conversation as resolved.
Show resolved Hide resolved
for _, tc := range []struct {
memo string // use memo if present, otherwise marshal tbPayload with json
tbPayload types.GatewayIbcTokenBridgePayload
shouldErr bool
joelsmith-2019 marked this conversation as resolved.
Show resolved Hide resolved
}{
{
memo: "abc123",
shouldErr: true,
},
{
tbPayload: types.GatewayIbcTokenBridgePayload{},
shouldErr: true,
},
{
tbPayload: types.GatewayIbcTokenBridgePayload{
GatewayIbcTokenBridgePayloadObj: types.GatewayIbcTokenBridgePayloadObj{
Transfer: types.GatewayTransfer{
Chain: 1,
Recipient: []byte("recipient"),
Fee: "0uworm",
Nonce: 1,
},
},
},
shouldErr: false,
},
{
tbPayload: types.GatewayIbcTokenBridgePayload{
GatewayIbcTokenBridgePayloadObj: types.GatewayIbcTokenBridgePayloadObj{
TransferWithPayload: types.GatewayTransferWithPayload{
Chain: 1,
Contract: []byte("contract"),
Payload: []byte("{\"payload\":\"data\"}"),
Nonce: 1,
},
},
},
shouldErr: false,
},
} {

memo := tc.memo

if memo == "" {
bz, err := json.Marshal(tc.tbPayload)
require.NoError(t, err)
memo = string(bz)
}

payload, err := types.VerifyAndParseGatewayPayload(memo)

if tc.shouldErr {
require.Error(t, err)
// continue to next case if err
continue
} else {
require.NoError(t, err)
}

// validate payload was parsed correctly
if payload.NoPayload {
require.Equal(t, tc.tbPayload.GatewayIbcTokenBridgePayloadObj.Transfer.Chain, payload.ChainId)
require.Equal(t, tc.tbPayload.GatewayIbcTokenBridgePayloadObj.Transfer.Recipient, payload.Recipient)
require.Equal(t, tc.tbPayload.GatewayIbcTokenBridgePayloadObj.Transfer.Fee, payload.Fee)
require.Equal(t, tc.tbPayload.GatewayIbcTokenBridgePayloadObj.Transfer.Nonce, payload.Nonce)
} else {
require.Equal(t, tc.tbPayload.GatewayIbcTokenBridgePayloadObj.TransferWithPayload.Chain, payload.ChainId)
require.Equal(t, tc.tbPayload.GatewayIbcTokenBridgePayloadObj.TransferWithPayload.Contract, payload.Recipient)
require.Equal(t, tc.tbPayload.GatewayIbcTokenBridgePayloadObj.TransferWithPayload.Payload, payload.Payload)
require.Equal(t, tc.tbPayload.GatewayIbcTokenBridgePayloadObj.TransferWithPayload.Nonce, payload.Nonce)
}
}
}
86 changes: 86 additions & 0 deletions wormchain/x/ibc-composability-mw/types/ibc_hooks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package types_test

import (
"testing"

"github.com/stretchr/testify/require"
"github.com/wormhole-foundation/wormchain/x/ibc-composability-mw/types"
)

func TestFormatIbcHooksMemo(t *testing.T) {

joelsmith-2019 marked this conversation as resolved.
Show resolved Hide resolved
ibcTranslatorContract := "wormhole123abc"

for _, tc := range []struct {
payload types.ParsedPayload
shouldErr bool
}{
// Normal w/ no payload
joelsmith-2019 marked this conversation as resolved.
Show resolved Hide resolved
{
payload: types.ParsedPayload{
NoPayload: true,
ChainId: 1,
Recipient: []byte{'a', 'b', 'c'},
Fee: "0uworm",
Nonce: 1,
Payload: nil,
},
shouldErr: false,
},
// Provide payload when unnecessary
{
payload: types.ParsedPayload{
NoPayload: true,
ChainId: 1,
Recipient: []byte{'a', 'b', 'c'},
Fee: "0uworm",
Nonce: 1,
Payload: []byte("{\"payload\":\"data\"}"),
},
shouldErr: false,
},
// Normal w/ payload
{
payload: types.ParsedPayload{
NoPayload: false,
ChainId: 1,
Recipient: []byte{'a', 'b', 'c'},
Fee: "0uworm",
Nonce: 1,
Payload: []byte("{\"payload\":\"data\"}"),
},
shouldErr: false,
},
// Nil payload should not err
{
payload: types.ParsedPayload{
NoPayload: true,
ChainId: 1,
Recipient: []byte{'a', 'b', 'c'},
Fee: "0uworm",
Nonce: 1,
Payload: nil,
},
shouldErr: false,
},
} {
res, err := types.FormatIbcHooksMemo(tc.payload, ibcTranslatorContract)

if tc.shouldErr {
require.Error(t, err)
continue
} else {
require.NoError(t, err)
require.NotNil(t, res)
}

if tc.payload.NoPayload {
require.NotContains(t, res, "gateway_convert_and_transfer_with_payload")
require.Contains(t, res, "recipient")
} else {
require.Contains(t, res, "gateway_convert_and_transfer_with_payload")
require.NotContains(t, res, "recipient")
require.Contains(t, res, "payload")
}
}
}
Loading
Loading