diff --git a/.github/workflows/e2e-compatibility.yaml b/.github/workflows/e2e-compatibility.yaml index 622c143feca..c4d1d2c5c50 100644 --- a/.github/workflows/e2e-compatibility.yaml +++ b/.github/workflows/e2e-compatibility.yaml @@ -218,15 +218,6 @@ jobs: test-file: "e2e/tests/transfer/authz_test.go" release-version: "${{ needs.determine-image-tag.outputs.release-version }}" - transfer-forwarding-test: - needs: - - build-release-images - - determine-image-tag - uses: ./.github/workflows/e2e-compatibility-workflow-call.yaml - with: - test-file: "e2e/tests/transfer/forwarding_test.go" - release-version: "${{ needs.determine-image-tag.outputs.release-version }}" - transfer-incentivized-test-a: needs: - build-release-images diff --git a/.github/workflows/e2e-fork.yml b/.github/workflows/e2e-fork.yml index 006f1363e45..0e417bfeb37 100644 --- a/.github/workflows/e2e-fork.yml +++ b/.github/workflows/e2e-fork.yml @@ -32,7 +32,7 @@ jobs: output=$(go run cmd/build_test_matrix/main.go) echo "matrix=$output" >> $GITHUB_OUTPUT env: - TEST_EXCLUSIONS: 'TestUpgradeTestSuite,TestIBCWasmUpgradeTestSuite' + TEST_EXCLUSIONS: 'TestUpgradeTestSuite' e2e-fork: env: diff --git a/.github/workflows/e2e-test-workflow-call.yml b/.github/workflows/e2e-test-workflow-call.yml index 039afdaaf4a..4e09295a143 100644 --- a/.github/workflows/e2e-test-workflow-call.yml +++ b/.github/workflows/e2e-test-workflow-call.yml @@ -257,7 +257,6 @@ jobs: - entrypoint: TestConnectionTestSuite - entrypoint: TestInterchainAccountsGovTestSuite - entrypoint: TestIncentivizedTransferTestSuite - - entrypoint: TestTransferForwardingTestSuite steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/e2e-upgrade.yaml b/.github/workflows/e2e-upgrade.yaml index adca6a3d2e9..6921dfa536f 100644 --- a/.github/workflows/e2e-upgrade.yaml +++ b/.github/workflows/e2e-upgrade.yaml @@ -69,17 +69,6 @@ jobs: test: "TestV8ToV8_1ChainUpgrade_FeeMiddlewareChannelUpgrade" upload-logs: true - upgrade-ibcwasm-v8: - uses: ./.github/workflows/e2e-test-workflow-call.yml - with: - chain-image: ghcr.io/cosmos/ibc-go-wasm-simd - chain-a-tag: v7.3.0-e2e-upgrade - chain-b-tag: v7.3.0-e2e-upgrade - upgrade-plan-name: "ibcwasm-v8" - test-entry-point: "TestIBCWasmUpgradeTestSuite" - test: "TestIBCWasmChainUpgrade" - upload-logs: true - upgrade-v9: uses: ./.github/workflows/e2e-test-workflow-call.yml with: @@ -102,13 +91,3 @@ jobs: test: "TestV8ToV9ChainUpgrade_Localhost" upload-logs: true - upgrade-v9-channel-upgrades: - uses: ./.github/workflows/e2e-test-workflow-call.yml - with: - chain-image: ghcr.io/cosmos/ibc-go-simd - chain-a-tag: v8.4.0 - chain-b-tag: v9.0.0 - upgrade-plan-name: "v9" - test-entry-point: "TestUpgradeTestSuite" - test: "TestV8ToV9ChainUpgrade_ICS20v2ChannelUpgrade" - upload-logs: true diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 67414eb1ef5..858082770a0 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -66,5 +66,5 @@ jobs: chain-b-tag: '${{ needs.determine-image-tag.outputs.simd-tag }}' # on regular PRs we won't run upgrade tests. # NOTE: we are excluding TestTransferTestSuite as we run this full suite instead of each individual test. - test-exclusions: 'TestUpgradeTestSuite,TestIBCWasmUpgradeTestSuite,TestTransferTestSuite,TestAuthzTransferTestSuite,TestTransferTestSuiteSendReceive,TestTransferTestSuiteSendEnabled,TestTransferLocalhostTestSuite,TestConnectionTestSuite,TestInterchainAccountsGovTestSuite,TestIncentivizedTransferTestSuite,TestTransferForwardingTestSuite' + test-exclusions: 'TestUpgradeTestSuite,TestTransferTestSuite,TestAuthzTransferTestSuite,TestTransferTestSuiteSendReceive,TestTransferTestSuiteSendEnabled,TestTransferLocalhostTestSuite,TestConnectionTestSuite,TestInterchainAccountsGovTestSuite,TestIncentivizedTransferTestSuite' temp-run-full-suite: true diff --git a/e2e/tests/core/03-connection/connection_test.go b/e2e/tests/core/03-connection/connection_test.go index 322cd865cbe..47253621684 100644 --- a/e2e/tests/core/03-connection/connection_test.go +++ b/e2e/tests/core/03-connection/connection_test.go @@ -114,7 +114,7 @@ func (s *ConnectionTestSuite) TestMaxExpectedTimePerBlockParam() { t.Run("ensure packets can be received, send from chainB to chainA", func(t *testing.T) { t.Run("send tokens from chainB to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferCoins(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferAmount(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "") s.AssertTxSuccess(transferTxResp) }) diff --git a/e2e/tests/transfer/authz_test.go b/e2e/tests/transfer/authz_test.go index 2c0efe6cd79..feb11b6cd01 100644 --- a/e2e/tests/transfer/authz_test.go +++ b/e2e/tests/transfer/authz_test.go @@ -129,13 +129,12 @@ func (suite *AuthzTransferTestSuite) TestAuthz_MsgTransfer_Succeeds() { channelA.PortID, channelA.ChannelID, channelA.Version, - testvalues.DefaultTransferCoins(chainADenom), + testvalues.DefaultTransferAmount(chainADenom), granterAddress, receiverWalletAddress, suite.GetTimeoutHeight(ctx, chainB), 0, "", - nil, ) protoAny, err := codectypes.NewAnyWithValue(transferMsg) @@ -190,13 +189,12 @@ func (suite *AuthzTransferTestSuite) TestAuthz_MsgTransfer_Succeeds() { channelA.PortID, channelA.ChannelID, channelA.Version, - testvalues.DefaultTransferCoins(chainADenom), + testvalues.DefaultTransferAmount(chainADenom), granterAddress, receiverWalletAddress, suite.GetTimeoutHeight(ctx, chainB), 0, "", - nil, ) protoAny, err := codectypes.NewAnyWithValue(transferMsg) @@ -276,13 +274,12 @@ func (suite *AuthzTransferTestSuite) TestAuthz_InvalidTransferAuthorizations() { channelA.PortID, channelA.ChannelID, channelA.Version, - sdk.NewCoins(sdk.Coin{Denom: chainADenom, Amount: sdkmath.NewInt(invalidSpendAmount)}), + sdk.Coin{Denom: chainADenom, Amount: sdkmath.NewInt(invalidSpendAmount)}, granterAddress, receiverWalletAddress, suite.GetTimeoutHeight(ctx, chainB), 0, "", - nil, ) protoAny, err := codectypes.NewAnyWithValue(transferMsg) @@ -337,13 +334,12 @@ func (suite *AuthzTransferTestSuite) TestAuthz_InvalidTransferAuthorizations() { channelA.PortID, channelA.ChannelID, channelA.Version, - sdk.NewCoins(sdk.Coin{Denom: chainADenom, Amount: sdkmath.NewInt(spendLimit)}), + sdk.Coin{Denom: chainADenom, Amount: sdkmath.NewInt(spendLimit)}, granterAddress, invalidWalletAddress, suite.GetTimeoutHeight(ctx, chainB), 0, "", - nil, ) protoAny, err := codectypes.NewAnyWithValue(transferMsg) diff --git a/e2e/tests/transfer/base_test.go b/e2e/tests/transfer/base_test.go index 882536ef82c..2020ee2f1cf 100644 --- a/e2e/tests/transfer/base_test.go +++ b/e2e/tests/transfer/base_test.go @@ -81,7 +81,7 @@ func (s *TransferTestSuite) TestMsgTransfer_Succeeds_Nonincentivized() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("native IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -125,7 +125,7 @@ func (s *TransferTestSuite) TestMsgTransfer_Succeeds_Nonincentivized() { } t.Run("non-native IBC token transfer from chainB to chainA, receiver is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferCoins(chainBIBCToken.IBCDenom()), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferAmount(chainBIBCToken.IBCDenom()), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -165,236 +165,6 @@ func (s *TransferTestSuite) TestMsgTransfer_Succeeds_Nonincentivized() { // } } -// TestMsgTransfer_Succeeds_Nonincentivized_MultiDenom will test sending successful IBC transfers from chainA to chainB. -// A multidenom transfer with native chainB tokens and IBC tokens from chainA is executed from chainB to chainA. -// compatibility:TestMsgTransfer_Succeeds_Nonincentivized_MultiDenom:from_versions: v9.0.0 -func (s *TransferTestSuite) TestMsgTransfer_Succeeds_Nonincentivized_MultiDenom() { - t := s.T() - ctx := context.TODO() - - testName := t.Name() - t.Parallel() - relayer, channelA := s.CreateTransferPath(testName) - - chainA, chainB := s.GetChains() - - chainADenom := chainA.Config().Denom - chainBDenom := chainB.Config().Denom - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID) - chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID) - - t.Run("native IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, sdk.NewCoins(testvalues.DefaultTransferAmount(chainADenom)), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) - s.AssertTxSuccess(transferTxResp) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("native chainA tokens are escrowed", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance) - - // https://github.com/cosmos/ibc-go/issues/6742 - // actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) - // s.Require().NoError(err) - // - // expectedTotalEscrow := sdk.NewCoin(chainADenom, sdkmath.NewInt(testvalues.IBCTransferAmount)) - // s.Require().Equal(expectedTotalEscrow, actualTotalEscrow) - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) - - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - - t.Run("metadata for IBC denomination exists on chainB", func(t *testing.T) { - s.AssertHumanReadableDenom(ctx, chainB, chainADenom, channelA) - }) - - // send the native chainB denom and also the ibc token from chainA - transferCoins := []sdk.Coin{ - testvalues.DefaultTransferAmount(chainBIBCToken.IBCDenom()), - testvalues.DefaultTransferAmount(chainBDenom), - } - - t.Run("native token from chain B and non-native IBC token from chainA, both to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, transferCoins, chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) - s.AssertTxSuccess(transferTxResp) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainB, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1) - - t.Run("chain A native denom", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("chain B IBC denom", func(t *testing.T) { - actualBalance, err := query.Balance(ctx, chainA, chainAAddress, chainAIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - }) - - // https://github.com/cosmos/ibc-go/issues/6742 - // t.Run("native chainA tokens are un-escrowed", func(t *testing.T) { - // actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) - // s.Require().NoError(err) - // s.Require().Equal(sdk.NewCoin(chainADenom, sdkmath.NewInt(0)), actualTotalEscrow) // total escrow is zero because tokens have come back - // }) -} - -// TestMsgTransfer_Fails_InvalidAddress_MultiDenom attempts to send a multidenom IBC transfer -// to an invalid address and ensures that the tokens on the sending chain are returned to the sender. -// compatibility:TestMsgTransfer_Fails_InvalidAddress_MultiDenom:from_versions: v9.0.0 -func (s *TransferTestSuite) TestMsgTransfer_Fails_InvalidAddress_MultiDenom() { - t := s.T() - ctx := context.TODO() - - testName := t.Name() - t.Parallel() - relayer, channelA := s.CreateTransferPath(testName) - - chainA, chainB := s.GetChains() - - chainADenom := chainA.Config().Denom - chainBDenom := chainB.Config().Denom - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID) - - t.Run("native IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, sdk.NewCoins(testvalues.DefaultTransferAmount(chainADenom)), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) - s.AssertTxSuccess(transferTxResp) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("native chainA tokens are escrowed", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance) - - // https://github.com/cosmos/ibc-go/issues/6742 - // actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) - // s.Require().NoError(err) - // - // expectedTotalEscrow := sdk.NewCoin(chainADenom, sdkmath.NewInt(testvalues.IBCTransferAmount)) - // s.Require().Equal(expectedTotalEscrow, actualTotalEscrow) - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) - - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - - t.Run("metadata for IBC denomination exists on chainB", func(t *testing.T) { - s.AssertHumanReadableDenom(ctx, chainB, chainADenom, channelA) - }) - - // send the native chainB denom and also the ibc token from chainA - transferCoins := []sdk.Coin{ - testvalues.DefaultTransferAmount(chainBIBCToken.IBCDenom()), - testvalues.DefaultTransferAmount(chainBDenom), - } - - t.Run("stop relayer", func(t *testing.T) { - s.StopRelayer(ctx, relayer) - }) - - t.Run("native token from chain B and non-native IBC token from chainA, both to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, transferCoins, chainBAddress, testvalues.InvalidAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) - s.AssertTxSuccess(transferTxResp) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("tokens are sent from chain B", func(t *testing.T) { - t.Run("native chainB tokens are escrowed", func(t *testing.T) { - actualBalance, err := s.GetChainBNativeBalance(ctx, chainBWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("non-native chainA IBC denom are burned", func(t *testing.T) { - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - s.Require().Equal(int64(0), actualBalance.Int64()) - }) - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainB, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1) - }) - - t.Run("tokens are returned to sender on chainB", func(t *testing.T) { - t.Run("native chainB denom", func(t *testing.T) { - actualBalance, err := s.GetChainBNativeBalance(ctx, chainBWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("non-native chainA IBC denom", func(t *testing.T) { - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - }) -} - // TestMsgTransfer_Fails_InvalidAddress attempts to send an IBC transfer to an invalid address and ensures // that the tokens on the sending chain are unescrowed. func (s *TransferTestSuite) TestMsgTransfer_Fails_InvalidAddress() { @@ -415,7 +185,7 @@ func (s *TransferTestSuite) TestMsgTransfer_Fails_InvalidAddress() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("native IBC token transfer from chainA to invalid address", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, testvalues.InvalidAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, testvalues.InvalidAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -523,7 +293,7 @@ func (s *TransferTestSuite) TestMsgTransfer_WithMemo() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("IBC token transfer with memo from chainA to chainB", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "memo", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "memo") s.AssertTxSuccess(transferTxResp) }) @@ -576,7 +346,7 @@ func (s *TransferTestSuite) TestMsgTransfer_EntireBalance() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("IBC token transfer from chainA to chainB", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, sdk.NewCoins(coinFromA), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, coinFromA, chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainA), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -606,16 +376,12 @@ func (s *TransferTestSuite) TestMsgTransfer_EntireBalance() { }) t.Run("send entire balance from B to A", func(t *testing.T) { - transferCoins := sdk.NewCoins(sdk.NewCoin(chainBIBCToken.IBCDenom(), transfertypes.UnboundedSpendLimit())) - if channelA.Version == transfertypes.V2 { - transferCoins = transferCoins.Add(sdk.NewCoin(chainB.Config().Denom, transfertypes.UnboundedSpendLimit())) - } + transferCoin := sdk.NewCoin(chainBIBCToken.IBCDenom(), transfertypes.UnboundedSpendLimit()) - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, transferCoins, chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, transferCoin, chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) - chainAIBCToken := testsuite.GetIBCToken(chainB.Config().Denom, channelA.PortID, channelA.ChannelID) t.Run("packets relayed", func(t *testing.T) { // test that chainA has the entire balance back of its native token. s.AssertPacketRelayed(ctx, chainB, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1) @@ -624,26 +390,10 @@ func (s *TransferTestSuite) TestMsgTransfer_EntireBalance() { s.Require().NoError(err) s.Require().Equal(testvalues.StartingTokenAmount, actualBalance.Int64()) - if channelA.Version == transfertypes.V2 { - // test that chainA has the entirety of chainB's IBC token denom. - actualBalance, err = query.Balance(ctx, chainA, chainAAddress, chainAIBCToken.IBCDenom()) - - s.Require().NoError(err) - s.Require().Equal(testvalues.StartingTokenAmount, actualBalance.Int64()) - } - // test that chainB has a zero balance of chainA's IBC token denom. actualBalance, err = query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) s.Require().NoError(err) s.Require().Zero(actualBalance.Int64()) - - if channelA.Version == transfertypes.V2 { - // test that chainB has a zero balance of its native token. - actualBalance, err = query.Balance(ctx, chainB, chainBAddress, chainB.Config().Denom) - - s.Require().NoError(err) - s.Require().Zero(actualBalance.Int64()) - } }) } diff --git a/e2e/tests/transfer/forwarding_test.go b/e2e/tests/transfer/forwarding_test.go deleted file mode 100644 index 47a9bbe6537..00000000000 --- a/e2e/tests/transfer/forwarding_test.go +++ /dev/null @@ -1,363 +0,0 @@ -//go:build !test_e2e - -package transfer - -import ( - "context" - "testing" - "time" - - "github.com/strangelove-ventures/interchaintest/v8/ibc" - test "github.com/strangelove-ventures/interchaintest/v8/testutil" - testifysuite "github.com/stretchr/testify/suite" - - "github.com/cosmos/ibc-go/e2e/testsuite" - "github.com/cosmos/ibc-go/e2e/testsuite/query" - "github.com/cosmos/ibc-go/e2e/testvalues" - transfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" -) - -// compatibility:from_version: v9.0.0 -func TestTransferForwardingTestSuite(t *testing.T) { - testifysuite.Run(t, new(TransferForwardingTestSuite)) -} - -type TransferForwardingTestSuite struct { - testsuite.E2ETestSuite -} - -// SetupSuite explicitly sets up three chains for this test suite. -func (s *TransferForwardingTestSuite) SetupSuite() { - s.SetupChains(context.TODO(), nil, testsuite.ThreeChainSetup()) -} - -// TestForwarding_WithLastChainBeingICS20v1_Succeeds tests the case where a token is forwarded and successfully -// received on a destination chain that is on ics20-v1 version. -func (s *TransferForwardingTestSuite) TestForwarding_WithLastChainBeingICS20v1_Succeeds() { - s.testForwardingThreeChains(transfertypes.V1) -} - -// TestForwarding_Succeeds tests the case where a token is forwarded and successfully -// received on a destination chain. -func (s *TransferForwardingTestSuite) TestForwarding_Succeeds() { - s.testForwardingThreeChains(transfertypes.V2) -} - -func (s *TransferForwardingTestSuite) testForwardingThreeChains(lastChainVersion string) { - ctx := context.TODO() - t := s.T() - - testName := t.Name() - t.Parallel() - relayer := s.CreateDefaultPaths(testName) - - chains := s.GetAllChains() - - chainA, chainB, chainC := chains[0], chains[1], chains[2] - - channelAtoB := s.GetChainAChannelForTest(testName) - - s.Require().Len(s.GetChannelsForTest(chainA, testName), 1, "expected one channel on chain A") - s.Require().Len(s.GetChannelsForTest(chainB, testName), 2, "expected two channels on chain B") - s.Require().Len(s.GetChannelsForTest(chainC, testName), 1, "expected one channel on chain C") - - var channelBtoC ibc.ChannelOutput - if lastChainVersion == transfertypes.V2 { - channelBtoC = s.GetChannelsForTest(chainB, testName)[1] - s.Require().Equal(transfertypes.V2, channelBtoC.Version, "the channel version is not ics20-2") - } else { - opts := s.TransferChannelOptions() - opts.Version = transfertypes.V1 - channelBtoC, _ = s.CreatePath(ctx, relayer, chainB, chainC, ibc.DefaultClientOpts(), opts, testName) - s.Require().Equal(transfertypes.V1, channelBtoC.Version, "the channel version is not ics20-1") - } - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - chainADenom := chainA.Config().Denom - - chainCWallet := s.CreateUserOnChainC(ctx, testvalues.StartingTokenAmount) - chainCAddress := chainCWallet.FormattedAddress() - - t.Run("IBC transfer from A to C with forwarding through B", func(t *testing.T) { - inFiveMinutes := time.Now().Add(5 * time.Minute).UnixNano() - forwarding := transfertypes.NewForwarding(false, transfertypes.NewHop(channelBtoC.PortID, channelBtoC.ChannelID)) - resp := s.Transfer(ctx, chainA, chainAWallet, channelAtoB.PortID, channelAtoB.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainCAddress, clienttypes.ZeroHeight(), uint64(inFiveMinutes), "", forwarding) - s.AssertTxSuccess(resp) - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("packets are relayed from A to B to C", func(t *testing.T) { - chainCDenom := transfertypes.NewDenom(chainADenom, - transfertypes.NewHop(channelBtoC.Counterparty.PortID, channelBtoC.Counterparty.ChannelID), - transfertypes.NewHop(channelAtoB.Counterparty.PortID, channelAtoB.Counterparty.ChannelID), - ) - - s.AssertPacketRelayed(ctx, chainA, channelAtoB.PortID, channelAtoB.ChannelID, 1) - s.AssertPacketRelayed(ctx, chainB, channelBtoC.PortID, channelBtoC.ChannelID, 1) - - actualBalance, err := query.Balance(ctx, chainC, chainCAddress, chainCDenom.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - - // packet from B to C is acknowledged on chain C - s.AssertPacketAcknowledged(ctx, chainC, channelBtoC.Counterparty.PortID, channelBtoC.Counterparty.ChannelID, 1) - // packet from A to B is acknowledged on chain B - s.AssertPacketAcknowledged(ctx, chainB, channelAtoB.Counterparty.PortID, channelAtoB.Counterparty.ChannelID, 1) - }) -} - -// TestForwardingWithUnwindSucceeds tests the forwarding scenario in which -// a packet is sent from A to B, then unwound back to A and forwarded to C -// The overall flow of the packet is: -// A ---> B -// B --(unwind)-->A --(forward)-->B --(forward)--> C -func (s *TransferForwardingTestSuite) TestForwardingWithUnwindSucceeds() { - t := s.T() - ctx := context.TODO() - t.Parallel() - testName := t.Name() - relayer := s.CreateDefaultPaths(testName) - - chains := s.GetAllChains() - - chainA, chainB, chainC := chains[0], chains[1], chains[2] - - channelAtoB := s.GetChainAChannelForTest(testName) - channelBtoC := s.GetChannelsForTest(chainB, testName)[1] - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - chainADenom := chainA.Config().Denom - - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - chainCWallet := s.CreateUserOnChainC(ctx, testvalues.StartingTokenAmount) - chainCAddress := chainCWallet.FormattedAddress() - - t.Run("IBC transfer from A to B", func(t *testing.T) { - inFiveMinutes := time.Now().Add(5 * time.Minute).UnixNano() - resp := s.Transfer(ctx, chainA, chainAWallet, channelAtoB.PortID, channelAtoB.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, clienttypes.ZeroHeight(), uint64(inFiveMinutes), "", nil) - s.AssertTxSuccess(resp) - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - chainBDenom := transfertypes.NewDenom(chainADenom, transfertypes.NewHop(channelAtoB.Counterparty.PortID, channelAtoB.Counterparty.ChannelID)) - t.Run("packet has reached B", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelAtoB.PortID, channelAtoB.ChannelID, 1) - s.AssertPacketAcknowledged(ctx, chainB, channelAtoB.Counterparty.PortID, channelAtoB.Counterparty.ChannelID, 1) - - balance, err := query.Balance(ctx, chainB, chainBAddress, chainBDenom.IBCDenom()) - s.Require().NoError(err) - - s.Require().Equal(testvalues.IBCTransferAmount, balance.Int64()) - }) - - t.Run("IBC transfer from B (unwind) to A and forwarded to C through B", func(t *testing.T) { - inFiveMinutes := time.Now().Add(5 * time.Minute).UnixNano() - - forwarding := transfertypes.NewForwarding( - true, - transfertypes.NewHop(channelAtoB.PortID, channelAtoB.ChannelID), - transfertypes.NewHop(channelBtoC.PortID, channelBtoC.ChannelID), - ) - msgTransfer := testsuite.GetMsgTransfer( - "", - "", - transfertypes.V2, - testvalues.DefaultTransferCoins(chainBDenom.IBCDenom()), - chainBAddress, - chainCAddress, - clienttypes.ZeroHeight(), - uint64(inFiveMinutes), - "", - forwarding) - resp := s.BroadcastMessages(ctx, chainB, chainBWallet, msgTransfer) - s.AssertTxSuccess(resp) - }) - - t.Run("packet has reached C", func(t *testing.T) { - chainCDenom := transfertypes.NewDenom(chainADenom, - transfertypes.NewHop(channelAtoB.Counterparty.PortID, channelAtoB.Counterparty.ChannelID), - transfertypes.NewHop(channelBtoC.Counterparty.PortID, channelBtoC.Counterparty.ChannelID), - ) - - err := test.WaitForCondition(time.Minute*10, time.Second*30, func() (bool, error) { - balance, err := query.Balance(ctx, chainC, chainCAddress, chainCDenom.IBCDenom()) - if err != nil { - return false, err - } - return balance.Int64() == testvalues.IBCTransferAmount, nil - }) - s.Require().NoError(err) - // packet from B to C is relayed - s.AssertPacketRelayed(ctx, chainB, channelBtoC.PortID, channelBtoC.ChannelID, 1) - // packet from B to C is acknowledged on chain C - s.AssertPacketAcknowledged(ctx, chainC, channelBtoC.Counterparty.PortID, channelBtoC.Counterparty.ChannelID, 1) - // packet from A to B is acknowledged on chain B - s.AssertPacketAcknowledged(ctx, chainB, channelAtoB.Counterparty.PortID, channelAtoB.Counterparty.ChannelID, 2) - }) -} - -func (s *TransferForwardingTestSuite) TestChannelUpgradeForwarding_Succeeds() { - ctx := context.TODO() - t := s.T() - testName := t.Name() - t.Parallel() - - relayer := s.CreateDefaultPaths(testName) - chains := s.GetAllChains() - - chainA, chainB, chainC := chains[0], chains[1], chains[2] - - opts := s.TransferChannelOptions() - opts.Version = transfertypes.V1 - - channelAtoB, _ := s.CreatePath(ctx, relayer, chains[0], chains[1], ibc.DefaultClientOpts(), opts, testName) - s.Require().Equal(transfertypes.V1, channelAtoB.Version, "the channel version is not ics20-1") - - channelBtoC, _ := s.CreatePath(ctx, relayer, chains[1], chains[2], ibc.DefaultClientOpts(), opts, testName) - s.Require().Equal(transfertypes.V1, channelBtoC.Version, "the channel version is not ics20-1") - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - chainADenom := chainA.Config().Denom - - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - - chainCWallet := s.CreateUserOnChainC(ctx, testvalues.StartingTokenAmount) - chainCAddress := chainCWallet.FormattedAddress() - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - t.Run("execute gov proposal to initiate channel upgrade", func(t *testing.T) { - chA, err := query.Channel(ctx, chainA, channelAtoB.PortID, channelAtoB.ChannelID) - s.Require().NoError(err) - - upgradeFields := channeltypes.NewUpgradeFields(chA.Ordering, chA.ConnectionHops, transfertypes.V2) - s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelAtoB.PortID, channelAtoB.ChannelID, upgradeFields) - - chB, err := query.Channel(ctx, chainB, channelBtoC.PortID, channelBtoC.ChannelID) - s.Require().NoError(err) - - upgradeFields = channeltypes.NewUpgradeFields(chB.Ordering, chB.ConnectionHops, transfertypes.V2) - s.InitiateChannelUpgrade(ctx, chainB, chainBWallet, channelBtoC.PortID, channelBtoC.ChannelID, upgradeFields) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB), "failed to wait for blocks") - - t.Run("verify channel A upgraded and transfer version is ics20-2", func(t *testing.T) { - channel, err := query.Channel(ctx, chainA, channelAtoB.PortID, channelAtoB.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") - }) - - t.Run("verify channel B upgraded and transfer version is ics20-2", func(t *testing.T) { - channel, err := query.Channel(ctx, chainB, channelBtoC.PortID, channelBtoC.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") - }) - - t.Run("IBC transfer from A to C with forwarding through B", func(t *testing.T) { - inFiveMinutes := time.Now().Add(5 * time.Minute).UnixNano() - forwarding := transfertypes.NewForwarding(false, transfertypes.NewHop(channelBtoC.PortID, channelBtoC.ChannelID)) - resp := s.Transfer(ctx, chainA, chainAWallet, channelAtoB.PortID, channelAtoB.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainCAddress, clienttypes.ZeroHeight(), uint64(inFiveMinutes), "", forwarding) - s.AssertTxSuccess(resp) - }) - - t.Run("packets are relayed from A to B to C", func(t *testing.T) { - chainCDenom := transfertypes.NewDenom(chainADenom, - transfertypes.NewHop(channelBtoC.Counterparty.PortID, channelBtoC.Counterparty.ChannelID), - transfertypes.NewHop(channelAtoB.Counterparty.PortID, channelAtoB.Counterparty.ChannelID), - ) - - actualBalance, err := query.Balance(ctx, chainC, chainCAddress, chainCDenom.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) -} - -// TestFailedForwarding tests the scenario in which the packet is sent from -// A to C (through B) but it can't reach C (we use an invalid address). -func (s *TransferForwardingTestSuite) TestFailedForwarding() { - t := s.T() - ctx := context.TODO() - - testName := t.Name() - t.Parallel() - relayer := s.CreateDefaultPaths(testName) - chains := s.GetAllChains() - - chainA, chainB, chainC := chains[0], chains[1], chains[2] - - chainADenom := chainA.Config().Denom - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - - chainCWallet := s.CreateUserOnChainC(ctx, testvalues.StartingTokenAmount) - - channelAtoB := s.GetChainAChannelForTest(testName) - channelBtoC := s.GetChannelsForTest(chainB, testName)[1] - - s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") - - t.Run("native IBC token transfer from chainA to invalid address through B", func(t *testing.T) { - inFiveMinutes := time.Now().Add(5 * time.Minute).UnixNano() - forwarding := transfertypes.NewForwarding(false, transfertypes.NewHop(channelBtoC.PortID, channelBtoC.ChannelID)) - resp := s.Transfer(ctx, chainA, chainAWallet, channelAtoB.PortID, channelAtoB.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, testvalues.InvalidAddress, clienttypes.ZeroHeight(), uint64(inFiveMinutes), "", forwarding) - s.AssertTxSuccess(resp) - }) - - t.Run("tokens are escrowed", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelAtoB.PortID, channelAtoB.ChannelID, 1) - }) - - t.Run("token transfer amount unescrowed", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("balances for B and C have not changed", func(t *testing.T) { - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelAtoB.Counterparty.PortID, channelAtoB.Counterparty.ChannelID) // IBC token sent to chainB - chainBBalance, err := testsuite.GetChainBalanceForDenom(ctx, chainB, chainBIBCToken.IBCDenom(), chainBWallet) - s.Require().NoError(err) - s.Require().Zero(chainBBalance) - - chainCIBCToken := testsuite.GetIBCToken(chainBIBCToken.IBCDenom(), channelBtoC.Counterparty.PortID, channelBtoC.Counterparty.ChannelID) // IBC token sent to chainC - chainCBalance, err := testsuite.GetChainBalanceForDenom(ctx, chainC, chainCIBCToken.IBCDenom(), chainCWallet) - s.Require().NoError(err) - s.Require().Zero(chainCBalance) - }) -} diff --git a/e2e/tests/transfer/incentivized_test.go b/e2e/tests/transfer/incentivized_test.go index 1982b416512..ca940793023 100644 --- a/e2e/tests/transfer/incentivized_test.go +++ b/e2e/tests/transfer/incentivized_test.go @@ -200,7 +200,7 @@ func (s *IncentivizedTransferTestSuite) TestMsgPayPacketFee_InvalidReceiverAccou transferAmount := testvalues.DefaultTransferAmount(chainADenom) t.Run("send IBC transfer", func(t *testing.T) { - resp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, sdk.NewCoins(transferAmount), chainAWallet.FormattedAddress(), testvalues.InvalidAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + resp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, transferAmount, chainAWallet.FormattedAddress(), testvalues.InvalidAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") // this message should be successful, as receiver account is not validated on the sending chain. s.AssertTxSuccess(resp) }) @@ -329,13 +329,12 @@ func (s *IncentivizedTransferTestSuite) TestMultiMsg_MsgPayPacketFeeSingleSender channelA.PortID, channelA.ChannelID, version.AppVersion, - sdk.NewCoins(transferAmount), + transferAmount, chainAWallet.FormattedAddress(), chainBWallet.FormattedAddress(), s.GetTimeoutHeight(ctx, chainB), 0, "", - nil, ) resp := s.BroadcastMessages(ctx, chainA, chainAWallet, msgPayPacketFee, msgTransfer) s.AssertTxSuccess(resp) diff --git a/e2e/tests/transfer/localhost_test.go b/e2e/tests/transfer/localhost_test.go index 03ff062cc5a..a7ec0dd6afb 100644 --- a/e2e/tests/transfer/localhost_test.go +++ b/e2e/tests/transfer/localhost_test.go @@ -6,7 +6,6 @@ import ( "context" "testing" - "github.com/strangelove-ventures/interchaintest/v8/ibc" test "github.com/strangelove-ventures/interchaintest/v8/testutil" testifysuite "github.com/stretchr/testify/suite" @@ -39,7 +38,7 @@ func (s *LocalhostTransferTestSuite) TestMsgTransfer_Localhost() { chainA, _ := s.GetChains() - channelVersion := testsuite.DetermineDefaultTransferVersion([]ibc.Chain{chainA}) + channelVersion := transfertypes.V1 chainADenom := chainA.Config().Denom @@ -120,7 +119,7 @@ func (s *LocalhostTransferTestSuite) TestMsgTransfer_Localhost() { t.Run("send packet localhost ibc transfer", func(t *testing.T) { var err error - txResp := s.Transfer(ctx, chainA, userAWallet, transfertypes.PortID, msgChanOpenInitRes.ChannelId, testvalues.DefaultTransferCoins(chainADenom), userAWallet.FormattedAddress(), userBWallet.FormattedAddress(), clienttypes.NewHeight(1, 500), 0, "", nil) + txResp := s.Transfer(ctx, chainA, userAWallet, transfertypes.PortID, msgChanOpenInitRes.ChannelId, testvalues.DefaultTransferAmount(chainADenom), userAWallet.FormattedAddress(), userBWallet.FormattedAddress(), clienttypes.NewHeight(1, 500), 0, "") s.AssertTxSuccess(txResp) packet, err = ibctesting.ParsePacketFromEvents(txResp.Events) diff --git a/e2e/tests/transfer/send_enabled_test.go b/e2e/tests/transfer/send_enabled_test.go index 0f01e9c5aed..4dc2b3c8ba2 100644 --- a/e2e/tests/transfer/send_enabled_test.go +++ b/e2e/tests/transfer/send_enabled_test.go @@ -69,7 +69,7 @@ func (s *TransferTestSuiteSendEnabled) TestSendEnabledParam() { }) t.Run("ensure packets can be sent", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -93,7 +93,7 @@ func (s *TransferTestSuiteSendEnabled) TestSendEnabledParam() { }) t.Run("ensure ics20 transfer fails", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxFailure(transferTxResp, transfertypes.ErrSendDisabled) }) } diff --git a/e2e/tests/transfer/send_receive_test.go b/e2e/tests/transfer/send_receive_test.go index 18418bd0b9f..782fcdc7858 100644 --- a/e2e/tests/transfer/send_receive_test.go +++ b/e2e/tests/transfer/send_receive_test.go @@ -76,7 +76,7 @@ func (s *TransferTestSuiteSendReceive) TestReceiveEnabledParam() { t.Run("ensure packets can be received, send from chainB to chainA", func(t *testing.T) { t.Run("send from chainB to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferCoins(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferAmount(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -128,7 +128,7 @@ func (s *TransferTestSuiteSendReceive) TestReceiveEnabledParam() { t.Run("ensure ics20 transfer fails", func(t *testing.T) { t.Run("send from chainB to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferCoins(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferAmount(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "") s.AssertTxSuccess(transferTxResp) }) diff --git a/e2e/tests/transfer/upgradesv1_test.go b/e2e/tests/transfer/upgradesv1_test.go deleted file mode 100644 index f3c7472dafb..00000000000 --- a/e2e/tests/transfer/upgradesv1_test.go +++ /dev/null @@ -1,364 +0,0 @@ -//go:build !test_e2e - -package transfer - -import ( - "context" - "testing" - - "github.com/strangelove-ventures/interchaintest/v8/ibc" - test "github.com/strangelove-ventures/interchaintest/v8/testutil" - testifysuite "github.com/stretchr/testify/suite" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/ibc-go/e2e/testsuite" - "github.com/cosmos/ibc-go/e2e/testsuite/query" - "github.com/cosmos/ibc-go/e2e/testvalues" - feetypes "github.com/cosmos/ibc-go/v9/modules/apps/29-fee/types" - transfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" -) - -// compatibility:from_version: v9.0.0 -func TestTransferChannelUpgradesV1TestSuite(t *testing.T) { - testifysuite.Run(t, new(TransferChannelUpgradesV1TestSuite)) -} - -type TransferChannelUpgradesV1TestSuite struct { - testsuite.E2ETestSuite -} - -func (s *TransferChannelUpgradesV1TestSuite) SetupChannelUpgradesV1Test(testName string) { - opts := s.TransferChannelOptions() - opts.Version = transfertypes.V1 - s.CreatePaths(ibc.DefaultClientOpts(), opts, testName) -} - -// TestChannelUpgrade_WithICS20v2_Succeeds tests upgrading a transfer channel to ICS20 v2. -func (s *TransferChannelUpgradesV1TestSuite) TestChannelUpgrade_WithICS20v2_Succeeds() { - t := s.T() - ctx := context.TODO() - - testName := t.Name() - s.SetupChannelUpgradesV1Test(testName) - - relayer, channelA := s.GetRelayerForTest(testName), s.GetChainAChannelForTest(testName) - - channelB := channelA.Counterparty - chainA, chainB := s.GetChains() - - chainADenom := chainA.Config().Denom - chainBDenom := chainB.Config().Denom - chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID) - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelB.PortID, channelB.ChannelID) - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") - - t.Run("verify transfer version of channel A is ics20-1", func(t *testing.T) { - channel, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") - }) - - t.Run("native token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - chainBWalletAmount := ibc.WalletAmount{ - Address: chainBWallet.FormattedAddress(), // destination address - Denom: chainA.Config().Denom, - Amount: sdkmath.NewInt(testvalues.IBCTransferAmount), - } - - transferTxResp, err := chainA.SendIBCTransfer(ctx, channelA.ChannelID, chainAWallet.KeyName(), chainBWalletAmount, ibc.TransferOptions{}) - s.Require().NoError(err) - s.Require().NoError(transferTxResp.Validate(), "chain-a ibc transfer tx is invalid") - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("tokens are escrowed", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance) - - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) - s.Require().NoError(err) - - expectedTotalEscrow := sdk.NewCoin(chainADenom, sdkmath.NewInt(testvalues.IBCTransferAmount)) - s.Require().Equal(expectedTotalEscrow, actualTotalEscrow) - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) - - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - - t.Run("execute gov proposal to initiate channel upgrade", func(t *testing.T) { - chA, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - - upgradeFields := channeltypes.NewUpgradeFields(chA.Ordering, chA.ConnectionHops, transfertypes.V2) - s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, upgradeFields) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB), "failed to wait for blocks") - - t.Run("verify channel A upgraded and transfer version is ics20-2", func(t *testing.T) { - channel, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") - }) - - t.Run("verify channel B upgraded and transfer version is ics20-2", func(t *testing.T) { - channel, err := query.Channel(ctx, chainB, channelB.PortID, channelB.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") - }) - - // send the native chainB denom and also the ibc token from chainA - transferCoins := []sdk.Coin{ - testvalues.DefaultTransferAmount(chainBIBCToken.IBCDenom()), - testvalues.DefaultTransferAmount(chainBDenom), - } - - t.Run("native token from chain B and non-native IBC token from chainA, both to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, transferCoins, chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) - s.AssertTxSuccess(transferTxResp) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainB, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1) - - t.Run("chain A native denom", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("chain B IBC denom", func(t *testing.T) { - actualBalance, err := query.Balance(ctx, chainA, chainAAddress, chainAIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - }) - - t.Run("tokens are un-escrowed", func(t *testing.T) { - t.Run("chain A escrow", func(t *testing.T) { - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) - s.Require().NoError(err) - s.Require().Equal(sdk.NewCoin(chainADenom, sdkmath.NewInt(0)), actualTotalEscrow) // total escrow is zero because tokens have come back - }) - - t.Run("chain B escrow", func(t *testing.T) { - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainB, chainBDenom) - s.Require().NoError(err) - s.Require().Equal(sdk.NewCoin(chainBDenom, sdkmath.NewInt(testvalues.IBCTransferAmount)), actualTotalEscrow) - }) - }) -} - -// TestChannelUpgrade_WithFeeMiddlewareAndICS20v2_Succeeds tests upgrading a transfer channel to wire up fee middleware and upgrade to ICS20 v2. -func (s *TransferChannelUpgradesV1TestSuite) TestChannelUpgrade_WithFeeMiddlewareAndICS20v2_Succeeds() { - t := s.T() - ctx := context.TODO() - - testName := t.Name() - s.SetupChannelUpgradesV1Test(testName) - - relayer, channelA := s.GetRelayerForTest(testName), s.GetChainAChannelForTest(testName) - - channelB := channelA.Counterparty - chainA, chainB := s.GetChains() - - chainADenom := chainA.Config().Denom - chainBDenom := chainB.Config().Denom - chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID) - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelB.PortID, channelB.ChannelID) - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") - - var ( - err error - channel channeltypes.Channel - ) - - t.Run("verify transfer version of channel A is ics20-1", func(t *testing.T) { - channel, err = query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") - }) - - t.Run("native token transfer from chainB to chainA, sender is source of tokens", func(t *testing.T) { - chainAwalletAmount := ibc.WalletAmount{ - Address: chainAWallet.FormattedAddress(), // destination address - Denom: chainBDenom, - Amount: sdkmath.NewInt(testvalues.IBCTransferAmount), - } - - transferTxResp, err := chainB.SendIBCTransfer(ctx, channelB.ChannelID, chainBWallet.KeyName(), chainAwalletAmount, ibc.TransferOptions{}) - s.Require().NoError(err) - s.Require().NoError(transferTxResp.Validate(), "chain-b ibc transfer tx is invalid") - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("execute gov proposal to initiate channel upgrade", func(t *testing.T) { - channel.Version = transfertypes.V2 // change version to ics20-2 - s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, s.CreateUpgradeFields(channel)) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB), "failed to wait for blocks") - - t.Run("verify channel A upgraded and channel version is {ics29-1,ics20-2}", func(t *testing.T) { - channel, err = query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - - // check the channel version include the fee version - version, err := feetypes.MetadataFromVersion(channel.Version) - s.Require().NoError(err) - s.Require().Equal(feetypes.Version, version.FeeVersion, "the channel version did not include ics29") - s.Require().Equal(transfertypes.V2, version.AppVersion, "the channel version is not ics20-2") - }) - - t.Run("verify channel B upgraded and channel version is {ics29-1,ics20-2}", func(t *testing.T) { - channel, err = query.Channel(ctx, chainB, channelB.PortID, channelB.ChannelID) - s.Require().NoError(err) - - // check the channel version include the fee version - version, err := feetypes.MetadataFromVersion(channel.Version) - s.Require().NoError(err) - s.Require().Equal(feetypes.Version, version.FeeVersion, "the channel version did not include ics29") - s.Require().Equal(transfertypes.V2, version.AppVersion, "the channel version is not ics20-2") - }) - - var ( - chainARelayerWallet, chainBRelayerWallet ibc.Wallet - relayerAStartingBalance int64 - testFee = testvalues.DefaultFee(chainADenom) - ) - - t.Run("recover relayer wallets", func(t *testing.T) { - _, _, err := s.RecoverRelayerWallets(ctx, relayer, testName) - s.Require().NoError(err) - - chainARelayerWallet, chainBRelayerWallet, err = s.GetRelayerWallets(relayer) - s.Require().NoError(err) - - relayerAStartingBalance, err = s.GetChainANativeBalance(ctx, chainARelayerWallet) - s.Require().NoError(err) - t.Logf("relayer A user starting with balance: %d", relayerAStartingBalance) - }) - - t.Run("register and verify counterparty payee", func(t *testing.T) { - _, chainBRelayerUser := s.GetRelayerUsers(ctx, testName) - resp := s.RegisterCounterPartyPayee(ctx, chainB, chainBRelayerUser, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, chainBRelayerWallet.FormattedAddress(), chainARelayerWallet.FormattedAddress()) - s.AssertTxSuccess(resp) - - address, err := query.CounterPartyPayee(ctx, chainB, chainBRelayerWallet.FormattedAddress(), channelA.Counterparty.ChannelID) - s.Require().NoError(err) - s.Require().Equal(chainARelayerWallet.FormattedAddress(), address) - }) - - // send the native chainA denom and also the ibc token from chainB - denoms := []string{chainAIBCToken.IBCDenom(), chainADenom} - var transferCoins []sdk.Coin - for _, denom := range denoms { - transferCoins = append(transferCoins, testvalues.DefaultTransferAmount(denom)) - } - - t.Run("send incentivized transfer packet to chain B with native token from chain A and non-native IBC token from chainB", func(t *testing.T) { - // before adding fees for the packet, there should not be incentivized packets - packets, err := query.IncentivizedPacketsForChannel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Empty(packets) - - msgPayPacketFee := feetypes.NewMsgPayPacketFee(testFee, channelA.PortID, channelA.ChannelID, chainAWallet.FormattedAddress(), nil) - msgTransfer := testsuite.GetMsgTransfer( - channelA.PortID, - channelA.ChannelID, - transfertypes.V2, - transferCoins, - chainAWallet.FormattedAddress(), - chainBWallet.FormattedAddress(), - s.GetTimeoutHeight(ctx, chainB), - 0, - "", - nil, - ) - resp := s.BroadcastMessages(ctx, chainA, chainAWallet, msgPayPacketFee, msgTransfer) - s.AssertTxSuccess(resp) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) - - t.Run("chain B native denom", func(t *testing.T) { - actualBalance, err := s.GetChainBNativeBalance(ctx, chainBWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - s.Require().Equal(expected, actualBalance) - }) - - t.Run("chain A IBC denom", func(t *testing.T) { - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - }) - - t.Run("timeout fee is refunded", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - // once the relayer has relayed the packets, the timeout fee should be refunded. - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - testFee.AckFee.AmountOf(chainADenom).Int64() - testFee.RecvFee.AmountOf(chainADenom).Int64() - s.Require().Equal(expected, actualBalance) - }) - - t.Run("relayerA is paid ack and recv fee", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainARelayerWallet) - s.Require().NoError(err) - - expected := relayerAStartingBalance + testFee.AckFee.AmountOf(chainADenom).Int64() + testFee.RecvFee.AmountOf(chainADenom).Int64() - s.Require().Equal(expected, actualBalance) - }) - - t.Run("tokens are un-escrowed", func(t *testing.T) { - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainB, chainADenom) - s.Require().NoError(err) - s.Require().Equal(sdk.NewCoin(chainADenom, sdkmath.NewInt(0)), actualTotalEscrow) // total escrow is zero because tokens have come back - }) -} diff --git a/e2e/tests/transfer/upgradesv2_test.go b/e2e/tests/transfer/upgradesv2_test.go index 3e52655bff1..53ff2f5d0e9 100644 --- a/e2e/tests/transfer/upgradesv2_test.go +++ b/e2e/tests/transfer/upgradesv2_test.go @@ -13,13 +13,10 @@ import ( sdkmath "cosmossdk.io/math" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/ibc-go/e2e/testsuite" "github.com/cosmos/ibc-go/e2e/testsuite/query" "github.com/cosmos/ibc-go/e2e/testvalues" feetypes "github.com/cosmos/ibc-go/v9/modules/apps/29-fee/types" - transfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" ) @@ -211,13 +208,12 @@ func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithFeeMiddleware_ channelA.PortID, channelA.ChannelID, channelA.Version, // upgrade adds fee middleware, but keeps transfer version - sdk.NewCoins(transferAmount), + transferAmount, chainAWallet.FormattedAddress(), chainBWallet.FormattedAddress(), s.GetTimeoutHeight(ctx, chainB), 0, "", - nil, ) resp := s.BroadcastMessages(ctx, chainA, chainAWallet, msgPayPacketFee, msgTransfer) s.AssertTxSuccess(resp) @@ -282,7 +278,7 @@ func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithFeeMiddleware_ // trying to create some inflight packets, although they might get relayed before the upgrade starts t.Run("create inflight transfer packets between chain A and chain B", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -412,99 +408,3 @@ func (s *TransferChannelUpgradesTestSuite) TestChannelUpgrade_WithFeeMiddleware_ s.Require().Contains(errorReceipt.Message, "restored channel to pre-upgrade state") }) } - -// TestChannelDowngrade_WithICS20v1_Succeeds tests downgrading a transfer channel from ICS20 v2 to ICS20 v1. -// compatibility:TestChannelDowngrade_WithICS20v1_Succeeds:from_versions: v9.0.0 -func (s *TransferChannelUpgradesTestSuite) TestChannelDowngrade_WithICS20v1_Succeeds() { - t := s.T() - ctx := context.TODO() - - testName := t.Name() - s.SetupChannelUpgradesPath(testName) - - relayer, channelA := s.GetRelayerForTest(testName), s.GetChainAChannelForTest(testName) - - channelB := channelA.Counterparty - chainA, chainB := s.GetChains() - - chainADenom := chainA.Config().Denom - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelB.PortID, channelB.ChannelID) - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") - - var ( - err error - channel channeltypes.Channel - ) - - t.Run("verify transfer version of channel A is ics20-2", func(t *testing.T) { - channel, err = query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V2, channel.Version, "the channel version is not ics20-2") - }) - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("execute gov proposal to initiate channel upgrade", func(t *testing.T) { - upgradeFields := channeltypes.NewUpgradeFields(channel.Ordering, channel.ConnectionHops, transfertypes.V1) - s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, upgradeFields) - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 10, chainA, chainB), "failed to wait for blocks") - - t.Run("verify channel A downgraded and transfer version is ics20-1", func(t *testing.T) { - channel, err = query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") - }) - - t.Run("verify channel B downgraded and transfer version is ics20-1", func(t *testing.T) { - channel, err = query.Channel(ctx, chainB, channelB.PortID, channelB.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") - }) - - t.Run("native IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - chainBWalletAmount := ibc.WalletAmount{ - Address: chainBWallet.FormattedAddress(), // destination address - Denom: chainA.Config().Denom, - Amount: sdkmath.NewInt(testvalues.IBCTransferAmount), - } - - transferTxResp, err := chainA.SendIBCTransfer(ctx, channelA.ChannelID, chainAWallet.KeyName(), chainBWalletAmount, ibc.TransferOptions{}) - s.Require().NoError(err) - s.Require().NoError(transferTxResp.Validate(), "chain-a ibc transfer tx is invalid") - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA, chainB), "failed to wait for blocks") - - t.Run("tokens are escrowed", func(t *testing.T) { - actualBalance, err := s.GetChainANativeBalance(ctx, chainAWallet) - s.Require().NoError(err) - - expected := testvalues.StartingTokenAmount - testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance) - - actualTotalEscrow, err := query.TotalEscrowForDenom(ctx, chainA, chainADenom) - s.Require().NoError(err) - - expectedTotalEscrow := sdk.NewCoin(chainADenom, sdkmath.NewInt(testvalues.IBCTransferAmount)) - s.Require().Equal(expectedTotalEscrow, actualTotalEscrow) - }) - - t.Run("packets are relayed", func(t *testing.T) { - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) - - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) -} diff --git a/e2e/tests/upgrades/genesis_test.go b/e2e/tests/upgrades/genesis_test.go index 84f64a28cfc..acb2ad33ed6 100644 --- a/e2e/tests/upgrades/genesis_test.go +++ b/e2e/tests/upgrades/genesis_test.go @@ -81,7 +81,7 @@ func (s *GenesisTestSuite) TestIBCGenesis() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("ics20: native IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -149,7 +149,7 @@ func (s *GenesisTestSuite) TestIBCGenesis() { }) t.Run("ics20: native IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) diff --git a/e2e/tests/upgrades/upgrade_test.go b/e2e/tests/upgrades/upgrade_test.go index da73a1e5897..07b0dd2ae96 100644 --- a/e2e/tests/upgrades/upgrade_test.go +++ b/e2e/tests/upgrades/upgrade_test.go @@ -155,7 +155,7 @@ func (s *UpgradeTestSuite) TestIBCChainUpgrade() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("native IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -194,7 +194,7 @@ func (s *UpgradeTestSuite) TestIBCChainUpgrade() { }) t.Run("native IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -212,7 +212,7 @@ func (s *UpgradeTestSuite) TestIBCChainUpgrade() { t.Run("ensure packets can be received, send from chainB to chainA", func(t *testing.T) { t.Run("send from chainB to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferCoins(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferAmount(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -377,7 +377,7 @@ func (s *UpgradeTestSuite) TestV6ToV7ChainUpgrade() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("IBC token transfer from chainA to chainB, sender is source of tokens", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -430,7 +430,7 @@ func (s *UpgradeTestSuite) TestV6ToV7ChainUpgrade() { }) t.Run("IBC token transfer from chainA to chainB, to make sure the upgrade did not break the packet flow", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB.(*cosmos.CosmosChain)), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB.(*cosmos.CosmosChain)), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -473,7 +473,7 @@ func (s *UpgradeTestSuite) TestV7ToV7_1ChainUpgrade() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("transfer native tokens from chainA to chainB", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB.(*cosmos.CosmosChain)), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB.(*cosmos.CosmosChain)), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -530,7 +530,7 @@ func (s *UpgradeTestSuite) TestV7ToV7_1ChainUpgrade() { }) t.Run("IBC token transfer from chainA to chainB, to make sure the upgrade did not break the packet flow", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -567,7 +567,7 @@ func (s *UpgradeTestSuite) TestV7ToV8ChainUpgrade() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("transfer native tokens from chainA to chainB", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -627,7 +627,7 @@ func (s *UpgradeTestSuite) TestV7ToV8ChainUpgrade() { }) t.Run("IBC token transfer from chainA to chainB, to make sure the upgrade did not break the packet flow", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -663,7 +663,7 @@ func (s *UpgradeTestSuite) TestV8ToV8_1ChainUpgrade() { s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") t.Run("transfer native tokens from chainA to chainB", func(t *testing.T) { - txResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + txResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(txResp) }) @@ -756,7 +756,7 @@ func (s *UpgradeTestSuite) TestV8ToV8_1ChainUpgrade() { s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA), "failed to wait for blocks") t.Run("IBC token transfer from chainA to chainB, to make sure the upgrade did not break the packet flow", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) }) @@ -992,13 +992,12 @@ func (s *UpgradeTestSuite) TestV8ToV8_1ChainUpgrade_FeeMiddlewareChannelUpgrade( channelA.PortID, channelA.ChannelID, channelA.Version, // upgrade adds fee middleware, but keeps transfer version - sdk.NewCoins(transferAmount), + transferAmount, chainAWallet.FormattedAddress(), chainBWallet.FormattedAddress(), s.GetTimeoutHeight(ctx, chainB), 0, "", - nil, ) resp := s.BroadcastMessages(ctx, chainA, chainAWallet, msgPayPacketFee, msgTransfer) s.AssertTxSuccess(resp) @@ -1066,7 +1065,7 @@ func (s *UpgradeTestSuite) TestV8ToV9ChainUpgrade() { }) t.Run("transfer native tokens from chainA to chainB", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) @@ -1079,7 +1078,7 @@ func (s *UpgradeTestSuite) TestV8ToV9ChainUpgrade() { }) t.Run("transfer native tokens from chainB to chainA", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferCoins(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA.(*cosmos.CosmosChain)), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, testvalues.DefaultTransferAmount(chainBDenom), chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA.(*cosmos.CosmosChain)), 0, "") s.AssertTxSuccess(transferTxResp) s.AssertPacketRelayed(ctx, chainA, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 1) @@ -1114,7 +1113,7 @@ func (s *UpgradeTestSuite) TestV8ToV9ChainUpgrade() { }) t.Run("IBC token transfer from chainA to chainB, to make sure the upgrade did not break the packet flow", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) + transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferAmount(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "") s.AssertTxSuccess(transferTxResp) s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 2) @@ -1190,7 +1189,7 @@ func (s *UpgradeTestSuite) TestV8ToV9ChainUpgrade_Localhost() { }) t.Run("ibc transfer over localhost", func(t *testing.T) { - txResp := s.Transfer(ctx, chainA, userAWallet, transfertypes.PortID, srcChannelID, testvalues.DefaultTransferCoins(chainADenom), userAWallet.FormattedAddress(), userBWallet.FormattedAddress(), s.GetTimeoutHeight(ctx, chainA), 0, "", nil) + txResp := s.Transfer(ctx, chainA, userAWallet, transfertypes.PortID, srcChannelID, testvalues.DefaultTransferAmount(chainADenom), userAWallet.FormattedAddress(), userBWallet.FormattedAddress(), s.GetTimeoutHeight(ctx, chainA), 0, "") s.AssertTxSuccess(txResp) packet, err := ibctesting.ParsePacketFromEvents(txResp.Events) @@ -1256,8 +1255,8 @@ func (s *UpgradeTestSuite) TestV8ToV9ChainUpgrade_Localhost() { t.Run("ibc transfer back over localhost after upgrade", func(t *testing.T) { ibcToken := testsuite.GetIBCToken(chainADenom, transfertypes.PortID, dstChannelID) - transferCoins := testvalues.DefaultTransferCoins(ibcToken.IBCDenom()) - txResp := s.Transfer(ctx, chainA, userBWallet, transfertypes.PortID, dstChannelID, transferCoins, userBWallet.FormattedAddress(), userAWallet.FormattedAddress(), s.GetTimeoutHeight(ctx, chainA), 0, "", nil) + transferCoins := testvalues.DefaultTransferAmount(ibcToken.IBCDenom()) + txResp := s.Transfer(ctx, chainA, userBWallet, transfertypes.PortID, dstChannelID, transferCoins, userBWallet.FormattedAddress(), userAWallet.FormattedAddress(), s.GetTimeoutHeight(ctx, chainA), 0, "") s.AssertTxSuccess(txResp) packet, err := ibctesting.ParsePacketFromEvents(txResp.Events) @@ -1285,103 +1284,6 @@ func (s *UpgradeTestSuite) TestV8ToV9ChainUpgrade_Localhost() { }) } -func (s *UpgradeTestSuite) TestV8ToV9ChainUpgrade_ICS20v2ChannelUpgrade() { - t := s.T() - testCfg := testsuite.LoadConfig() - ctx := context.Background() - - testName := t.Name() - - relayer, channelA := s.CreateUpgradeTestPath(testName) - - chainA, chainB := s.GetChains() - chainADenom := chainA.Config().Denom - chainBDenom := chainB.Config().Denom - - chainAWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - chainAAddress := chainAWallet.FormattedAddress() - - chainBWallet := s.CreateUserOnChainB(ctx, testvalues.StartingTokenAmount) - chainBAddress := chainBWallet.FormattedAddress() - - chainBIBCToken := testsuite.GetIBCToken(chainADenom, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID) - - s.Require().NoError(test.WaitForBlocks(ctx, 1, chainA, chainB), "failed to wait for blocks") - - t.Run("start relayer", func(t *testing.T) { - s.StartRelayer(relayer, testName) - }) - - t.Run("transfer native tokens from chainA to chainB", func(t *testing.T) { - transferTxResp := s.Transfer(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, testvalues.DefaultTransferCoins(chainADenom), chainAAddress, chainBAddress, s.GetTimeoutHeight(ctx, chainB), 0, "", nil) - s.AssertTxSuccess(transferTxResp) - - s.AssertPacketRelayed(ctx, chainA, channelA.PortID, channelA.ChannelID, 1) - - actualBalance, err := query.Balance(ctx, chainB, chainBAddress, chainBIBCToken.IBCDenom()) - s.Require().NoError(err) - - expected := testvalues.IBCTransferAmount - s.Require().Equal(expected, actualBalance.Int64()) - }) - - t.Run("verify channel version before upgrade", func(t *testing.T) { - channel, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - s.Require().Equal(transfertypes.V1, channel.Version, "the channel version is not ics20-1") - }) - - s.Require().NoError(test.WaitForBlocks(ctx, 5, chainA), "failed to wait for blocks") - - t.Run("upgrade chain", func(t *testing.T) { - govProposalWallet := s.CreateUserOnChainA(ctx, testvalues.StartingTokenAmount) - s.UpgradeChain(ctx, chainA.(*cosmos.CosmosChain), govProposalWallet, testCfg.GetUpgradeConfig().PlanName, testCfg.ChainConfigs[0].Tag, testCfg.GetUpgradeConfig().Tag) - }) - - t.Run("upgrade channel to ics20-2", func(t *testing.T) { - chA, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - s.Require().NoError(err) - - upgradeFields := channeltypes.NewUpgradeFields(chA.Ordering, chA.ConnectionHops, transfertypes.V2) - s.InitiateChannelUpgrade(ctx, chainA, chainAWallet, channelA.PortID, channelA.ChannelID, upgradeFields) - }) - - t.Run("verify channel A upgraded and transfer version is ics20-2", func(t *testing.T) { - err := test.WaitForCondition(time.Minute*3, time.Second*2, func() (bool, error) { - channel, err := query.Channel(ctx, chainA, channelA.PortID, channelA.ChannelID) - if err != nil { - return false, err - } - - return channel.Version == transfertypes.V2, nil - }) - s.Require().NoError(err, "failed to wait for channel to be upgraded to ics20-2") - }) - - t.Run("multi-denom IBC token transfer from chainB to chainA, to make sure the upgrade did not break the packet flow", func(t *testing.T) { - transferCoins := []sdk.Coin{ - testvalues.DefaultTransferAmount(chainBIBCToken.IBCDenom()), - testvalues.DefaultTransferAmount(chainBDenom), - } - - transferTxResp := s.Transfer(ctx, chainB, chainBWallet, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, transferCoins, chainBAddress, chainAAddress, s.GetTimeoutHeight(ctx, chainA), 0, "", nil) - s.AssertTxSuccess(transferTxResp) - - s.AssertPacketRelayed(ctx, chainB, channelA.Counterparty.PortID, channelA.Counterparty.ChannelID, 2) - - actualNativeBalance, err := chainA.GetBalance(ctx, chainAAddress, chainADenom) - s.Require().NoError(err) - expected := testvalues.StartingTokenAmount - s.Require().Equal(expected, actualNativeBalance.Int64()) - - chainAIBCToken := testsuite.GetIBCToken(chainBDenom, channelA.PortID, channelA.ChannelID) - actualIBCTokenBalance, err := query.Balance(ctx, chainA, chainAAddress, chainAIBCToken.IBCDenom()) - s.Require().NoError(err) - expected = testvalues.IBCTransferAmount - s.Require().Equal(expected, actualIBCTokenBalance.Int64()) - }) -} - // ClientState queries the current ClientState by clientID func (*UpgradeTestSuite) ClientState(ctx context.Context, chain ibc.Chain, clientID string) (*clienttypes.QueryClientStateResponse, error) { res, err := query.GRPCQuery[clienttypes.QueryClientStateResponse](ctx, chain, &clienttypes.QueryClientStateRequest{ClientId: clientID}) diff --git a/e2e/testsuite/testconfig.go b/e2e/testsuite/testconfig.go index 501543cd003..9a370d834ba 100644 --- a/e2e/testsuite/testconfig.go +++ b/e2e/testsuite/testconfig.go @@ -698,6 +698,7 @@ func getGenesisModificationFunction(cc ChainConfig) func(ibc.ChainConfig, []byte simdSupportsGovV1Genesis := binary == defaultBinary && testvalues.GovGenesisFeatureReleases.IsSupported(version) + // TODO: Remove after we drop v7 support (this is only needed right now because of v6 -> v7 upgrade tests) if simdSupportsGovV1Genesis { return defaultGovv1ModifyGenesis(version) } @@ -742,6 +743,14 @@ func defaultGovv1ModifyGenesis(version string) func(ibc.ChainConfig, []byte) ([] appState[ibcexported.ModuleName] = ibcGenBz } + if !testvalues.ChannelsV2FeatureReleases.IsSupported(version) { + ibcGenBz, err := modifyChannelV2GenesisAppState(appState[ibcexported.ModuleName]) + if err != nil { + return nil, err + } + appState[ibcexported.ModuleName] = ibcGenBz + } + appGenesis.AppState, err = json.Marshal(appState) if err != nil { return nil, err @@ -812,6 +821,46 @@ func defaultGovv1Beta1ModifyGenesis(version string) func(ibc.ChainConfig, []byte if err != nil { return nil, fmt.Errorf("failed to unmarshal gov genesis bytes into map: %w", err) } + appStateMap[ibcexported.ModuleName] = ibcModuleGenesisMap + } + + if !testvalues.ChannelParamsFeatureReleases.IsSupported(version) { + ibcModuleBytes, err := json.Marshal(appStateMap[ibcexported.ModuleName]) + if err != nil { + return nil, fmt.Errorf("failed to extract ibc genesis bytes: %s", err) + } + + ibcGenesisBytes, err := modifyChannelGenesisAppState(ibcModuleBytes) + if err != nil { + return nil, err + } + + ibcModuleGenesisMap := map[string]interface{}{} + err = json.Unmarshal(ibcGenesisBytes, &ibcModuleGenesisMap) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal gov genesis bytes into map: %w", err) + } + appStateMap[ibcexported.ModuleName] = ibcModuleGenesisMap + + } + + if !testvalues.ChannelsV2FeatureReleases.IsSupported(version) { + ibcModuleBytes, err := json.Marshal(appStateMap[ibcexported.ModuleName]) + if err != nil { + return nil, fmt.Errorf("failed to extract ibc genesis bytes: %s", err) + } + + ibcGenesisBytes, err := modifyChannelV2GenesisAppState(ibcModuleBytes) + if err != nil { + return nil, err + } + + ibcModuleGenesisMap := map[string]interface{}{} + err = json.Unmarshal(ibcGenesisBytes, &ibcModuleGenesisMap) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal gov genesis bytes into map: %w", err) + } + appStateMap[ibcexported.ModuleName] = ibcModuleGenesisMap } appStateMap[govtypes.ModuleName] = govModuleGenesisMap @@ -916,3 +965,13 @@ func modifyChannelGenesisAppState(ibcAppState []byte) ([]byte, error) { return json.Marshal(ibcGenesisMap) } + +func modifyChannelV2GenesisAppState(ibcAppState []byte) ([]byte, error) { + var ibcGenesisMap map[string]interface{} + if err := json.Unmarshal(ibcAppState, &ibcGenesisMap); err != nil { + return nil, err + } + delete(ibcGenesisMap, "channel_v2_genesis") + + return json.Marshal(ibcGenesisMap) +} diff --git a/e2e/testsuite/testsuite.go b/e2e/testsuite/testsuite.go index 2ea2c3bc1a8..734b41a39b9 100644 --- a/e2e/testsuite/testsuite.go +++ b/e2e/testsuite/testsuite.go @@ -29,7 +29,6 @@ import ( "github.com/cosmos/ibc-go/e2e/relayer" "github.com/cosmos/ibc-go/e2e/testsuite/diagnostics" "github.com/cosmos/ibc-go/e2e/testsuite/query" - "github.com/cosmos/ibc-go/e2e/testvalues" feetypes "github.com/cosmos/ibc-go/v9/modules/apps/29-fee/types" transfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" @@ -663,9 +662,9 @@ func (s *E2ETestSuite) GetRelayerExecReporter() *testreporter.RelayerExecReporte } // TransferChannelOptions configures both of the chains to have non-incentivized transfer channels. -func (s *E2ETestSuite) TransferChannelOptions() ibc.CreateChannelOptions { +func (*E2ETestSuite) TransferChannelOptions() ibc.CreateChannelOptions { opts := ibc.DefaultChannelOpts() - opts.Version = DetermineDefaultTransferVersion(s.GetAllChains()) + opts.Version = transfertypes.V1 return opts } @@ -673,7 +672,7 @@ func (s *E2ETestSuite) TransferChannelOptions() ibc.CreateChannelOptions { func (s *E2ETestSuite) FeeTransferChannelOptions() ibc.CreateChannelOptions { versionMetadata := feetypes.Metadata{ FeeVersion: feetypes.Version, - AppVersion: DetermineDefaultTransferVersion(s.GetAllChains()), + AppVersion: transfertypes.V1, } versionBytes, err := feetypes.ModuleCdc.MarshalJSON(&versionMetadata) s.Require().NoError(err) @@ -740,27 +739,20 @@ func getValidatorsAndFullNodes(chainIdx int) (int, int) { } // GetMsgTransfer returns a MsgTransfer that is constructed based on the channel version -func GetMsgTransfer(portID, channelID, version string, tokens sdk.Coins, sender, receiver string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, memo string, forwarding *transfertypes.Forwarding) *transfertypes.MsgTransfer { - if len(tokens) == 0 { - panic(errors.New("tokens cannot be empty")) - } - +func GetMsgTransfer(portID, channelID, version string, token sdk.Coin, sender, receiver string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, memo string) *transfertypes.MsgTransfer { var msg *transfertypes.MsgTransfer switch version { case transfertypes.V1: msg = &transfertypes.MsgTransfer{ SourcePort: portID, SourceChannel: channelID, - Token: tokens[0], + Token: token, Sender: sender, Receiver: receiver, TimeoutHeight: timeoutHeight, TimeoutTimestamp: timeoutTimestamp, Memo: memo, - Tokens: sdk.NewCoins(), } - case transfertypes.V2: - msg = transfertypes.NewMsgTransfer(portID, channelID, tokens, sender, receiver, timeoutHeight, timeoutTimestamp, memo, forwarding) default: panic(fmt.Errorf("unsupported transfer version: %s", version)) } @@ -789,18 +781,6 @@ func ThreeChainSetup() ChainOptionConfiguration { // DefaultChannelOpts returns the default chain options for the test suite based on the provided chains. func DefaultChannelOpts(chains []ibc.Chain) ibc.CreateChannelOptions { channelOptions := ibc.DefaultChannelOpts() - channelOptions.Version = DetermineDefaultTransferVersion(chains) + channelOptions.Version = transfertypes.V1 return channelOptions } - -// DetermineDefaultTransferVersion determines the version of transfer that should be used with an arbitrary number of chains. -// the default is V2, but if any chain does not support V2, then V1 is used. -func DetermineDefaultTransferVersion(chains []ibc.Chain) string { - for _, chain := range chains { - chainVersion := chain.Config().Images[0].Version - if !testvalues.ICS20v2FeatureReleases.IsSupported(chainVersion) { - return transfertypes.V1 - } - } - return transfertypes.V2 -} diff --git a/e2e/testsuite/tx.go b/e2e/testsuite/tx.go index 23e6131b3f6..73dfe089978 100644 --- a/e2e/testsuite/tx.go +++ b/e2e/testsuite/tx.go @@ -31,7 +31,6 @@ import ( "github.com/cosmos/ibc-go/e2e/testsuite/sanitize" "github.com/cosmos/ibc-go/e2e/testvalues" feetypes "github.com/cosmos/ibc-go/v9/modules/apps/29-fee/types" - transfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" ) @@ -281,9 +280,9 @@ func (s *E2ETestSuite) ExecuteGovV1Beta1Proposal(ctx context.Context, chain ibc. // Transfer broadcasts a MsgTransfer message. func (s *E2ETestSuite) Transfer(ctx context.Context, chain ibc.Chain, user ibc.Wallet, - portID, channelID string, tokens sdk.Coins, sender, receiver string, + portID, channelID string, token sdk.Coin, sender, receiver string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, - memo string, forwarding *transfertypes.Forwarding, + memo string, ) sdk.TxResponse { channel, err := query.Channel(ctx, chain, portID, channelID) s.Require().NoError(err) @@ -303,7 +302,7 @@ func (s *E2ETestSuite) Transfer(ctx context.Context, chain ibc.Chain, user ibc.W transferVersion = version.AppVersion } - msg := GetMsgTransfer(portID, channelID, transferVersion, tokens, sender, receiver, timeoutHeight, timeoutTimestamp, memo, forwarding) + msg := GetMsgTransfer(portID, channelID, transferVersion, token, sender, receiver, timeoutHeight, timeoutTimestamp, memo) return s.BroadcastMessages(ctx, chain, user, msg) } diff --git a/e2e/testvalues/values.go b/e2e/testvalues/values.go index aab8bbacb5d..7f0bbcbdc2a 100644 --- a/e2e/testvalues/values.go +++ b/e2e/testvalues/values.go @@ -43,10 +43,6 @@ func DefaultTransferAmount(denom string) sdk.Coin { return sdk.Coin{Denom: denom, Amount: sdkmath.NewInt(IBCTransferAmount)} } -func DefaultTransferCoins(denom string) sdk.Coins { - return sdk.NewCoins(DefaultTransferAmount(denom)) -} - func TransferAmount(amount int64, denom string) sdk.Coin { return sdk.Coin{Denom: denom, Amount: sdkmath.NewInt(amount)} } @@ -136,7 +132,6 @@ var TransactionEventQueryFeatureReleases = semverutil.FeatureReleases{ MajorVersion: "v8", } -// ICS20v2FeatureReleases represents the releases the support for ICS20 v2 was released in. -var ICS20v2FeatureReleases = semverutil.FeatureReleases{ - MajorVersion: "v9", +var ChannelsV2FeatureReleases = semverutil.FeatureReleases{ + MajorVersion: "v10", } diff --git a/modules/apps/27-interchain-accounts/host/keeper/relay_test.go b/modules/apps/27-interchain-accounts/host/keeper/relay_test.go index 16c3c405221..8bc89cc9384 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/relay_test.go +++ b/modules/apps/27-interchain-accounts/host/keeper/relay_test.go @@ -320,13 +320,12 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { msg := transfertypes.NewMsgTransfer( transferPath.EndpointA.ChannelConfig.PortID, transferPath.EndpointA.ChannelID, - sdk.NewCoins(ibctesting.TestCoin), + ibctesting.TestCoin, interchainAccountAddr, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.GetTimeoutHeight(), 0, "", - nil, ) data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding) @@ -356,13 +355,12 @@ func (suite *KeeperTestSuite) TestOnRecvPacket() { msg := transfertypes.NewMsgTransfer( transferPath.EndpointA.ChannelConfig.PortID, transferPath.EndpointA.ChannelID, - sdk.NewCoins(ibctesting.TestCoin), + ibctesting.TestCoin, interchainAccountAddr, "", suite.chainB.GetTimeoutHeight(), 0, "", - nil, ) data, err := icatypes.SerializeCosmosTx(suite.chainA.GetSimApp().AppCodec(), []proto.Message{msg}, encoding) @@ -746,13 +744,12 @@ func (suite *KeeperTestSuite) TestJSONOnRecvPacket() { "@type": "/ibc.applications.transfer.v1.MsgTransfer", "source_port": "transfer", "source_channel": "` + transferPath.EndpointA.ChannelID + `", - "tokens": [{ "denom": "stake", "amount": "100" }], + "token": { "denom": "stake", "amount": "100" }, "sender": "` + icaAddress + `", "receiver": "cosmos15ulrf36d4wdtrtqzkgaan9ylwuhs7k7qz753uk", "timeout_height": { "revision_number": 1, "revision_height": 100 }, "timeout_timestamp": 0, - "memo": "", - "forwarding": { "hops": [], "unwind": false } + "memo": "" } ] }`) diff --git a/modules/apps/29-fee/keeper/events_test.go b/modules/apps/29-fee/keeper/events_test.go index 9e441f9730b..856c2c683dc 100644 --- a/modules/apps/29-fee/keeper/events_test.go +++ b/modules/apps/29-fee/keeper/events_test.go @@ -91,7 +91,7 @@ func (suite *KeeperTestSuite) TestIncentivizePacketEvent() { func (suite *KeeperTestSuite) TestDistributeFeeEvent() { // create an incentivized transfer path path := ibctesting.NewPath(suite.chainA, suite.chainB) - feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V2})) + feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V1})) path.EndpointA.ChannelConfig.Version = feeTransferVersion path.EndpointB.ChannelConfig.Version = feeTransferVersion path.EndpointA.ChannelConfig.PortID = transfertypes.PortID @@ -111,9 +111,8 @@ func (suite *KeeperTestSuite) TestDistributeFeeEvent() { msgTransfer := transfertypes.NewMsgTransfer( path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, - sdk.NewCoins(ibctesting.TestCoin), suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), + ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, "", - nil, ) res, err := suite.chainA.SendMsgs(msgPayPacketFee, msgTransfer) diff --git a/modules/apps/29-fee/transfer_test.go b/modules/apps/29-fee/transfer_test.go index 285b4528a38..f16180d39e5 100644 --- a/modules/apps/29-fee/transfer_test.go +++ b/modules/apps/29-fee/transfer_test.go @@ -12,16 +12,12 @@ import ( // Integration test to ensure ics29 works with ics20 func (suite *FeeTestSuite) TestFeeTransfer() { testCases := []struct { - name string - coinsToTransfer sdk.Coins + name string + coinToTransfer sdk.Coin }{ { "transfer single denom", - sdk.NewCoins(ibctesting.TestCoin), - }, - { - "transfer multiple denoms", - sdk.NewCoins(ibctesting.TestCoin, ibctesting.SecondaryTestCoin), + ibctesting.TestCoin, }, } @@ -30,7 +26,7 @@ func (suite *FeeTestSuite) TestFeeTransfer() { suite.SetupTest() // reset path := ibctesting.NewPath(suite.chainA, suite.chainB) - feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V2})) + feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V1})) path.EndpointA.ChannelConfig.Version = feeTransferVersion path.EndpointB.ChannelConfig.Version = feeTransferVersion path.EndpointA.ChannelConfig.PortID = transfertypes.PortID @@ -46,7 +42,7 @@ func (suite *FeeTestSuite) TestFeeTransfer() { msgs := []sdk.Msg{ types.NewMsgPayPacketFee(fee, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, suite.chainA.SenderAccount.GetAddress().String(), nil), - transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, tc.coinsToTransfer, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, "", nil), + transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, tc.coinToTransfer, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, ""), } res, err := suite.chainA.SendMsgs(msgs...) @@ -112,13 +108,13 @@ func (suite *FeeTestSuite) TestTransferFeeUpgrade() { // configure the initial path to create a regular transfer channel path.EndpointA.ChannelConfig.PortID = transfertypes.PortID path.EndpointB.ChannelConfig.PortID = transfertypes.PortID - path.EndpointA.ChannelConfig.Version = transfertypes.V2 - path.EndpointB.ChannelConfig.Version = transfertypes.V2 + path.EndpointA.ChannelConfig.Version = transfertypes.V1 + path.EndpointB.ChannelConfig.Version = transfertypes.V1 path.Setup() // configure the channel upgrade to an incentivized fee enabled transfer channel - upgradeVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V2})) + upgradeVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V1})) path.EndpointA.ChannelConfig.ProposedUpgrade.Fields.Version = upgradeVersion path.EndpointB.ChannelConfig.ProposedUpgrade.Fields.Version = upgradeVersion @@ -155,7 +151,7 @@ func (suite *FeeTestSuite) TestTransferFeeUpgrade() { fee := types.NewFee(defaultRecvFee, defaultAckFee, defaultTimeoutFee) msgs := []sdk.Msg{ types.NewMsgPayPacketFee(fee, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, suite.chainA.SenderAccount.GetAddress().String(), nil), - transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, sdk.NewCoins(ibctesting.TestCoin), suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, "", nil), + transfertypes.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, ""), } res, err := suite.chainA.SendMsgs(msgs...) @@ -185,7 +181,7 @@ func (suite *FeeTestSuite) TestOnesidedFeeMiddlewareTransferHandshake() { RemoveFeeMiddleware(suite.chainB) // remove fee middleware from chainB path := ibctesting.NewPath(suite.chainA, suite.chainB) - feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V2})) + feeTransferVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: transfertypes.V1})) path.EndpointA.ChannelConfig.Version = feeTransferVersion // this will be renegotiated by the Try step path.EndpointB.ChannelConfig.Version = "" // this will be overwritten by the Try step path.EndpointA.ChannelConfig.PortID = transfertypes.PortID @@ -193,6 +189,6 @@ func (suite *FeeTestSuite) TestOnesidedFeeMiddlewareTransferHandshake() { path.Setup() - suite.Require().Equal(path.EndpointA.ChannelConfig.Version, transfertypes.V2) - suite.Require().Equal(path.EndpointB.ChannelConfig.Version, transfertypes.V2) + suite.Require().Equal(path.EndpointA.ChannelConfig.Version, transfertypes.V1) + suite.Require().Equal(path.EndpointB.ChannelConfig.Version, transfertypes.V1) } diff --git a/modules/apps/callbacks/callbacks_test.go b/modules/apps/callbacks/callbacks_test.go index 743683f2f99..500a0b0c2eb 100644 --- a/modules/apps/callbacks/callbacks_test.go +++ b/modules/apps/callbacks/callbacks_test.go @@ -80,8 +80,8 @@ func (s *CallbacksTestSuite) SetupTransferTest() { s.path.EndpointA.ChannelConfig.PortID = ibctesting.TransferPort s.path.EndpointB.ChannelConfig.PortID = ibctesting.TransferPort - s.path.EndpointA.ChannelConfig.Version = transfertypes.V2 - s.path.EndpointB.ChannelConfig.Version = transfertypes.V2 + s.path.EndpointA.ChannelConfig.Version = transfertypes.V1 + s.path.EndpointB.ChannelConfig.Version = transfertypes.V1 s.path.Setup() } @@ -90,7 +90,7 @@ func (s *CallbacksTestSuite) SetupTransferTest() { func (s *CallbacksTestSuite) SetupFeeTransferTest() { s.setupChains() - feeTransferVersion := string(feetypes.ModuleCdc.MustMarshalJSON(&feetypes.Metadata{FeeVersion: feetypes.Version, AppVersion: transfertypes.V2})) + feeTransferVersion := string(feetypes.ModuleCdc.MustMarshalJSON(&feetypes.Metadata{FeeVersion: feetypes.Version, AppVersion: transfertypes.V1})) s.path.EndpointA.ChannelConfig.Version = feeTransferVersion s.path.EndpointB.ChannelConfig.Version = feeTransferVersion s.path.EndpointA.ChannelConfig.PortID = transfertypes.PortID diff --git a/modules/apps/callbacks/forwarding_test.go b/modules/apps/callbacks/forwarding_test.go deleted file mode 100644 index f52ebb34437..00000000000 --- a/modules/apps/callbacks/forwarding_test.go +++ /dev/null @@ -1,189 +0,0 @@ -package ibccallbacks_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/suite" - - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/ibc-go/modules/apps/callbacks/testing/simapp" - callbacktypes "github.com/cosmos/ibc-go/modules/apps/callbacks/types" - "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" - ibctesting "github.com/cosmos/ibc-go/v9/testing" -) - -func init() { - ibctesting.DefaultTestingAppInit = SetupTestingApp -} - -type CallbacksForwardingTestSuite struct { - suite.Suite - - coordinator *ibctesting.Coordinator - - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - chainC *ibctesting.TestChain - - pathAtoB *ibctesting.Path - pathBtoC *ibctesting.Path -} - -// setupChains sets up a coordinator with 3 test chains. -func (s *CallbacksForwardingTestSuite) setupChains() { - s.coordinator = ibctesting.NewCoordinator(s.T(), 3) - s.chainA = s.coordinator.GetChain(ibctesting.GetChainID(1)) - s.chainB = s.coordinator.GetChain(ibctesting.GetChainID(2)) - s.chainC = s.coordinator.GetChain(ibctesting.GetChainID(3)) - - s.pathAtoB = ibctesting.NewTransferPath(s.chainA, s.chainB) - s.pathBtoC = ibctesting.NewTransferPath(s.chainB, s.chainC) -} - -func (s *CallbacksForwardingTestSuite) SetupTest() { - s.setupChains() - - s.pathAtoB.Setup() - s.pathBtoC.Setup() -} - -func TestIBCCallbacksForwardingTestsuite(t *testing.T) { - suite.Run(t, new(CallbacksForwardingTestSuite)) -} - -// TestForwardingWithMemoCallback tests that, when forwarding a packet with memo from A to B to C, -// the callback is executed only on the final hop. -// NOTE: this does not test the full forwarding behaviour (assert on amounts, packets, acks etc) -// as this is covered in other forwarding tests. -func (s *CallbacksForwardingTestSuite) TestForwardingWithMemoCallback() { - testCases := []struct { - name string - testMemo string - expCallbackMapOnChainB map[callbacktypes.CallbackType]int - expCallbackMapOnChainC map[callbacktypes.CallbackType]int - }{ - { - name: "no memo", - expCallbackMapOnChainB: map[callbacktypes.CallbackType]int{}, - expCallbackMapOnChainC: map[callbacktypes.CallbackType]int{}, - }, - { - name: "recv callback", - testMemo: fmt.Sprintf(`{"dest_callback": {"address": "%s"}}`, simapp.SuccessContract), - expCallbackMapOnChainB: map[callbacktypes.CallbackType]int{}, - expCallbackMapOnChainC: map[callbacktypes.CallbackType]int{callbacktypes.CallbackTypeReceivePacket: 1}, - }, - { - name: "ack callback", - testMemo: fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, simapp.SuccessContract), - expCallbackMapOnChainB: map[callbacktypes.CallbackType]int{callbacktypes.CallbackTypeAcknowledgementPacket: 1}, - expCallbackMapOnChainC: map[callbacktypes.CallbackType]int{}, - }, - { - name: "ack and recv callback", - testMemo: fmt.Sprintf(`{"src_callback": {"address": "%s"}, "dest_callback": {"address": "%s"}}`, simapp.SuccessContract, simapp.SuccessContract), - expCallbackMapOnChainB: map[callbacktypes.CallbackType]int{callbacktypes.CallbackTypeAcknowledgementPacket: 1}, - expCallbackMapOnChainC: map[callbacktypes.CallbackType]int{callbacktypes.CallbackTypeReceivePacket: 1}, - }, - { - name: "ack callback with low gas (error)", - testMemo: fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, simapp.OogErrorContract), - expCallbackMapOnChainB: map[callbacktypes.CallbackType]int{callbacktypes.CallbackTypeAcknowledgementPacket: 1}, - expCallbackMapOnChainC: map[callbacktypes.CallbackType]int{}, - }, - { - name: "recv callback with low gas (error)", - testMemo: fmt.Sprintf(`{"dest_callback": {"address": "%s"}}`, simapp.OogErrorContract), - expCallbackMapOnChainB: map[callbacktypes.CallbackType]int{}, - expCallbackMapOnChainC: map[callbacktypes.CallbackType]int{callbacktypes.CallbackTypeReceivePacket: 1}, - }, - } - for _, tc := range testCases { - s.Run(tc.name, func() { - s.SetupTest() - - coinOnA := ibctesting.TestCoin - sender := s.chainA.SenderAccounts[0].SenderAccount - receiver := s.chainC.SenderAccounts[0].SenderAccount - forwarding := types.NewForwarding(false, types.NewHop( - s.pathBtoC.EndpointA.ChannelConfig.PortID, - s.pathBtoC.EndpointA.ChannelID, - )) - successAck := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - - transferMsg := types.NewMsgTransfer( - s.pathAtoB.EndpointA.ChannelConfig.PortID, - s.pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(coinOnA), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - s.chainA.GetTimeoutTimestamp(), - tc.testMemo, - forwarding, - ) - - result, err := s.chainA.SendMsgs(transferMsg) - s.Require().NoError(err) // message committed - - // parse the packet from result events and recv packet on chainB - packetFromAtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - s.Require().NoError(err) - s.Require().NotNil(packetFromAtoB) - - err = s.pathAtoB.EndpointB.UpdateClient() - s.Require().NoError(err) - - result, err = s.pathAtoB.EndpointB.RecvPacketWithResult(packetFromAtoB) - s.Require().NoError(err) - s.Require().NotNil(result) - - packetFromBtoC, err := ibctesting.ParsePacketFromEvents(result.Events) - s.Require().NoError(err) - s.Require().NotNil(packetFromBtoC) - - err = s.pathBtoC.EndpointA.UpdateClient() - s.Require().NoError(err) - - err = s.pathBtoC.EndpointB.UpdateClient() - s.Require().NoError(err) - - result, err = s.pathBtoC.EndpointB.RecvPacketWithResult(packetFromBtoC) - s.Require().NoError(err) - s.Require().NotNil(result) - - packetOnC, err := ibctesting.ParseRecvPacketFromEvents(result.Events) - s.Require().NoError(err) - s.Require().NotNil(packetOnC) - - // Ack back to B - err = s.pathBtoC.EndpointB.UpdateClient() - s.Require().NoError(err) - - err = s.pathBtoC.EndpointA.AcknowledgePacket(packetFromBtoC, successAck.Acknowledgement()) - s.Require().NoError(err) - - // Ack back to A - err = s.pathAtoB.EndpointA.UpdateClient() - s.Require().NoError(err) - - err = s.pathAtoB.EndpointA.AcknowledgePacket(packetFromAtoB, successAck.Acknowledgement()) - s.Require().NoError(err) - - // We never expect chainA to have executed any callback - s.Require().Empty(GetSimApp(s.chainA).MockContractKeeper.Counters, "chainA's callbacks counter map is not empty") - - // We expect chainB to have executed callbacks when the memo is of type `src_callback` - chainBCallbackMap := GetSimApp(s.chainB).MockContractKeeper.Counters - s.Require().Equal(tc.expCallbackMapOnChainB, chainBCallbackMap, "chainB: expected callback counters map to be %v, got %v instead", tc.expCallbackMapOnChainB, chainBCallbackMap) - - // We expect chainC to have executed callbacks when the memo is of type `dest_callback` - chainCCallbackMap := GetSimApp(s.chainC).MockContractKeeper.Counters - s.Require().Equal(tc.expCallbackMapOnChainC, chainCCallbackMap, "chainC: expected callback counters map to be %v, got %v instead", tc.expCallbackMapOnChainC, chainCCallbackMap) - }) - } -} diff --git a/modules/apps/callbacks/ibc_middleware_test.go b/modules/apps/callbacks/ibc_middleware_test.go index 6e2ccd79722..7274fe7b5b4 100644 --- a/modules/apps/callbacks/ibc_middleware_test.go +++ b/modules/apps/callbacks/ibc_middleware_test.go @@ -1,10 +1,9 @@ package ibccallbacks_test import ( + "encoding/json" "fmt" - "github.com/cosmos/gogoproto/proto" - errorsmod "cosmossdk.io/errors" storetypes "cosmossdk.io/store/types" @@ -94,7 +93,7 @@ func (s *CallbacksTestSuite) TestWithICS4Wrapper() { } func (s *CallbacksTestSuite) TestSendPacket() { - var packetData transfertypes.FungibleTokenPacketDataV2 + var packetData transfertypes.FungibleTokenPacketData testCases := []struct { name string @@ -110,18 +109,6 @@ func (s *CallbacksTestSuite) TestSendPacket() { false, nil, }, - { - "success: multiple denoms", - func() { - packetData.Tokens = append(packetData.Tokens, transfertypes.Token{ - Denom: transfertypes.NewDenom(ibctesting.SecondaryDenom), - Amount: ibctesting.SecondaryTestCoin.Amount.String(), - }) - }, - types.CallbackTypeSendPacket, - false, - nil, - }, { "success: no-op on callback data is not valid", func() { @@ -177,17 +164,12 @@ func (s *CallbacksTestSuite) TestSendPacket() { transferICS4Wrapper := GetSimApp(s.chainA).TransferKeeper.GetICS4Wrapper() - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), ibctesting.TestAccAddress, ibctesting.TestAccAddress, fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, simapp.SuccessContract), - ibctesting.EmptyForwardingPacketData, ) tc.malleate() @@ -241,7 +223,7 @@ func (s *CallbacksTestSuite) TestOnAcknowledgementPacket() { ) var ( - packetData transfertypes.FungibleTokenPacketDataV2 + packetData transfertypes.FungibleTokenPacketData packet channeltypes.Packet ack []byte ctx sdk.Context @@ -317,17 +299,12 @@ func (s *CallbacksTestSuite) TestOnAcknowledgementPacket() { s.SetupTransferTest() userGasLimit = 600000 - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), ibctesting.TestAccAddress, ibctesting.TestAccAddress, fmt.Sprintf(`{"src_callback": {"address":"%s", "gas_limit":"%d"}}`, simapp.SuccessContract, userGasLimit), - ibctesting.EmptyForwardingPacketData, ) packet = channeltypes.Packet{ @@ -411,7 +388,7 @@ func (s *CallbacksTestSuite) TestOnTimeoutPacket() { ) var ( - packetData transfertypes.FungibleTokenPacketDataV2 + packetData transfertypes.FungibleTokenPacketData packet channeltypes.Packet ctx sdk.Context ) @@ -490,10 +467,9 @@ func (s *CallbacksTestSuite) TestOnTimeoutPacket() { timeoutTimestamp := uint64(s.chainB.GetContext().BlockTime().UnixNano()) msg := transfertypes.NewMsgTransfer( s.path.EndpointA.ChannelConfig.PortID, s.path.EndpointA.ChannelID, - sdk.NewCoins(ibctesting.TestCoin), s.chainA.SenderAccount.GetAddress().String(), + ibctesting.TestCoin, s.chainA.SenderAccount.GetAddress().String(), s.chainB.SenderAccount.GetAddress().String(), clienttypes.ZeroHeight(), timeoutTimestamp, fmt.Sprintf(`{"src_callback": {"address":"%s", "gas_limit":"%d"}}`, ibctesting.TestAccAddress, userGasLimit), // set user gas limit above panic level in mock contract keeper - nil, ) res, err := s.chainA.SendMsgs(msg) @@ -504,7 +480,7 @@ func (s *CallbacksTestSuite) TestOnTimeoutPacket() { s.Require().NoError(err) s.Require().NotNil(packet) - err = proto.Unmarshal(packet.Data, &packetData) + err = json.Unmarshal(packet.Data, &packetData) s.Require().NoError(err) ctx = s.chainA.GetContext() @@ -574,7 +550,7 @@ func (s *CallbacksTestSuite) TestOnRecvPacket() { ) var ( - packetData transfertypes.FungibleTokenPacketDataV2 + packetData transfertypes.FungibleTokenPacketData packet channeltypes.Packet ctx sdk.Context userGasLimit uint64 @@ -651,17 +627,12 @@ func (s *CallbacksTestSuite) TestOnRecvPacket() { // set user gas limit above panic level in mock contract keeper userGasLimit = 600_000 - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), ibctesting.TestAccAddress, s.chainB.SenderAccount.GetAddress().String(), fmt.Sprintf(`{"dest_callback": {"address":"%s", "gas_limit":"%d"}}`, ibctesting.TestAccAddress, userGasLimit), - ibctesting.EmptyForwardingPacketData, ) packet = channeltypes.Packet{ @@ -736,7 +707,7 @@ func (s *CallbacksTestSuite) TestOnRecvPacket() { func (s *CallbacksTestSuite) TestWriteAcknowledgement() { var ( - packetData transfertypes.FungibleTokenPacketDataV2 + packetData transfertypes.FungibleTokenPacketData packet channeltypes.Packet ctx sdk.Context ack ibcexported.Acknowledgement @@ -783,17 +754,12 @@ func (s *CallbacksTestSuite) TestWriteAcknowledgement() { s.SetupTransferTest() // set user gas limit above panic level in mock contract keeper - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), ibctesting.TestAccAddress, s.chainB.SenderAccount.GetAddress().String(), fmt.Sprintf(`{"dest_callback": {"address":"%s", "gas_limit":"600000"}}`, ibctesting.TestAccAddress), - ibctesting.EmptyForwardingPacketData, ) packet = channeltypes.Packet{ @@ -1000,46 +966,9 @@ func (s *CallbacksTestSuite) TestUnmarshalPacketDataV1() { } expPacketDataICS20V2 := transfertypes.FungibleTokenPacketDataV2{ - Tokens: []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: ibctesting.TestAccAddress, - Receiver: ibctesting.TestAccAddress, - Memo: fmt.Sprintf(`{"src_callback": {"address": "%s"}, "dest_callback": {"address":"%s"}}`, ibctesting.TestAccAddress, ibctesting.TestAccAddress), - Forwarding: ibctesting.EmptyForwardingPacketData, - } - - portID := s.path.EndpointA.ChannelConfig.PortID - channelID := s.path.EndpointA.ChannelID - - // Unmarshal ICS20 v1 packet data into v2 packet data - data := expPacketDataICS20V1.GetBytes() - packetData, version, err := unmarshalerStack.UnmarshalPacketData(s.chainA.GetContext(), portID, channelID, data) - s.Require().NoError(err) - s.Require().Equal(s.path.EndpointA.ChannelConfig.Version, version) - s.Require().Equal(expPacketDataICS20V2, packetData) -} - -func (s *CallbacksTestSuite) TestUnmarshalPacketDataV2() { - s.SetupTransferTest() - - // We will pass the function call down the transfer stack to the transfer module - // transfer stack UnmarshalPacketData call order: callbacks -> fee -> transfer - transferStack, ok := s.chainA.App.GetIBCKeeper().PortKeeper.Route(transfertypes.ModuleName) - s.Require().True(ok) - - unmarshalerStack, ok := transferStack.(types.CallbacksCompatibleModule) - s.Require().True(ok) - - expPacketDataICS20V2 := transfertypes.FungibleTokenPacketDataV2{ - Tokens: []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, + Token: transfertypes.Token{ + Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), + Amount: ibctesting.TestCoin.Amount.String(), }, Sender: ibctesting.TestAccAddress, Receiver: ibctesting.TestAccAddress, @@ -1049,12 +978,12 @@ func (s *CallbacksTestSuite) TestUnmarshalPacketDataV2() { portID := s.path.EndpointA.ChannelConfig.PortID channelID := s.path.EndpointA.ChannelID - // Unmarshal ICS20 v2 packet data - data := expPacketDataICS20V2.GetBytes() + // Unmarshal ICS20 v1 packet data into v2 packet data + data := expPacketDataICS20V1.GetBytes() packetData, version, err := unmarshalerStack.UnmarshalPacketData(s.chainA.GetContext(), portID, channelID, data) s.Require().NoError(err) - s.Require().Equal(expPacketDataICS20V2, packetData) s.Require().Equal(s.path.EndpointA.ChannelConfig.Version, version) + s.Require().Equal(expPacketDataICS20V2, packetData) } func (s *CallbacksTestSuite) TestGetAppVersion() { diff --git a/modules/apps/callbacks/replay_test.go b/modules/apps/callbacks/replay_test.go index f414f47f5f5..501584586ed 100644 --- a/modules/apps/callbacks/replay_test.go +++ b/modules/apps/callbacks/replay_test.go @@ -326,11 +326,10 @@ func (s *CallbacksTestSuite) ExecuteFailedTransfer(memo string) { msg := transfertypes.NewMsgTransfer( s.path.EndpointA.ChannelConfig.PortID, s.path.EndpointA.ChannelID, - sdk.NewCoins(amount), + amount, s.chainA.SenderAccount.GetAddress().String(), s.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, memo, - nil, ) res, err := s.chainA.SendMsgs(msg) diff --git a/modules/apps/callbacks/transfer_test.go b/modules/apps/callbacks/transfer_test.go index 656df913543..96b2abc45aa 100644 --- a/modules/apps/callbacks/transfer_test.go +++ b/modules/apps/callbacks/transfer_test.go @@ -189,11 +189,10 @@ func (s *CallbacksTestSuite) ExecuteTransfer(memo string) { msg := transfertypes.NewMsgTransfer( s.path.EndpointA.ChannelConfig.PortID, s.path.EndpointA.ChannelID, - sdk.NewCoins(amount), + amount, s.chainA.SenderAccount.GetAddress().String(), s.chainB.SenderAccount.GetAddress().String(), clienttypes.NewHeight(1, 100), 0, memo, - nil, ) res, err := s.chainA.SendMsgs(msg) @@ -224,11 +223,10 @@ func (s *CallbacksTestSuite) ExecuteTransferTimeout(memo string) { msg := transfertypes.NewMsgTransfer( s.path.EndpointA.ChannelConfig.PortID, s.path.EndpointA.ChannelID, - sdk.NewCoins(amount), + amount, s.chainA.SenderAccount.GetAddress().String(), s.chainB.SenderAccount.GetAddress().String(), timeoutHeight, timeoutTimestamp, memo, - nil, ) res, err := s.chainA.SendMsgs(msg) diff --git a/modules/apps/callbacks/types/callbacks_test.go b/modules/apps/callbacks/types/callbacks_test.go index 26dc099edfd..b67c3782b44 100644 --- a/modules/apps/callbacks/types/callbacks_test.go +++ b/modules/apps/callbacks/types/callbacks_test.go @@ -319,161 +319,6 @@ func (s *CallbacksTypesTestSuite) TestGetCallbackData() { }, nil, }, - { - "success v2: destination callback with 0 user defined gas limit", - func() { - callbackKey = types.DestinationCallbackKey - - remainingGas = 2_000_000 - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"dest_callback": {"address": "%s", "gas_limit":"0"}}`, sender), - } - }, - types.CallbackData{ - CallbackAddress: sender, - SenderAddress: "", - ExecutionGasLimit: 1_000_000, - CommitGasLimit: 1_000_000, - ApplicationVersion: transfertypes.V2, - }, - nil, - }, - { - "success v2: source callback with gas limit < remaining gas < max gas", - func() { - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.GetDenom()), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"src_callback": {"address": "%s", "gas_limit": "50000"}}`, sender), - } - - remainingGas = 100_000 - }, - types.CallbackData{ - CallbackAddress: sender, - SenderAddress: sender, - ExecutionGasLimit: 50_000, - CommitGasLimit: 50_000, - ApplicationVersion: transfertypes.V2, - }, - nil, - }, - { - "success v2: source callback with remaining gas < gas limit < max gas", - func() { - remainingGas = 100_000 - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"src_callback": {"address": "%s", "gas_limit": "200000"}}`, sender), - } - }, - types.CallbackData{ - CallbackAddress: sender, - SenderAddress: sender, - ExecutionGasLimit: 100_000, - CommitGasLimit: 200_000, - ApplicationVersion: transfertypes.V2, - }, - nil, - }, - { - "success v2: source callback with remaining gas < max gas < gas limit", - func() { - remainingGas = 100_000 - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"src_callback": {"address": "%s", "gas_limit": "2000000"}}`, sender), - } - }, - types.CallbackData{ - CallbackAddress: sender, - SenderAddress: sender, - ExecutionGasLimit: 100_000, - CommitGasLimit: 1_000_000, - ApplicationVersion: transfertypes.V2, - }, - nil, - }, - { - "success v2: destination callback with remaining gas < max gas < gas limit", - func() { - callbackKey = types.DestinationCallbackKey - - remainingGas = 100_000 - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"dest_callback": {"address": "%s", "gas_limit": "2000000"}}`, sender), - } - }, - types.CallbackData{ - CallbackAddress: sender, - SenderAddress: "", - ExecutionGasLimit: 100_000, - CommitGasLimit: 1_000_000, - ApplicationVersion: transfertypes.V2, - }, - nil, - }, - { - "success v2: source callback with max gas < remaining gas < gas limit", - func() { - remainingGas = 2_000_000 - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"src_callback": {"address": "%s", "gas_limit": "3000000"}}`, sender), - } - }, - types.CallbackData{ - CallbackAddress: sender, - SenderAddress: sender, - ExecutionGasLimit: 1_000_000, - CommitGasLimit: 1_000_000, - ApplicationVersion: transfertypes.V2, - }, - nil, - }, { "failure: packet data does not implement PacketDataProvider", func() { @@ -482,60 +327,6 @@ func (s *CallbacksTypesTestSuite) TestGetCallbackData() { types.CallbackData{}, types.ErrNotPacketDataProvider, }, - { - "failure v2: empty memo", - func() { - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: "", - } - }, - types.CallbackData{}, - types.ErrCallbackKeyNotFound, - }, - { - "failure v2: empty address", - func() { - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"address": ""}}`, - } - }, - types.CallbackData{}, - types.ErrCallbackAddressNotFound, - }, - { - "failure v2: space address", - func() { - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"address": " "}}`, - } - }, - types.CallbackData{}, - types.ErrCallbackAddressNotFound, - }, } for _, tc := range testCases { @@ -544,7 +335,7 @@ func (s *CallbacksTypesTestSuite) TestGetCallbackData() { s.SetupTest() callbackKey = types.SourceCallbackKey - version = transfertypes.V2 + version = transfertypes.V1 tc.malleate() @@ -624,32 +415,6 @@ func (s *CallbacksTypesTestSuite) TestGetDestSourceCallbackDataTransfer() { types.GetSourceCallbackData, true, }, - { - "success: src_callback v2", - func() { - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, sender), - } - - expCallbackData = expSrcCallBack - expCallbackData.ApplicationVersion = transfertypes.V2 - - s.path.EndpointA.ChannelConfig.Version = transfertypes.V2 - s.path.EndpointA.ChannelConfig.PortID = transfertypes.ModuleName - s.path.EndpointB.ChannelConfig.Version = transfertypes.V2 - s.path.EndpointB.ChannelConfig.PortID = transfertypes.ModuleName - }, - types.GetSourceCallbackData, - true, - }, { "success: dest_callback v1", func() { @@ -671,32 +436,6 @@ func (s *CallbacksTypesTestSuite) TestGetDestSourceCallbackDataTransfer() { types.GetDestCallbackData, false, }, - { - "success: dest_callback v2", - func() { - packetData = transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"dest_callback": {"address": "%s"}}`, sender), - } - - expCallbackData = expDstCallBack - expCallbackData.ApplicationVersion = transfertypes.V2 - - s.path.EndpointA.ChannelConfig.Version = transfertypes.V2 - s.path.EndpointA.ChannelConfig.PortID = transfertypes.ModuleName - s.path.EndpointB.ChannelConfig.Version = transfertypes.V2 - s.path.EndpointB.ChannelConfig.PortID = transfertypes.ModuleName - }, - types.GetDestCallbackData, - false, - }, } for _, tc := range testCases { @@ -828,126 +567,6 @@ func (s *CallbacksTypesTestSuite) TestGetCallbackAddress() { }, "", }, - { - "success v2: memo has callbacks in json struct and properly formatted src_callback_address which does not match packet sender", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, receiver), - }, - receiver, - }, - { - "success v2: valid src_callback address specified in memo that matches sender", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, sender), - }, - sender, - }, - { - "failure v2: memo is empty", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: "", - }, - "", - }, - { - "failure v2: memo is not json string", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: "memo", - }, - "", - }, - { - "failure v2: memo has empty src_callback object", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {}}`, - }, - "", - }, - { - "failure v2: memo does not have callbacks in json struct", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"Key": 10}`, - }, - "", - }, - { - "failure v2: memo has src_callback in json struct but does not have address key", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"Key": 10}}`, - }, - "", - }, - { - "failure v2: memo has src_callback in json struct but does not have string value for address key", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"address": 10}}`, - }, - "", - }, } for _, tc := range testCases { @@ -1070,141 +689,6 @@ func (s *CallbacksTypesTestSuite) TestUserDefinedGasLimit() { }, 0, }, - { - "success v2: memo is empty", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: "", - }, - 0, - }, - { - "success v2: memo has user defined gas limit", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"gas_limit": "100"}}`, - }, - 100, - }, - { - "success v2: user defined gas limit is zero", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"gas_limit": "0"}}`, - }, - 0, - }, - { - "failure v2: memo has empty src_callback object", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {}}`, - }, - 0, - }, - { - "failure v2: memo has user defined gas limit as json number", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"gas_limit": 100}}`, - }, - 0, - }, - { - "failure v2: memo has user defined gas limit as negative", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"gas_limit": "-100"}}`, - }, - 0, - }, - { - "failure v2: memo has user defined gas limit as string", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"gas_limit": "invalid"}}`, - }, - 0, - }, - { - "failure v2: memo has user defined gas limit as empty string", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `{"src_callback": {"gas_limit": ""}}`, - }, - 0, - }, - { - "failure v2: malformed memo", - transfertypes.FungibleTokenPacketDataV2{ - Tokens: transfertypes.Tokens{ - { - Denom: denom, - Amount: amount, - }, - }, - Sender: sender, - Receiver: receiver, - Memo: `invalid`, - }, - 0, - }, } for _, tc := range testCases { diff --git a/modules/apps/callbacks/types/events_test.go b/modules/apps/callbacks/types/events_test.go index ae4ec7deaad..e5c4e98fff1 100644 --- a/modules/apps/callbacks/types/events_test.go +++ b/modules/apps/callbacks/types/events_test.go @@ -64,7 +64,7 @@ func (s *CallbacksTypesTestSuite) TestEvents() { CallbackAddress: ibctesting.TestAccAddress, ExecutionGasLimit: 100_000, CommitGasLimit: 200_000, - ApplicationVersion: transfertypes.V2, + ApplicationVersion: transfertypes.V1, }, nil, func() []abci.Event { @@ -80,7 +80,7 @@ func (s *CallbacksTypesTestSuite) TestEvents() { sdk.NewAttribute(types.AttributeKeyCallbackSourceChannelID, ibctesting.FirstChannelID), sdk.NewAttribute(types.AttributeKeyCallbackSequence, "1"), sdk.NewAttribute(types.AttributeKeyCallbackResult, types.AttributeValueCallbackSuccess), - sdk.NewAttribute(types.AttributeKeyCallbackBaseApplicationVersion, transfertypes.V2), + sdk.NewAttribute(types.AttributeKeyCallbackBaseApplicationVersion, transfertypes.V1), ), }.ToABCIEvents() }, diff --git a/modules/apps/callbacks/v2/ibc_middleware_test.go b/modules/apps/callbacks/v2/ibc_middleware_test.go index 7f2db397a81..ba4cef072aa 100644 --- a/modules/apps/callbacks/v2/ibc_middleware_test.go +++ b/modules/apps/callbacks/v2/ibc_middleware_test.go @@ -97,7 +97,7 @@ func (s *CallbacksTestSuite) TestWithWriteAckWrapper() { } func (s *CallbacksTestSuite) TestSendPacket() { - var packetData transfertypes.FungibleTokenPacketDataV2 + var packetData transfertypes.FungibleTokenPacketData testCases := []struct { name string @@ -113,18 +113,6 @@ func (s *CallbacksTestSuite) TestSendPacket() { false, nil, }, - { - "success: multiple denoms", - func() { - packetData.Tokens = append(packetData.Tokens, transfertypes.Token{ - Denom: transfertypes.NewDenom(ibctesting.SecondaryDenom), - Amount: ibctesting.SecondaryTestCoin.Amount.String(), - }) - }, - types.CallbackTypeSendPacket, - false, - nil, - }, { "success: no-op on callback data is not valid", func() { @@ -169,24 +157,19 @@ func (s *CallbacksTestSuite) TestSendPacket() { s.Run(tc.name, func() { s.SetupTest() - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), s.chainA.SenderAccount.GetAddress().String(), ibctesting.TestAccAddress, fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, simapp.SuccessContract), - ibctesting.EmptyForwardingPacketData, ) tc.malleate() payload := channeltypesv2.NewPayload( transfertypes.PortID, transfertypes.PortID, - transfertypes.V2, transfertypes.EncodingProtobuf, + transfertypes.V1, transfertypes.EncodingJSON, packetData.GetBytes(), ) @@ -237,7 +220,7 @@ func (s *CallbacksTestSuite) TestOnAcknowledgementPacket() { ) var ( - packetData transfertypes.FungibleTokenPacketDataV2 + packetData transfertypes.FungibleTokenPacketData ack []byte ctx sdk.Context userGasLimit uint64 @@ -308,17 +291,12 @@ func (s *CallbacksTestSuite) TestOnAcknowledgementPacket() { s.SetupTest() userGasLimit = 600000 - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), ibctesting.TestAccAddress, ibctesting.TestAccAddress, fmt.Sprintf(`{"src_callback": {"address":"%s", "gas_limit":"%d"}}`, simapp.SuccessContract, userGasLimit), - ibctesting.EmptyForwardingPacketData, ) ack = channeltypes.NewResultAcknowledgement([]byte{1}).Acknowledgement() @@ -329,7 +307,7 @@ func (s *CallbacksTestSuite) TestOnAcknowledgementPacket() { payload := channeltypesv2.NewPayload( transfertypes.PortID, transfertypes.PortID, - transfertypes.V2, transfertypes.EncodingProtobuf, + transfertypes.V1, transfertypes.EncodingJSON, packetData.GetBytes(), ) @@ -397,7 +375,7 @@ func (s *CallbacksTestSuite) TestOnTimeoutPacket() { ) var ( - packetData transfertypes.FungibleTokenPacketDataV2 + packetData transfertypes.FungibleTokenPacketData ctx sdk.Context ) @@ -416,7 +394,7 @@ func (s *CallbacksTestSuite) TestOnTimeoutPacket() { { "failure: underlying app OnTimeoutPacket fails", func() { - packetData.Tokens = nil + packetData.Amount = "invalid amount" }, noExecution, transfertypes.ErrInvalidAmount, @@ -469,22 +447,17 @@ func (s *CallbacksTestSuite) TestOnTimeoutPacket() { // succeed on timeout userGasLimit := 600_000 timeoutTimestamp := uint64(s.chainB.GetContext().BlockTime().Unix()) - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), s.chainA.SenderAccount.GetAddress().String(), ibctesting.TestAccAddress, fmt.Sprintf(`{"src_callback": {"address":"%s", "gas_limit":"%d"}}`, simapp.SuccessContract, userGasLimit), - ibctesting.EmptyForwardingPacketData, ) payload := channeltypesv2.NewPayload( transfertypes.PortID, transfertypes.PortID, - transfertypes.V2, transfertypes.EncodingProtobuf, + transfertypes.V1, transfertypes.EncodingJSON, packetData.GetBytes(), ) @@ -567,7 +540,7 @@ func (s *CallbacksTestSuite) TestOnRecvPacket() { ) var ( - packetData transfertypes.FungibleTokenPacketDataV2 + packetData transfertypes.FungibleTokenPacketData ctx sdk.Context userGasLimit uint64 ) @@ -587,7 +560,7 @@ func (s *CallbacksTestSuite) TestOnRecvPacket() { { "failure: underlying app OnRecvPacket fails", func() { - packetData.Tokens = nil + packetData.Denom = "" }, noExecution, failure, @@ -636,22 +609,17 @@ func (s *CallbacksTestSuite) TestOnRecvPacket() { // set user gas limit above panic level in mock contract keeper userGasLimit = 600_000 - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), ibctesting.TestAccAddress, s.chainB.SenderAccount.GetAddress().String(), fmt.Sprintf(`{"dest_callback": {"address":"%s", "gas_limit":"%d"}}`, ibctesting.TestAccAddress, userGasLimit), - ibctesting.EmptyForwardingPacketData, ) payload := channeltypesv2.NewPayload( transfertypes.PortID, transfertypes.PortID, - transfertypes.V2, transfertypes.EncodingProtobuf, + transfertypes.V1, transfertypes.EncodingJSON, packetData.GetBytes(), ) @@ -718,7 +686,7 @@ func (s *CallbacksTestSuite) TestOnRecvPacket() { func (s *CallbacksTestSuite) TestWriteAcknowledgement() { var ( - packetData transfertypes.FungibleTokenPacketDataV2 + packetData transfertypes.FungibleTokenPacketData destClient string ctx sdk.Context ack channeltypesv2.Acknowledgement @@ -773,17 +741,12 @@ func (s *CallbacksTestSuite) TestWriteAcknowledgement() { s.SetupTest() // set user gas limit above panic level in mock contract keeper - packetData = transfertypes.NewFungibleTokenPacketDataV2( - []transfertypes.Token{ - { - Denom: transfertypes.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, + packetData = transfertypes.NewFungibleTokenPacketData( + ibctesting.TestCoin.Denom, + ibctesting.TestCoin.Amount.String(), ibctesting.TestAccAddress, s.chainB.SenderAccount.GetAddress().String(), fmt.Sprintf(`{"dest_callback": {"address":"%s", "gas_limit":"600000"}}`, ibctesting.TestAccAddress), - ibctesting.EmptyForwardingPacketData, ) ctx = s.chainB.GetContext() @@ -794,7 +757,7 @@ func (s *CallbacksTestSuite) TestWriteAcknowledgement() { payload := channeltypesv2.NewPayload( transfertypes.PortID, transfertypes.PortID, - transfertypes.V2, transfertypes.EncodingProtobuf, + transfertypes.V1, transfertypes.EncodingJSON, packetData.GetBytes(), ) timeoutTimestamp := uint64(s.chainB.GetContext().BlockTime().Unix()) diff --git a/modules/apps/transfer/client/cli/tx.go b/modules/apps/transfer/client/cli/tx.go index 4850019c841..753312dfeaa 100644 --- a/modules/apps/transfer/client/cli/tx.go +++ b/modules/apps/transfer/client/cli/tx.go @@ -23,8 +23,6 @@ const ( flagPacketTimeoutTimestamp = "packet-timeout-timestamp" flagAbsoluteTimeouts = "absolute-timeouts" flagMemo = "memo" - flagForwarding = "forwarding" - flagUnwind = "unwind" ) // defaultRelativePacketTimeoutTimestamp is the default packet timeout timestamp (in nanoseconds) @@ -36,18 +34,13 @@ var defaultRelativePacketTimeoutTimestamp = uint64((time.Duration(10) * time.Min // NewTransferTxCmd returns the command to create a NewMsgTransfer transaction func NewTransferTxCmd() *cobra.Command { cmd := &cobra.Command{ - Use: "transfer [src-port] [src-channel] [receiver] [coins]", - Short: "Transfer one or more fungible tokens through IBC", - Long: strings.TrimSpace(`Transfer one or more fungible tokens through IBC. Multiple tokens can be transferred in a single -packet if the coins list is a comma-separated string (e.g. 100uatom,100uosmo). Timeouts can be specified as absolute using the {absolute-timeouts} flag. + Use: "transfer [src-port] [src-channel] [receiver] [coin]", + Short: "Transfer a fungible tokens through IBC", + Long: strings.TrimSpace(`Transfer one fungible tokens through IBC. Timeouts can be specified as absolute using the {absolute-timeouts} flag. Timeout height can be set by passing in the height string in the form {revision}-{height} using the {packet-timeout-height} flag. Note, relative timeout height is not supported. Relative timeout timestamp is added to the value of the user's local system clock time -using the {packet-timeout-timestamp} flag. If no timeout value is set then a default relative timeout value of 10 minutes is used. IBC tokens -can be automatically unwound to their native chain using the {unwind} flag. Please note that if the {unwind} flag is used, then all coins must -be IBC vouchers and share exactly the same denomination trace path, and the src-port and src-channel arguments must not be specified. Tokens can also be -automatically forwarded through multiple chains using the {forwarding} flag and specifying a comma-separated list of source portID/channelID pairs for -each intermediary chain. {unwind} and {forwarding} flags can be used together to first unwind IBC tokens to their native chain and then forward them to the final destination.`), - Example: fmt.Sprintf("%s tx ibc-transfer transfer [src-port] [src-channel] [receiver] [coins]", version.AppName), +using the {packet-timeout-timestamp} flag. If no timeout value is set then a default relative timeout value of 10 minutes is used.`), + Example: fmt.Sprintf("%s tx ibc-transfer transfer [src-port] [src-channel] [receiver] [coin]", version.AppName), Args: cobra.RangeArgs(2, 4), RunE: func(cmd *cobra.Command, args []string) error { clientCtx, err := client.GetClientTxContext(cmd) @@ -56,25 +49,18 @@ each intermediary chain. {unwind} and {forwarding} flags can be used together to } sender := clientCtx.GetFromAddress().String() - args, err = normalizeArgs(cmd, args) - if err != nil { - return err - } - srcPort := args[0] srcChannel := args[1] receiver := args[2] - coins, err := sdk.ParseCoinsNormalized(args[3]) + coin, err := sdk.ParseCoinNormalized(args[3]) if err != nil { return err } - for i, coin := range coins { - if !strings.HasPrefix(coin.Denom, "ibc/") { - denom := types.ExtractDenomFromPath(coin.Denom) - coins[i].Denom = denom.IBCDenom() - } + if !strings.HasPrefix(coin.Denom, "ibc/") { + denom := types.ExtractDenomFromPath(coin.Denom) + coin.Denom = denom.IBCDenom() } timeoutHeightStr, err := cmd.Flags().GetString(flagPacketTimeoutHeight) @@ -102,11 +88,6 @@ each intermediary chain. {unwind} and {forwarding} flags can be used together to return err } - forwarding, err := parseForwarding(cmd) - if err != nil { - return err - } - // NOTE: relative timeouts using block height are not supported. // if the timeouts are not absolute, CLI users rely solely on local clock time in order to calculate relative timestamps. if !absoluteTimeouts { @@ -128,7 +109,7 @@ each intermediary chain. {unwind} and {forwarding} flags can be used together to } msg := types.NewMsgTransfer( - srcPort, srcChannel, coins, sender, receiver, timeoutHeight, timeoutTimestamp, memo, forwarding, + srcPort, srcChannel, coin, sender, receiver, timeoutHeight, timeoutTimestamp, memo, ) return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg) @@ -139,74 +120,8 @@ each intermediary chain. {unwind} and {forwarding} flags can be used together to cmd.Flags().Uint64(flagPacketTimeoutTimestamp, defaultRelativePacketTimeoutTimestamp, "Packet timeout timestamp in nanoseconds from now. Default is 10 minutes. The timeout is disabled when set to 0.") cmd.Flags().Bool(flagAbsoluteTimeouts, false, "Timeout flags are used as absolute timeouts.") cmd.Flags().String(flagMemo, "", "Memo to be sent along with the packet.") - cmd.Flags().String(flagForwarding, "", "Forwarding information in the form of a comma separated list of portID/channelID pairs.") - cmd.Flags().Bool(flagUnwind, false, "Flag to indicate if the coin should be unwound to its native chain before forwarding.") flags.AddTxFlagsToCmd(cmd) return cmd } - -// parseForwarding parses the forwarding flag into a Forwarding object or nil if the flag is not specified. If the flag cannot -// be parsed or the hops aren't in the portID/channelID format an error is returned. -func parseForwarding(cmd *cobra.Command) (*types.Forwarding, error) { - var hops []types.Hop - - unwind, err := cmd.Flags().GetBool(flagUnwind) - if err != nil { - return nil, err - } - forwarding := types.NewForwarding(unwind) - - forwardingString, err := cmd.Flags().GetString(flagForwarding) - if err != nil { - return nil, err - } - - if strings.TrimSpace(forwardingString) == "" { - // If forwarding not specified, we might have unwind set - return forwarding, nil - } - - pairs := strings.Split(forwardingString, ",") - for _, pair := range pairs { - pairSplit := strings.Split(pair, "/") - if len(pairSplit) != 2 { - return nil, fmt.Errorf("expected a portID/channelID pair, found %s", pair) - } - - hop := types.NewHop(pairSplit[0], pairSplit[1]) - hops = append(hops, hop) - } - - forwarding.Hops = hops - return forwarding, nil -} - -// normalizeArgs takes the positional arguments specified and if the unwind flag -// is false and the args array is of length 4, returns them as-is or, if unwind is true and the -// args array has a length of 2, inserts two empty strings at the beginning signifying the -// portID and channelID. -func normalizeArgs(cmd *cobra.Command, args []string) ([]string, error) { - unwind, err := cmd.Flags().GetBool(flagUnwind) - if err != nil { - return nil, err - } - - if unwind { - if len(args) != 2 { - return nil, fmt.Errorf("expected only 2 arguments, got %d", len(args)) - } - - // Inject empty source portID/channelID. - args = append([]string{"", ""}, args...) - return args, nil - } - - // Unwind false, just ensure we have 4 args. - if len(args) != 4 { - return nil, fmt.Errorf("expected 4 args, got %d", len(args)) - } - - return args, nil -} diff --git a/modules/apps/transfer/ibc_module.go b/modules/apps/transfer/ibc_module.go index ed190190b96..e60ca6a58f6 100644 --- a/modules/apps/transfer/ibc_module.go +++ b/modules/apps/transfer/ibc_module.go @@ -87,7 +87,7 @@ func (im IBCModule) OnChanOpenInit( // default to latest supported version if strings.TrimSpace(version) == "" { - version = types.V2 + version = types.V1 } if !slices.Contains(types.SupportedVersions, version) { @@ -112,8 +112,8 @@ func (im IBCModule) OnChanOpenTry( } if !slices.Contains(types.SupportedVersions, counterpartyVersion) { - im.keeper.Logger(ctx).Debug("invalid counterparty version, proposing latest app version", "counterpartyVersion", counterpartyVersion, "version", types.V2) - return types.V2, nil + im.keeper.Logger(ctx).Debug("invalid counterparty version, proposing latest app version", "counterpartyVersion", counterpartyVersion, "version", types.V1) + return types.V1, nil } return counterpartyVersion, nil @@ -165,7 +165,6 @@ func (IBCModule) OnChanCloseConfirm( // OnRecvPacket implements the IBCModule interface. A successful acknowledgement // is returned if the packet data is successfully decoded and the receive application // logic returns without error. -// A nil acknowledgement may be returned when using the packet forwarding feature. This signals to core IBC that the acknowledgement will be written asynchronously. func (im IBCModule) OnRecvPacket( ctx context.Context, channelVersion string, @@ -191,7 +190,8 @@ func (im IBCModule) OnRecvPacket( return ack } - receivedCoins, ackErr := im.keeper.OnRecvPacket( + // NOTE: this needs to set the ackErr variable and not do if ackErr := ... because the ackErr variable is used in the defer function + ackErr = im.keeper.OnRecvPacket( ctx, data, packet.SourcePort, @@ -205,29 +205,12 @@ func (im IBCModule) OnRecvPacket( return ack } - if data.HasForwarding() { - // we are now sending from the forward escrow address to the final receiver address. - if ackErr = im.keeper.ForwardPacket(ctx, data, packet, receivedCoins); ackErr != nil { - ack = channeltypes.NewErrorAcknowledgement(ackErr) - im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", ackErr.Error(), packet.Sequence)) - return ack - - } - - ack = nil - } - ack = channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - telemetry.ReportOnRecvPacket(packet.SourcePort, packet.SourceChannel, packet.DestinationPort, packet.DestinationChannel, data.Tokens) + telemetry.ReportOnRecvPacket(packet.SourcePort, packet.SourceChannel, packet.DestinationPort, packet.DestinationChannel, data.Token) im.keeper.Logger(ctx).Info("successfully handled ICS-20 packet", "sequence", packet.Sequence) - if data.HasForwarding() { - // NOTE: acknowledgement will be written asynchronously - return nil - } - // NOTE: acknowledgement will be written synchronously during IBC handler execution. return ack } @@ -254,12 +237,6 @@ func (im IBCModule) OnAcknowledgementPacket( return err } - if forwardedPacket, isForwarded := im.keeper.GetForwardedPacket(ctx, packet.SourcePort, packet.SourceChannel, packet.Sequence); isForwarded { - if err := im.keeper.HandleForwardedPacketAcknowledgement(ctx, packet, forwardedPacket, data, ack); err != nil { - return err - } - } - events.EmitOnAcknowledgementPacketEvent(ctx, data, ack) return nil @@ -282,12 +259,6 @@ func (im IBCModule) OnTimeoutPacket( return err } - if forwardedPacket, isForwarded := im.keeper.GetForwardedPacket(ctx, packet.SourcePort, packet.SourceChannel, packet.Sequence); isForwarded { - if err := im.keeper.HandleForwardedPacketTimeout(ctx, packet, forwardedPacket, data); err != nil { - return err - } - } - events.EmitOnTimeoutEvent(ctx, data) return nil @@ -313,8 +284,8 @@ func (im IBCModule) OnChanUpgradeTry(ctx context.Context, portID, channelID stri } if !slices.Contains(types.SupportedVersions, counterpartyVersion) { - im.keeper.Logger(ctx).Debug("invalid counterparty version, proposing latest app version", "counterpartyVersion", counterpartyVersion, "version", types.V2) - return types.V2, nil + im.keeper.Logger(ctx).Debug("invalid counterparty version, proposing latest app version", "counterpartyVersion", counterpartyVersion, "version", types.V1) + return types.V1, nil } return counterpartyVersion, nil diff --git a/modules/apps/transfer/ibc_module_test.go b/modules/apps/transfer/ibc_module_test.go index c11a88bf04d..8c89a5ec95d 100644 --- a/modules/apps/transfer/ibc_module_test.go +++ b/modules/apps/transfer/ibc_module_test.go @@ -1,7 +1,6 @@ package transfer_test import ( - "encoding/json" "errors" "math" @@ -35,22 +34,22 @@ func (suite *TransferTestSuite) TestOnChanOpenInit() { expVersion string }{ { - "success", func() {}, nil, types.V2, + "success", func() {}, nil, types.V1, }, { // connection hops is not used in the transfer application callback, // it is already validated in the core OnChanUpgradeInit. "success: invalid connection hops", func() { path.EndpointA.ConnectionID = ibctesting.InvalidID - }, nil, types.V2, + }, nil, types.V1, }, { "success: empty version string", func() { channel.Version = "" - }, nil, types.V2, + }, nil, types.V1, }, { - "success: ics20-1 legacy", func() { + "success: ics20-1", func() { channel.Version = types.V1 }, nil, types.V1, }, @@ -91,7 +90,7 @@ func (suite *TransferTestSuite) TestOnChanOpenInit() { Ordering: channeltypes.UNORDERED, Counterparty: counterparty, ConnectionHops: []string{path.EndpointA.ConnectionID}, - Version: types.V2, + Version: types.V1, } tc.malleate() // explicitly change fields in channel and testChannel @@ -127,10 +126,10 @@ func (suite *TransferTestSuite) TestOnChanOpenTry() { expVersion string }{ { - "success", func() {}, nil, types.V2, + "success", func() {}, nil, types.V1, }, { - "success: counterparty version is legacy ics20-1", func() { + "success: counterparty version is ics20-1", func() { counterpartyVersion = types.V1 }, nil, types.V1, }, @@ -138,7 +137,7 @@ func (suite *TransferTestSuite) TestOnChanOpenTry() { "success: invalid counterparty version, we propose new version", func() { // transfer module will propose the default version counterpartyVersion = "version" - }, nil, types.V2, + }, nil, types.V1, }, { "failure: max channels reached", func() { @@ -173,9 +172,9 @@ func (suite *TransferTestSuite) TestOnChanOpenTry() { Ordering: channeltypes.UNORDERED, Counterparty: counterparty, ConnectionHops: []string{path.EndpointA.ConnectionID}, - Version: types.V2, + Version: types.V1, } - counterpartyVersion = types.V2 + counterpartyVersion = types.V1 cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort) suite.Require().True(ok) @@ -225,7 +224,7 @@ func (suite *TransferTestSuite) TestOnChanOpenAck() { path := ibctesting.NewTransferPath(suite.chainA, suite.chainB) path.SetupConnections() path.EndpointA.ChannelID = ibctesting.FirstChannelID - counterpartyVersion = types.V2 + counterpartyVersion = types.V1 cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort) suite.Require().True(ok) @@ -261,34 +260,6 @@ func (suite *TransferTestSuite) TestOnRecvPacket() { { "success", func() {}, channeltypes.NewResultAcknowledgement([]byte{byte(1)}), "", }, - { - "success: async acknowledgment with forwarding path", - func() { - packetData := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(sdk.DefaultBondDenom), - Amount: sdkmath.NewInt(100).String(), - }, - }, - suite.chainA.SenderAccount.GetAddress().String(), - suite.chainB.SenderAccount.GetAddress().String(), - "", types.NewForwardingPacketData("", types.NewHop(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)), - ) - packet.Data = packetData.GetBytes() - - forwardingHopsBz, err := json.Marshal(packetData.Forwarding.Hops) - suite.Require().NoError(err) - for i, attr := range expectedAttributes { - if attr.Key == types.AttributeKeyForwardingHops { - expectedAttributes[i].Value = string(forwardingHopsBz) - break - } - } - }, - nil, - "", - }, { "failure: invalid packet data bytes", func() { @@ -298,15 +269,15 @@ func (suite *TransferTestSuite) TestOnRecvPacket() { expectedAttributes = []sdk.Attribute{ sdk.NewAttribute(types.AttributeKeySender, ""), sdk.NewAttribute(types.AttributeKeyReceiver, ""), - sdk.NewAttribute(types.AttributeKeyTokens, "null"), + sdk.NewAttribute(types.AttributeKeyDenom, ""), + sdk.NewAttribute(types.AttributeKeyAmount, ""), sdk.NewAttribute(types.AttributeKeyMemo, ""), - sdk.NewAttribute(types.AttributeKeyForwardingHops, "null"), sdk.NewAttribute(types.AttributeKeyAckSuccess, "false"), - sdk.NewAttribute(types.AttributeKeyAckError, "cannot unmarshal ICS20-V2 transfer packet data: errUnknownField \"*types.FungibleTokenPacketDataV2\": {TagNum: 13, WireType:\"fixed64\"}: invalid type"), + 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-V2 transfer packet data: unexpected EOF: invalid type", + "cannot unmarshal ICS20-V1 transfer packet data: invalid character 'i' looking for beginning of value: invalid type", }, { "failure: receive disabled", @@ -325,30 +296,24 @@ func (suite *TransferTestSuite) TestOnRecvPacket() { path = ibctesting.NewTransferPath(suite.chainA, suite.chainB) path.Setup() - packetData := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(sdk.DefaultBondDenom), - Amount: sdkmath.NewInt(100).String(), - }, - }, + 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(), "", - ibctesting.EmptyForwardingPacketData, ) - tokensBz, err := json.Marshal(packetData.Tokens) - suite.Require().NoError(err) - forwardingHopsBz, err := json.Marshal(packetData.Forwarding.Hops) - suite.Require().NoError(err) - expectedAttributes = []sdk.Attribute{ sdk.NewAttribute(types.AttributeKeySender, packetData.Sender), sdk.NewAttribute(types.AttributeKeyReceiver, packetData.Receiver), - sdk.NewAttribute(types.AttributeKeyTokens, string(tokensBz)), + sdk.NewAttribute(types.AttributeKeyDenom, packetData.Denom), + sdk.NewAttribute(types.AttributeKeyAmount, packetData.Amount), sdk.NewAttribute(types.AttributeKeyMemo, packetData.Memo), - sdk.NewAttribute(types.AttributeKeyForwardingHops, string(forwardingHopsBz)), } if tc.expAck == nil || tc.expAck.Success() { expectedAttributes = append(expectedAttributes, sdk.NewAttribute(types.AttributeKeyAckSuccess, "true")) @@ -391,25 +356,19 @@ func (suite *TransferTestSuite) TestOnTimeoutPacket() { testCases := []struct { name string - coinsToSendToB sdk.Coins + coinsToSendToB sdk.Coin malleate func() expError error }{ { "success", - sdk.NewCoins(ibctesting.TestCoin), - func() {}, - nil, - }, - { - "success with multiple coins", - sdk.NewCoins(ibctesting.TestCoin, ibctesting.SecondaryTestCoin), + ibctesting.TestCoin, func() {}, nil, }, { "non-existent channel", - sdk.NewCoins(ibctesting.TestCoin), + ibctesting.TestCoin, func() { packet.SourceChannel = "channel-100" }, @@ -417,7 +376,7 @@ func (suite *TransferTestSuite) TestOnTimeoutPacket() { }, { "invalid packet data", - sdk.NewCoins(ibctesting.TestCoin), + ibctesting.TestCoin, func() { packet.Data = []byte("invalid data") }, @@ -425,7 +384,7 @@ func (suite *TransferTestSuite) TestOnTimeoutPacket() { }, { "already timed-out packet", - sdk.NewCoins(ibctesting.TestCoin), + ibctesting.TestCoin, func() { cbs, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(ibctesting.TransferPort) suite.Require().True(ok) @@ -454,7 +413,6 @@ func (suite *TransferTestSuite) TestOnTimeoutPacket() { timeoutHeight, 0, "", - nil, ) res, err := suite.chainA.SendMsgs(msg) suite.Require().NoError(err) // message committed @@ -620,7 +578,7 @@ func (suite *TransferTestSuite) TestOnChanUpgradeTry() { if tc.expError == nil { suite.Require().NoError(err) - suite.Require().Equal(types.V2, version) + suite.Require().Equal(types.V1, version) } else { suite.Require().Error(err) suite.Require().Contains(err.Error(), tc.expError.Error()) @@ -697,7 +655,6 @@ func (suite *TransferTestSuite) TestPacketDataUnmarshalerInterface() { sender = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String() receiver = sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()).String() - path *ibctesting.Path data []byte initialPacketData interface{} ) @@ -708,9 +665,8 @@ func (suite *TransferTestSuite) TestPacketDataUnmarshalerInterface() { expError error }{ { - "success: valid packet data single denom -> multidenom conversion with memo", + "success: valid packet data with memo", func() { - path.EndpointA.ChannelConfig.Version = types.V1 initialPacketData = types.FungibleTokenPacketData{ Denom: ibctesting.TestCoin.Denom, Amount: ibctesting.TestCoin.Amount.String(), @@ -718,31 +674,13 @@ func (suite *TransferTestSuite) TestPacketDataUnmarshalerInterface() { Receiver: receiver, Memo: "some memo", } - data = initialPacketData.(types.FungibleTokenPacketData).GetBytes() }, nil, }, { - "success: valid packet data single denom -> multidenom conversion without memo", + "success: valid packet data denom with trace", func() { - path.EndpointA.ChannelConfig.Version = types.V1 - initialPacketData = types.FungibleTokenPacketData{ - Denom: ibctesting.TestCoin.Denom, - Amount: ibctesting.TestCoin.Amount.String(), - Sender: sender, - Receiver: receiver, - Memo: "", - } - - data = initialPacketData.(types.FungibleTokenPacketData).GetBytes() - }, - nil, - }, - { - "success: valid packet data single denom with trace -> multidenom conversion with trace", - func() { - path.EndpointA.ChannelConfig.Version = types.V1 initialPacketData = types.FungibleTokenPacketData{ Denom: "transfer/channel-0/atom", Amount: ibctesting.TestCoin.Amount.String(), @@ -755,81 +693,21 @@ func (suite *TransferTestSuite) TestPacketDataUnmarshalerInterface() { }, nil, }, - { - "success: valid packet data multidenom with memo", - func() { - initialPacketData = types.FungibleTokenPacketDataV2{ - Tokens: []types.Token{ - { - Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0")), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: "some memo", - } - - data = initialPacketData.(types.FungibleTokenPacketDataV2).GetBytes() - }, - nil, - }, - { - "success: valid packet data multidenom nil trace", - func() { - path.EndpointA.ChannelConfig.Version = types.V2 - initialPacketData = types.FungibleTokenPacketDataV2{ - Tokens: []types.Token{ - { - Denom: types.NewDenom(ibctesting.TestCoin.Denom), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: "", - } - - data = initialPacketData.(types.FungibleTokenPacketDataV2).GetBytes() - }, - nil, - }, - { - "failure: invalid token trace", - func() { - path.EndpointA.ChannelConfig.Version = types.V2 - initialPacketData = types.FungibleTokenPacketDataV2{ - Tokens: []types.Token{ - { - Denom: types.NewDenom(ibctesting.TestCoin.Denom, []types.Hop{{}}...), - Amount: ibctesting.TestCoin.Amount.String(), - }, - }, - Sender: sender, - Receiver: receiver, - Memo: "", - } - - data = initialPacketData.(types.FungibleTokenPacketDataV2).GetBytes() - }, - errors.New("invalid token denom: invalid trace: invalid hop source port ID : identifier cannot be blank: invalid identifier"), - }, { "failure: invalid packet data", func() { data = []byte("invalid packet data") }, - errors.New("cannot unmarshal ICS20-V2 transfer 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 { tc := tc suite.Run(tc.name, func() { - path = ibctesting.NewTransferPath(suite.chainA, suite.chainB) - tc.malleate() + path := ibctesting.NewTransferPath(suite.chainA, suite.chainB) path.Setup() transferStack, ok := suite.chainA.App.GetIBCKeeper().PortKeeper.Route(types.ModuleName) @@ -849,7 +727,7 @@ func (suite *TransferTestSuite) TestPacketDataUnmarshalerInterface() { 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.Tokens[0].Amount) + 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) diff --git a/modules/apps/transfer/internal/events/events.go b/modules/apps/transfer/internal/events/events.go index 799db43e682..dc35c1a1824 100644 --- a/modules/apps/transfer/internal/events/events.go +++ b/modules/apps/transfer/internal/events/events.go @@ -13,19 +13,17 @@ import ( ) // EmitTransferEvent emits a ibc transfer event on successful transfers. -func EmitTransferEvent(ctx context.Context, sender, receiver string, tokens types.Tokens, memo string, forwardingHops []types.Hop) { +func EmitTransferEvent(ctx context.Context, sender, receiver string, token types.Token, memo string) { sdkCtx := sdk.UnwrapSDKContext(ctx) - tokensStr := mustMarshalJSON(tokens) - forwardingHopsStr := mustMarshalJSON(forwardingHops) sdkCtx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeTransfer, sdk.NewAttribute(types.AttributeKeySender, sender), sdk.NewAttribute(types.AttributeKeyReceiver, receiver), - sdk.NewAttribute(types.AttributeKeyTokens, tokensStr), + sdk.NewAttribute(types.AttributeKeyDenom, token.Denom.Path()), + sdk.NewAttribute(types.AttributeKeyAmount, token.Amount), sdk.NewAttribute(types.AttributeKeyMemo, memo), - sdk.NewAttribute(types.AttributeKeyForwardingHops, forwardingHopsStr), ), sdk.NewEvent( sdk.EventTypeMessage, @@ -36,15 +34,12 @@ func EmitTransferEvent(ctx context.Context, sender, receiver string, tokens type // EmitOnRecvPacketEvent emits a fungible token packet event in the OnRecvPacket callback func EmitOnRecvPacketEvent(ctx context.Context, packetData types.FungibleTokenPacketDataV2, ack ibcexported.Acknowledgement, ackErr error) { - tokensStr := mustMarshalJSON(packetData.Tokens) - forwardingHopStr := mustMarshalJSON(packetData.Forwarding.Hops) - eventAttributes := []sdk.Attribute{ sdk.NewAttribute(types.AttributeKeySender, packetData.Sender), sdk.NewAttribute(types.AttributeKeyReceiver, packetData.Receiver), - sdk.NewAttribute(types.AttributeKeyTokens, tokensStr), + sdk.NewAttribute(types.AttributeKeyDenom, packetData.Token.Denom.Path()), + sdk.NewAttribute(types.AttributeKeyAmount, packetData.Token.Amount), sdk.NewAttribute(types.AttributeKeyMemo, packetData.Memo), - sdk.NewAttribute(types.AttributeKeyForwardingHops, forwardingHopStr), sdk.NewAttribute(types.AttributeKeyAckSuccess, strconv.FormatBool(ack.Success())), } @@ -68,17 +63,15 @@ func EmitOnRecvPacketEvent(ctx context.Context, packetData types.FungibleTokenPa // EmitOnAcknowledgementPacketEvent emits a fungible token packet event in the OnAcknowledgementPacket callback func EmitOnAcknowledgementPacketEvent(ctx context.Context, packetData types.FungibleTokenPacketDataV2, ack channeltypes.Acknowledgement) { - tokensStr := mustMarshalJSON(packetData.Tokens) - forwardingHopsStr := mustMarshalJSON(packetData.Forwarding.Hops) sdkCtx := sdk.UnwrapSDKContext(ctx) sdkCtx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypePacket, sdk.NewAttribute(sdk.AttributeKeySender, packetData.Sender), sdk.NewAttribute(types.AttributeKeyReceiver, packetData.Receiver), - sdk.NewAttribute(types.AttributeKeyTokens, tokensStr), + sdk.NewAttribute(types.AttributeKeyDenom, packetData.Token.Denom.Path()), + sdk.NewAttribute(types.AttributeKeyAmount, packetData.Token.Amount), sdk.NewAttribute(types.AttributeKeyMemo, packetData.Memo), - sdk.NewAttribute(types.AttributeKeyForwardingHops, forwardingHopsStr), sdk.NewAttribute(types.AttributeKeyAck, ack.String()), ), sdk.NewEvent( @@ -108,16 +101,14 @@ func EmitOnAcknowledgementPacketEvent(ctx context.Context, packetData types.Fung // EmitOnTimeoutEvent emits a fungible token packet event in the OnTimeoutPacket callback func EmitOnTimeoutEvent(ctx context.Context, packetData types.FungibleTokenPacketDataV2) { sdkCtx := sdk.UnwrapSDKContext(ctx) - tokensStr := mustMarshalJSON(packetData.Tokens) - forwardingHopsStr := mustMarshalJSON(packetData.Forwarding.Hops) + tokenStr := mustMarshalJSON(packetData.Token) sdkCtx.EventManager().EmitEvents(sdk.Events{ sdk.NewEvent( types.EventTypeTimeout, sdk.NewAttribute(types.AttributeKeyReceiver, packetData.Sender), - sdk.NewAttribute(types.AttributeKeyRefundTokens, tokensStr), + sdk.NewAttribute(types.AttributeKeyRefundTokens, tokenStr), sdk.NewAttribute(types.AttributeKeyMemo, packetData.Memo), - sdk.NewAttribute(types.AttributeKeyForwardingHops, forwardingHopsStr), ), sdk.NewEvent( sdk.EventTypeMessage, diff --git a/modules/apps/transfer/internal/telemetry/telemetry.go b/modules/apps/transfer/internal/telemetry/telemetry.go index 91244134809..824d359ac05 100644 --- a/modules/apps/transfer/internal/telemetry/telemetry.go +++ b/modules/apps/transfer/internal/telemetry/telemetry.go @@ -13,25 +13,23 @@ import ( coremetrics "github.com/cosmos/ibc-go/v9/modules/core/metrics" ) -func ReportTransfer(sourcePort, sourceChannel, destinationPort, destinationChannel string, tokens types.Tokens) { +func ReportTransfer(sourcePort, sourceChannel, destinationPort, destinationChannel string, token types.Token) { labels := []metrics.Label{ telemetry.NewLabel(coremetrics.LabelDestinationPort, destinationPort), telemetry.NewLabel(coremetrics.LabelDestinationChannel, destinationChannel), } - for _, token := range tokens { - amount, ok := sdkmath.NewIntFromString(token.Amount) - if ok && amount.IsInt64() { - telemetry.SetGaugeWithLabels( - []string{"tx", "msg", "ibc", "transfer"}, - float32(amount.Int64()), - []metrics.Label{telemetry.NewLabel(coremetrics.LabelDenom, token.Denom.Path())}, - ) - } - - labels = append(labels, telemetry.NewLabel(coremetrics.LabelSource, fmt.Sprintf("%t", !token.Denom.HasPrefix(sourcePort, sourceChannel)))) + amount, ok := sdkmath.NewIntFromString(token.Amount) + if ok && amount.IsInt64() { + telemetry.SetGaugeWithLabels( + []string{"tx", "msg", "ibc", "transfer"}, + float32(amount.Int64()), + []metrics.Label{telemetry.NewLabel(coremetrics.LabelDenom, token.Denom.Path())}, + ) } + labels = append(labels, telemetry.NewLabel(coremetrics.LabelSource, fmt.Sprintf("%t", !token.Denom.HasPrefix(sourcePort, sourceChannel)))) + telemetry.IncrCounterWithLabels( []string{"ibc", types.ModuleName, "send"}, 1, @@ -39,34 +37,32 @@ func ReportTransfer(sourcePort, sourceChannel, destinationPort, destinationChann ) } -func ReportOnRecvPacket(sourcePort, sourceChannel, destinationPort, destinationChannel string, tokens types.Tokens) { +func ReportOnRecvPacket(sourcePort, sourceChannel, destinationPort, destinationChannel string, token types.Token) { labels := []metrics.Label{ telemetry.NewLabel(coremetrics.LabelSourcePort, sourcePort), telemetry.NewLabel(coremetrics.LabelSourceChannel, sourceChannel), } - for _, token := range tokens { - // Modify trace as Recv does. - if token.Denom.HasPrefix(sourcePort, sourceChannel) { - token.Denom.Trace = token.Denom.Trace[1:] - } else { - trace := []types.Hop{types.NewHop(destinationPort, destinationChannel)} - token.Denom.Trace = append(trace, token.Denom.Trace...) - } - - // Transfer amount has already been parsed in caller. - transferAmount, ok := sdkmath.NewIntFromString(token.Amount) - if ok && transferAmount.IsInt64() { - telemetry.SetGaugeWithLabels( - []string{"ibc", types.ModuleName, "packet", "receive"}, - float32(transferAmount.Int64()), - []metrics.Label{telemetry.NewLabel(coremetrics.LabelDenom, token.Denom.Path())}, - ) - } + // Modify trace as Recv does. + if token.Denom.HasPrefix(sourcePort, sourceChannel) { + token.Denom.Trace = token.Denom.Trace[1:] + } else { + trace := []types.Hop{types.NewHop(destinationPort, destinationChannel)} + token.Denom.Trace = append(trace, token.Denom.Trace...) + } - labels = append(labels, telemetry.NewLabel(coremetrics.LabelSource, fmt.Sprintf("%t", token.Denom.HasPrefix(sourcePort, sourceChannel)))) + // Transfer amount has already been parsed in caller. + transferAmount, ok := sdkmath.NewIntFromString(token.Amount) + if ok && transferAmount.IsInt64() { + telemetry.SetGaugeWithLabels( + []string{"ibc", types.ModuleName, "packet", "receive"}, + float32(transferAmount.Int64()), + []metrics.Label{telemetry.NewLabel(coremetrics.LabelDenom, token.Denom.Path())}, + ) } + labels = append(labels, telemetry.NewLabel(coremetrics.LabelSource, fmt.Sprintf("%t", token.Denom.HasPrefix(sourcePort, sourceChannel)))) + telemetry.IncrCounterWithLabels( []string{"ibc", types.ModuleName, "receive"}, 1, diff --git a/modules/apps/transfer/internal/types/ack.go b/modules/apps/transfer/internal/types/ack.go deleted file mode 100644 index b8d7cf9a284..00000000000 --- a/modules/apps/transfer/internal/types/ack.go +++ /dev/null @@ -1,27 +0,0 @@ -package types - -import ( - "fmt" - - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" -) - -// NewForwardErrorAcknowledgement returns a new error acknowledgement with path forwarding information. -func NewForwardErrorAcknowledgement(packet channeltypes.Packet, ack channeltypes.Acknowledgement) channeltypes.Acknowledgement { - ackErr := fmt.Sprintf("forwarding packet failed on %s/%s: %s", packet.GetSourcePort(), packet.GetSourceChannel(), ack.GetError()) - return channeltypes.Acknowledgement{ - Response: &channeltypes.Acknowledgement_Error{ - Error: ackErr, - }, - } -} - -// NewForwardTimeoutAcknowledgement returns a new error acknowledgement with path forwarding information. -func NewForwardTimeoutAcknowledgement(packet channeltypes.Packet) channeltypes.Acknowledgement { - ackErr := fmt.Sprintf("forwarding packet timed out on %s/%s", packet.GetSourcePort(), packet.GetSourceChannel()) - return channeltypes.Acknowledgement{ - Response: &channeltypes.Acknowledgement_Error{ - Error: ackErr, - }, - } -} diff --git a/modules/apps/transfer/keeper/export_test.go b/modules/apps/transfer/keeper/export_test.go index ba500ad2ddc..1f9c2eb81c3 100644 --- a/modules/apps/transfer/keeper/export_test.go +++ b/modules/apps/transfer/keeper/export_test.go @@ -5,7 +5,6 @@ import ( internaltypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/types" "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" ) // SetDenomTrace is a wrapper around setDenomTrace for testing purposes. @@ -29,22 +28,7 @@ func (k Keeper) GetAllDenomTraces(ctx sdk.Context) []internaltypes.DenomTrace { return traces } -// UnwindHops is a wrapper around unwindHops for testing purposes. -func (k Keeper) UnwindHops(ctx sdk.Context, msg *types.MsgTransfer) (*types.MsgTransfer, error) { - return k.unwindHops(ctx, msg) -} - -// SetForwardedPacket is a wrapper around setForwardedPacket for testing purposes. -func (k Keeper) SetForwardedPacket(ctx sdk.Context, portID, channelID string, sequence uint64, packet channeltypes.Packet) { - k.setForwardedPacket(ctx, portID, channelID, sequence, packet) -} - -// GetAllForwardedPackets is a wrapper around getAllForwardedPackets for testing purposes. -func (k Keeper) GetAllForwardedPackets(ctx sdk.Context) []types.ForwardedPacket { - return k.getAllForwardedPackets(ctx) -} - // CreatePacketDataBytesFromVersion is a wrapper around createPacketDataBytesFromVersion for testing purposes -func CreatePacketDataBytesFromVersion(appVersion, sender, receiver, memo string, tokens types.Tokens, hops []types.Hop) ([]byte, error) { - return createPacketDataBytesFromVersion(appVersion, sender, receiver, memo, tokens, hops) +func CreatePacketDataBytesFromVersion(appVersion, sender, receiver, memo string, token types.Token) ([]byte, error) { + return createPacketDataBytesFromVersion(appVersion, sender, receiver, memo, token) } diff --git a/modules/apps/transfer/keeper/forwarding.go b/modules/apps/transfer/keeper/forwarding.go deleted file mode 100644 index 99b81808bbe..00000000000 --- a/modules/apps/transfer/keeper/forwarding.go +++ /dev/null @@ -1,113 +0,0 @@ -package keeper - -import ( - "context" - - errorsmod "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" - ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors" -) - -// ForwardPacket forwards a fungible FungibleTokenPacketDataV2 to the next hop in the forwarding path. -func (k Keeper) ForwardPacket(ctx context.Context, data types.FungibleTokenPacketDataV2, packet channeltypes.Packet, receivedCoins sdk.Coins) error { - var nextForwardingPath *types.Forwarding - if len(data.Forwarding.Hops) > 1 { - // remove the first hop since we are going to send to the first hop now and we want to propagate the rest of the hops to the receiver - nextForwardingPath = types.NewForwarding(false, data.Forwarding.Hops[1:]...) - } - - // sending from module account (used as a temporary forward escrow) to the original receiver address. - sender := k.AuthKeeper.GetModuleAddress(types.ModuleName) - - msg := types.NewMsgTransfer( - data.Forwarding.Hops[0].PortId, - data.Forwarding.Hops[0].ChannelId, - receivedCoins, - sender.String(), - data.Receiver, - clienttypes.ZeroHeight(), - packet.TimeoutTimestamp, - data.Forwarding.DestinationMemo, - nextForwardingPath, - ) - - resp, err := k.Transfer(ctx, msg) - if err != nil { - return err - } - - k.setForwardedPacket(ctx, data.Forwarding.Hops[0].PortId, data.Forwarding.Hops[0].ChannelId, resp.Sequence, packet) - return nil -} - -// acknowledgeForwardedPacket writes the async acknowledgement for forwardedPacket -func (k Keeper) acknowledgeForwardedPacket(ctx context.Context, forwardedPacket, packet channeltypes.Packet, ack channeltypes.Acknowledgement) error { - if err := k.ics4Wrapper.WriteAcknowledgement(ctx, forwardedPacket, ack); err != nil { - return err - } - - k.deleteForwardedPacket(ctx, packet.SourcePort, packet.SourceChannel, packet.Sequence) - return nil -} - -// revertForwardedPacket reverts the logic of receive packet that occurs in the middle chains during a packet forwarding. -// If the packet fails to be forwarded all the way to the final destination, the state changes on this chain must be reverted -// before sending back the error acknowledgement to ensure atomic packet forwarding. -func (k Keeper) revertForwardedPacket(ctx context.Context, forwardedPacket channeltypes.Packet, failedPacketData types.FungibleTokenPacketDataV2) error { - /* - Recall that RecvPacket handles an incoming packet depending on the denom of the received funds: - 1. If the funds are native, then the amount is sent to the receiver from the escrow. - 2. If the funds are foreign, then a voucher token is minted. - We revert it in this function by: - 1. Sending funds back to escrow if the funds are native. - 2. Burning voucher tokens if the funds are foreign - */ - - forwardingAddr := k.AuthKeeper.GetModuleAddress(types.ModuleName) - escrow := types.GetEscrowAddress(forwardedPacket.DestinationPort, forwardedPacket.DestinationChannel) - - // we can iterate over the received tokens of forwardedPacket by iterating over the sent tokens of failedPacketData - for _, token := range failedPacketData.Tokens { - // parse the transfer amount - coin, err := token.ToCoin() - if err != nil { - return err - } - - // check if the token we received originated on the sender - // given that the packet is being reversed, we check the DestinationChannel and DestinationPort - // of the forwardedPacket to see if a hop was added to the trace during the receive step - if token.Denom.HasPrefix(forwardedPacket.DestinationPort, forwardedPacket.DestinationChannel) { - if err := k.BankKeeper.BurnCoins(ctx, types.ModuleName, sdk.NewCoins(coin)); err != nil { - return err - } - } else { - // send it back to the escrow address - if err := k.EscrowCoin(ctx, forwardingAddr, escrow, coin); err != nil { - return err - } - } - } - return nil -} - -// getReceiverFromPacketData returns either the sender specified in the packet data or the forwarding address -// if there are still hops left to perform. -func (k Keeper) getReceiverFromPacketData(data types.FungibleTokenPacketDataV2) (sdk.AccAddress, error) { - if data.HasForwarding() { - // since data.Receiver can potentially be a non-CosmosSDK AccAddress, we return early if the packet should be forwarded - return k.AuthKeeper.GetModuleAddress(types.ModuleName), nil - } - - receiver, err := sdk.AccAddressFromBech32(data.Receiver) - if err != nil { - return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "failed to decode receiver address %s: %v", data.Receiver, err) - } - - return receiver, nil -} diff --git a/modules/apps/transfer/keeper/genesis.go b/modules/apps/transfer/keeper/genesis.go index 330c6f0360d..5a9e5d3dde9 100644 --- a/modules/apps/transfer/keeper/genesis.go +++ b/modules/apps/transfer/keeper/genesis.go @@ -22,21 +22,14 @@ func (k Keeper) InitGenesis(ctx sdk.Context, state types.GenesisState) { for _, denomEscrow := range state.TotalEscrowed { k.SetTotalEscrowForDenom(ctx, denomEscrow) } - - // Set any forwarded packets imported. - for _, forwardPacketState := range state.ForwardedPackets { - forwardKey := forwardPacketState.ForwardKey - k.setForwardedPacket(ctx, forwardKey.PortId, forwardKey.ChannelId, forwardKey.Sequence, forwardPacketState.Packet) - } } // ExportGenesis exports ibc-transfer module's portID and denom trace info into its genesis state. func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { return &types.GenesisState{ - PortId: k.GetPort(ctx), - Denoms: k.GetAllDenoms(ctx), - Params: k.GetParams(ctx), - TotalEscrowed: k.GetAllTotalEscrowed(ctx), - ForwardedPackets: k.getAllForwardedPackets(ctx), + PortId: k.GetPort(ctx), + Denoms: k.GetAllDenoms(ctx), + Params: k.GetParams(ctx), + TotalEscrowed: k.GetAllTotalEscrowed(ctx), } } diff --git a/modules/apps/transfer/keeper/genesis_test.go b/modules/apps/transfer/keeper/genesis_test.go index 2a44b65610d..61fa75ebf3c 100644 --- a/modules/apps/transfer/keeper/genesis_test.go +++ b/modules/apps/transfer/keeper/genesis_test.go @@ -8,9 +8,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" - ibctesting "github.com/cosmos/ibc-go/v9/testing" ) func (suite *KeeperTestSuite) TestGenesis() { @@ -31,7 +28,6 @@ func (suite *KeeperTestSuite) TestGenesis() { {[]types.Hop{getHop(3), getHop(2), getHop(1), getHop(0)}, "1000000000000000"}, {[]types.Hop{getHop(4), getHop(3), getHop(2), getHop(1), getHop(0)}, "100000000000000000000"}, } - forwardPackets []types.ForwardedPacket ) for _, traceAndEscrowAmount := range traceAndEscrowAmounts { @@ -46,17 +42,6 @@ func (suite *KeeperTestSuite) TestGenesis() { suite.chainA.GetSimApp().TransferKeeper.SetTotalEscrowForDenom(suite.chainA.GetContext(), escrow) } - // Store forward packets on transfer/channel-1 and transfer/channel-2 - for _, channelID := range []string{"channel-1", "channel-2"} { - // go across '10' to test numerical order - for sequence := uint64(5); sequence <= 15; sequence++ { - packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequence, ibctesting.TransferPort, channelID, "", "", clienttypes.ZeroHeight(), 0) - forwardPackets = append(forwardPackets, types.ForwardedPacket{ForwardKey: channeltypes.NewPacketID(ibctesting.TransferPort, channelID, sequence), Packet: packet}) - - suite.chainA.GetSimApp().TransferKeeper.SetForwardedPacket(suite.chainA.GetContext(), ibctesting.TransferPort, channelID, sequence, packet) - } - } - genesis := suite.chainA.GetSimApp().TransferKeeper.ExportGenesis(suite.chainA.GetContext()) suite.Require().Equal(types.PortID, genesis.PortId) @@ -71,7 +56,4 @@ func (suite *KeeperTestSuite) TestGenesis() { _, found := suite.chainA.GetSimApp().BankKeeper.GetDenomMetaData(suite.chainA.GetContext(), denom.IBCDenom()) suite.Require().True(found) } - - storedForwardedPackets := suite.chainA.GetSimApp().TransferKeeper.GetAllForwardedPackets(suite.chainA.GetContext()) - suite.Require().Equal(storedForwardedPackets, forwardPackets) } diff --git a/modules/apps/transfer/keeper/keeper.go b/modules/apps/transfer/keeper/keeper.go index f2b0933e777..b67df9b9584 100644 --- a/modules/apps/transfer/keeper/keeper.go +++ b/modules/apps/transfer/keeper/keeper.go @@ -20,9 +20,7 @@ import ( cmtbytes "github.com/cometbft/cometbft/libs/bytes" "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v9/modules/core/05-port/types" - host "github.com/cosmos/ibc-go/v9/modules/core/24-host" "github.com/cosmos/ibc-go/v9/modules/core/exported" ) @@ -299,90 +297,6 @@ func (k Keeper) IterateTokensInEscrow(ctx context.Context, storeprefix []byte, c } } -// setForwardedPacket sets the forwarded packet in the store. -func (k Keeper) setForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64, packet channeltypes.Packet) { - store := k.storeService.OpenKVStore(ctx) - bz := k.cdc.MustMarshal(&packet) - if err := store.Set(types.PacketForwardKey(portID, channelID, sequence), bz); err != nil { - panic(err) - } -} - -// GetForwardedPacket gets the forwarded packet from the store. -func (k Keeper) GetForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64) (channeltypes.Packet, bool) { - store := k.storeService.OpenKVStore(ctx) - bz, err := store.Get(types.PacketForwardKey(portID, channelID, sequence)) - if err != nil { - panic(err) - } - if bz == nil { - return channeltypes.Packet{}, false - } - - var storedPacket channeltypes.Packet - k.cdc.MustUnmarshal(bz, &storedPacket) - - return storedPacket, true -} - -// deleteForwardedPacket deletes the forwarded packet from the store. -func (k Keeper) deleteForwardedPacket(ctx context.Context, portID, channelID string, sequence uint64) { - store := k.storeService.OpenKVStore(ctx) - packetKey := types.PacketForwardKey(portID, channelID, sequence) - - if err := store.Delete(packetKey); err != nil { - panic(err) - } -} - -// getAllForwardedPackets gets all forward packets stored in state. -func (k Keeper) getAllForwardedPackets(ctx context.Context) []types.ForwardedPacket { - var packets []types.ForwardedPacket - k.iterateForwardedPackets(ctx, func(packet types.ForwardedPacket) bool { - packets = append(packets, packet) - return false - }) - - return packets -} - -// iterateForwardedPackets iterates over the forward packets in the store and performs a callback function. -func (k Keeper) iterateForwardedPackets(ctx context.Context, cb func(packet types.ForwardedPacket) bool) { - store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) - iterator := storetypes.KVStorePrefixIterator(store, types.ForwardedPacketKey) - - defer sdk.LogDeferred(k.Logger(ctx), func() error { return iterator.Close() }) - for ; iterator.Valid(); iterator.Next() { - var forwardPacket types.ForwardedPacket - k.cdc.MustUnmarshal(iterator.Value(), &forwardPacket.Packet) - - // Iterator key consists of types.ForwardedPacketKey/portID/channelID/sequence - parts := strings.Split(string(iterator.Key()), "/") - if len(parts) != 4 { - panic(errors.New("key path should always have 4 elements")) - } - if parts[0] != string(types.ForwardedPacketKey) { - panic(fmt.Errorf("key path does not start with expected prefix: %s", types.ForwardedPacketKey)) - } - - portID, channelID := parts[1], parts[2] - if err := host.PortIdentifierValidator(portID); err != nil { - panic(errors.New("port identifier validation failed while parsing forward key path")) - } - if err := host.ChannelIdentifierValidator(channelID); err != nil { - panic(errors.New("channel identifier validation failed while parsing forward key path")) - } - - forwardPacket.ForwardKey.Sequence = sdk.BigEndianToUint64([]byte(parts[3])) - forwardPacket.ForwardKey.ChannelId = channelID - forwardPacket.ForwardKey.PortId = portID - - if cb(forwardPacket) { - break - } - } -} - // IsBlockedAddr checks if the given address is allowed to send or receive tokens. // The module account is always allowed to send and receive tokens. func (k Keeper) IsBlockedAddr(addr sdk.AccAddress) bool { diff --git a/modules/apps/transfer/keeper/keeper_test.go b/modules/apps/transfer/keeper/keeper_test.go index 72dc5453733..e2f790c1882 100644 --- a/modules/apps/transfer/keeper/keeper_test.go +++ b/modules/apps/transfer/keeper/keeper_test.go @@ -18,9 +18,7 @@ import ( "github.com/cosmos/ibc-go/v9/modules/apps/transfer/keeper" "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" channelkeeper "github.com/cosmos/ibc-go/v9/modules/core/04-channel/keeper" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" ibctesting "github.com/cosmos/ibc-go/v9/testing" ) @@ -289,36 +287,6 @@ func (suite *KeeperTestSuite) TestGetAllDenomEscrows() { } } -func (suite *KeeperTestSuite) TestGetAllForwardedPackets() { - suite.SetupTest() - - // Store forward packets on transfer/channel-1 and transfer/channel-2 - for _, channelID := range []string{"channel-1", "channel-2"} { - // go across '10' to test numerical order - for sequence := uint64(5); sequence <= 15; sequence++ { - packet := channeltypes.NewPacket(ibctesting.MockPacketData, sequence, ibctesting.TransferPort, channelID, "", "", clienttypes.ZeroHeight(), 0) - suite.chainA.GetSimApp().TransferKeeper.SetForwardedPacket(suite.chainA.GetContext(), ibctesting.TransferPort, channelID, sequence, packet) - } - } - - packets := suite.chainA.GetSimApp().TransferKeeper.GetAllForwardedPackets(suite.chainA.GetContext()) - // Assert each packets is as expected - i := 0 - for _, channelID := range []string{"channel-1", "channel-2"} { - for sequence := uint64(5); sequence <= 15; sequence++ { - forwardedPacket := packets[i] - - expForwardKey := channeltypes.NewPacketID(ibctesting.TransferPort, channelID, sequence) - suite.Require().Equal(forwardedPacket.ForwardKey, expForwardKey) - - expPacket := channeltypes.NewPacket(ibctesting.MockPacketData, sequence, ibctesting.TransferPort, channelID, "", "", clienttypes.ZeroHeight(), 0) - suite.Require().Equal(forwardedPacket.Packet, expPacket) - - i++ - } - } -} - func (suite *KeeperTestSuite) TestParams() { testCases := []struct { name string diff --git a/modules/apps/transfer/keeper/mbt_relay_test.go b/modules/apps/transfer/keeper/mbt_relay_test.go index 8174b1960f5..10eb11fac54 100644 --- a/modules/apps/transfer/keeper/mbt_relay_test.go +++ b/modules/apps/transfer/keeper/mbt_relay_test.go @@ -150,16 +150,13 @@ func FungibleTokenPacketFromTla(packet TlaFungibleTokenPacket) FungibleTokenPack DestChannel: packet.DestChannel, DestPort: packet.DestPort, Data: types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: denom, - Amount: packet.Data.Amount, - }, + types.Token{ + Denom: denom, + Amount: packet.Data.Amount, }, AddressFromString(packet.Data.Sender), AddressFromString(packet.Data.Receiver), "", - ibctesting.EmptyForwardingPacketData, ), } } @@ -317,8 +314,8 @@ func (suite *KeeperTestSuite) TestModelBasedRelay() { for i, tlaTc := range tlaTestCases { tc := OnRecvPacketTestCaseFromTla(tlaTc) registerDenomFn := func() { - if !suite.chainB.GetSimApp().TransferKeeper.HasDenom(suite.chainB.GetContext(), tc.packet.Data.Tokens[0].Denom.Hash()) { - suite.chainB.GetSimApp().TransferKeeper.SetDenom(suite.chainB.GetContext(), tc.packet.Data.Tokens[0].Denom) + if !suite.chainB.GetSimApp().TransferKeeper.HasDenom(suite.chainB.GetContext(), tc.packet.Data.Token.Denom.Hash()) { + suite.chainB.GetSimApp().TransferKeeper.SetDenom(suite.chainB.GetContext(), tc.packet.Data.Token.Denom) } } @@ -342,10 +339,10 @@ func (suite *KeeperTestSuite) TestModelBasedRelay() { panic(errors.New("MBT failed to convert sender address")) } registerDenomFn() - denom := tc.packet.Data.Tokens[0].Denom.IBCDenom() + denom := tc.packet.Data.Token.Denom.IBCDenom() err = sdk.ValidateDenom(denom) if err == nil { - amount, ok := sdkmath.NewIntFromString(tc.packet.Data.Tokens[0].Amount) + amount, ok := sdkmath.NewIntFromString(tc.packet.Data.Token.Amount) if !ok { panic(errors.New("MBT failed to parse amount from string")) } @@ -353,19 +350,18 @@ func (suite *KeeperTestSuite) TestModelBasedRelay() { msg := types.NewMsgTransfer( tc.packet.SourcePort, tc.packet.SourceChannel, - sdk.NewCoins(sdk.NewCoin(denom, amount)), + sdk.NewCoin(denom, amount), sender.String(), tc.packet.Data.Receiver, suite.chainA.GetTimeoutHeight(), 0, // only use timeout height "", - nil, ) _, err = suite.chainB.GetSimApp().TransferKeeper.Transfer(suite.chainB.GetContext(), msg) } case "OnRecvPacket": - _, err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket( + err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket( suite.chainB.GetContext(), tc.packet.Data, packet.SourcePort, diff --git a/modules/apps/transfer/keeper/msg_server.go b/modules/apps/transfer/keeper/msg_server.go index 31105721c3c..01906cdd653 100644 --- a/modules/apps/transfer/keeper/msg_server.go +++ b/modules/apps/transfer/keeper/msg_server.go @@ -2,7 +2,6 @@ package keeper import ( "context" - "slices" errorsmod "cosmossdk.io/errors" @@ -30,13 +29,6 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types. return nil, err } - if msg.Forwarding.GetUnwind() { - msg, err = k.unwindHops(ctx, msg) - if err != nil { - return nil, err - } - } - channel, found := k.channelKeeper.GetChannel(ctx, msg.SourcePort, msg.SourceChannel) if !found { return nil, errorsmod.Wrapf(channeltypes.ErrChannelNotFound, "port ID (%s) channel ID (%s)", msg.SourcePort, msg.SourceChannel) @@ -47,43 +39,27 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types. return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "application version not found for source port: %s and source channel: %s", msg.SourcePort, msg.SourceChannel) } - coins := msg.GetCoins() - hops := msg.Forwarding.GetHops() - if appVersion == types.V1 { - // ics20-1 only supports a single coin, so if that is the current version, we must only process a single coin. - if len(coins) > 1 { - return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "cannot transfer multiple coins with %s", types.V1) - } + coin := msg.Token - // ics20-1 does not support forwarding, so if that is the current version, we must reject the transfer. - if len(hops) > 0 { - return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "cannot forward coins with %s", types.V1) + // Using types.UnboundedSpendLimit allows us to send the entire balance of a given denom. + if coin.Amount.Equal(types.UnboundedSpendLimit()) { + coin.Amount = k.BankKeeper.SpendableCoin(ctx, sender, coin.Denom).Amount + if coin.Amount.IsZero() { + return nil, errorsmod.Wrapf(types.ErrInvalidAmount, "empty spendable balance for %s", coin.Denom) } } - tokens := make([]types.Token, len(coins)) - - for i, coin := range coins { - // Using types.UnboundedSpendLimit allows us to send the entire balance of a given denom. - if coin.Amount.Equal(types.UnboundedSpendLimit()) { - coin.Amount = k.BankKeeper.SpendableCoin(ctx, sender, coin.Denom).Amount - if coin.Amount.IsZero() { - return nil, errorsmod.Wrapf(types.ErrInvalidAmount, "empty spendable balance for %s", coin.Denom) - } - } - - tokens[i], err = k.TokenFromCoin(ctx, coin) - if err != nil { - return nil, err - } + token, err := k.TokenFromCoin(ctx, coin) + if err != nil { + return nil, err } - if err := k.SendTransfer(ctx, msg.SourcePort, msg.SourceChannel, tokens, sender); err != nil { + if err := k.SendTransfer(ctx, msg.SourcePort, msg.SourceChannel, token, sender); err != nil { return nil, err } packetDataBytes, err := createPacketDataBytesFromVersion( - appVersion, sender.String(), msg.Receiver, msg.Memo, tokens, hops, + appVersion, sender.String(), msg.Receiver, msg.Memo, token, ) if err != nil { return nil, err @@ -94,13 +70,13 @@ func (k Keeper) Transfer(goCtx context.Context, msg *types.MsgTransfer) (*types. return nil, err } - events.EmitTransferEvent(ctx, sender.String(), msg.Receiver, tokens, msg.Memo, hops) + events.EmitTransferEvent(ctx, sender.String(), msg.Receiver, token, msg.Memo) destinationPort := channel.Counterparty.PortId destinationChannel := channel.Counterparty.ChannelId - telemetry.ReportTransfer(msg.SourcePort, msg.SourceChannel, destinationPort, destinationChannel, tokens) + telemetry.ReportTransfer(msg.SourcePort, msg.SourceChannel, destinationPort, destinationChannel, token) - k.Logger(ctx).Info("IBC fungible token transfer", "tokens", coins, "sender", msg.Sender, "receiver", msg.Receiver) + k.Logger(ctx).Info("IBC fungible token transfer", "token", coin, "sender", msg.Sender, "receiver", msg.Receiver) return &types.MsgTransferResponse{Sequence: sequence}, nil } @@ -116,58 +92,3 @@ func (k Keeper) UpdateParams(goCtx context.Context, msg *types.MsgUpdateParams) return &types.MsgUpdateParamsResponse{}, nil } - -// unwindHops unwinds the hops present in the tokens denomination and returns the message modified to reflect -// the unwound path to take. It assumes that only a single token is present (as this is verified in ValidateBasic) -// in the tokens list and ensures that the token is not native to the chain. -func (k Keeper) unwindHops(ctx sdk.Context, msg *types.MsgTransfer) (*types.MsgTransfer, error) { - unwindHops, err := k.getUnwindHops(ctx, msg.GetCoins()) - if err != nil { - return nil, err - } - - // Update message fields. - msg.SourcePort, msg.SourceChannel = unwindHops[0].PortId, unwindHops[0].ChannelId - msg.Forwarding.Hops = append(unwindHops[1:], msg.Forwarding.Hops...) - msg.Forwarding.Unwind = false - - // Message is validate again, this would only fail if hops now exceeds maximum allowed. - if err := msg.ValidateBasic(); err != nil { - return nil, err - } - return msg, nil -} - -// getUnwindHops returns the hops to be used during unwinding. If coins consists of more than -// one coin, all coins must have the exact same trace, else an error is returned. getUnwindHops -// also validates that the coins are not native to the chain. -func (k Keeper) getUnwindHops(ctx sdk.Context, coins sdk.Coins) ([]types.Hop, error) { - // Sanity: validation for MsgTransfer ensures coins are not empty. - if len(coins) == 0 { - return nil, errorsmod.Wrap(types.ErrInvalidForwarding, "coins cannot be empty") - } - - token, err := k.TokenFromCoin(ctx, coins[0]) - if err != nil { - return nil, err - } - - if token.Denom.IsNative() { - return nil, errorsmod.Wrap(types.ErrInvalidForwarding, "cannot unwind a native token") - } - - unwindTrace := token.Denom.Trace - for _, coin := range coins[1:] { - token, err := k.TokenFromCoin(ctx, coin) - if err != nil { - return nil, err - } - - // Implicitly ensures coin we're iterating over is not native. - if !slices.Equal(token.Denom.Trace, unwindTrace) { - return nil, errorsmod.Wrap(types.ErrInvalidForwarding, "cannot unwind tokens with different traces.") - } - } - - return unwindTrace, nil -} diff --git a/modules/apps/transfer/keeper/msg_server_test.go b/modules/apps/transfer/keeper/msg_server_test.go index 73b54850ebe..1903decfbf1 100644 --- a/modules/apps/transfer/keeper/msg_server_test.go +++ b/modules/apps/transfer/keeper/msg_server_test.go @@ -1,7 +1,6 @@ package keeper_test import ( - "encoding/json" "errors" "strings" @@ -12,7 +11,6 @@ import ( abci "github.com/cometbft/cometbft/abci/types" "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors" ibctesting "github.com/cosmos/ibc-go/v9/testing" @@ -23,22 +21,15 @@ func (suite *KeeperTestSuite) TestMsgTransfer() { var msg *types.MsgTransfer var path *ibctesting.Path - testCoins := ibctesting.TestCoins - testCases := []struct { name string malleate func() expError error }{ { - "success: multiple coins", - func() {}, - nil, - }, - { - "success: single coin", + "success", func() { - msg.Tokens = []sdk.Coin{ibctesting.TestCoin} + msg.Token = ibctesting.TestCoin }, nil, }, @@ -83,7 +74,7 @@ func (suite *KeeperTestSuite) TestMsgTransfer() { ibcerrors.ErrUnauthorized, }, { - "failure: bank send disabled for one of the denoms", + "failure: bank send disabled", func() { err := suite.chainA.GetSimApp().BankKeeper.SetParams(suite.chainA.GetContext(), banktypes.Params{ @@ -101,22 +92,6 @@ func (suite *KeeperTestSuite) TestMsgTransfer() { }, channeltypes.ErrChannelNotFound, }, - { - "failure: multidenom with ics20-1", - func() { - // explicitly set to ics20-1 which does not support multi-denom - path.EndpointA.UpdateChannel(func(channel *channeltypes.Channel) { channel.Version = types.V1 }) - }, - ibcerrors.ErrInvalidRequest, - }, - { - "failure: cannot unwind native tokens", - func() { - msg.Forwarding = types.NewForwarding(true) - msg.Tokens = []sdk.Coin{ibctesting.TestCoin} - }, - types.ErrInvalidForwarding, - }, } for _, tc := range testCases { @@ -131,12 +106,11 @@ func (suite *KeeperTestSuite) TestMsgTransfer() { msg = types.NewMsgTransfer( path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, - testCoins, + ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainB.GetTimeoutHeight(), 0, // only use timeout height "memo", - nil, ) // send some coins of the second denom from bank module to the sender account as well @@ -149,17 +123,7 @@ func (suite *KeeperTestSuite) TestMsgTransfer() { ctx := suite.chainA.GetContext() - var tokens []types.Token - for _, coin := range msg.GetCoins() { - token, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(ctx, coin) - suite.Require().NoError(err) - tokens = append(tokens, token) - } - - tokensBz, err := json.Marshal(types.Tokens(tokens)) - suite.Require().NoError(err) - - forwardingHopsBz, err := json.Marshal(msg.Forwarding.GetHops()) + token, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(ctx, msg.Token) suite.Require().NoError(err) res, err := suite.chainA.GetSimApp().TransferKeeper.Transfer(ctx, msg) @@ -172,9 +136,9 @@ func (suite *KeeperTestSuite) TestMsgTransfer() { sdk.NewEvent(types.EventTypeTransfer, sdk.NewAttribute(types.AttributeKeySender, msg.Sender), sdk.NewAttribute(types.AttributeKeyReceiver, msg.Receiver), - sdk.NewAttribute(types.AttributeKeyTokens, string(tokensBz)), + sdk.NewAttribute(types.AttributeKeyDenom, token.Denom.Path()), + sdk.NewAttribute(types.AttributeKeyAmount, msg.Token.Amount.String()), sdk.NewAttribute(types.AttributeKeyMemo, msg.Memo), - sdk.NewAttribute(types.AttributeKeyForwardingHops, string(forwardingHopsBz)), ), sdk.NewEvent( sdk.EventTypeMessage, @@ -244,161 +208,3 @@ func (suite *KeeperTestSuite) TestUpdateParams() { }) } } - -func (suite *KeeperTestSuite) TestUnwindHops() { - var msg *types.MsgTransfer - var path *ibctesting.Path - denom := types.NewDenom(ibctesting.TestCoin.Denom, types.NewHop(ibctesting.MockPort, "channel-0"), types.NewHop(ibctesting.MockPort, "channel-1")) - coins := sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) - testCases := []struct { - name string - malleate func() - assertResult func(modified *types.MsgTransfer, err error) - }{ - { - "success", - func() { - suite.chainA.GetSimApp().TransferKeeper.SetDenom(suite.chainA.GetContext(), denom) - }, - func(modified *types.MsgTransfer, err error) { - suite.Require().NoError(err, "got unexpected error from unwindHops") - msg.SourceChannel = denom.Trace[0].PortId - msg.SourcePort = denom.Trace[0].ChannelId - msg.Forwarding = types.NewForwarding(false, types.NewHop(denom.Trace[1].PortId, denom.Trace[1].ChannelId)) - suite.Require().Equal(*msg, *modified, "expected msg and modified msg are different") - }, - }, - { - "success: multiple unwind hops", - func() { - denom.Trace = append(denom.Trace, types.NewHop(ibctesting.MockPort, "channel-2"), types.NewHop(ibctesting.MockPort, "channel-3")) - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) - suite.chainA.GetSimApp().TransferKeeper.SetDenom(suite.chainA.GetContext(), denom) - msg.Tokens = coins - }, - func(modified *types.MsgTransfer, err error) { - suite.Require().NoError(err, "got unexpected error from unwindHops") - msg.SourceChannel = denom.Trace[0].PortId - msg.SourcePort = denom.Trace[0].ChannelId - msg.Forwarding = types.NewForwarding(false, - types.NewHop(denom.Trace[3].PortId, denom.Trace[3].ChannelId), - types.NewHop(denom.Trace[2].PortId, denom.Trace[2].ChannelId), - types.NewHop(denom.Trace[1].PortId, denom.Trace[1].ChannelId), - ) - suite.Require().Equal(*msg, *modified, "expected msg and modified msg are different") - }, - }, - { - "success - unwind hops are added to existing hops", - func() { - suite.chainA.GetSimApp().TransferKeeper.SetDenom(suite.chainA.GetContext(), denom) - msg.Forwarding = types.NewForwarding(true, types.NewHop(ibctesting.MockPort, "channel-2")) - }, - func(modified *types.MsgTransfer, err error) { - suite.Require().NoError(err, "got unexpected error from unwindHops") - msg.SourceChannel = denom.Trace[0].PortId - msg.SourcePort = denom.Trace[0].ChannelId - msg.Forwarding = types.NewForwarding(false, - types.NewHop(denom.Trace[1].PortId, denom.Trace[1].ChannelId), - types.NewHop(ibctesting.MockPort, "channel-2"), - ) - suite.Require().Equal(*msg, *modified, "expected msg and modified msg are different") - }, - }, - { - "success: multiple denoms with equal traces", - func() { - coins = []sdk.Coin{} - for _, base := range []string{sdk.DefaultBondDenom, ibctesting.SecondaryDenom} { - denom := types.NewDenom(base, types.NewHop(ibctesting.MockPort, "channel-1")) - suite.chainA.GetSimApp().TransferKeeper.SetDenom(suite.chainA.GetContext(), denom) - - coins = append(coins, sdk.NewCoin(denom.IBCDenom(), defaultAmount)) - } - msg.Tokens = coins - }, - func(modified *types.MsgTransfer, err error) { - suite.Require().NoError(err) - - msg.SourceChannel = denom.Trace[0].PortId - msg.SourcePort = denom.Trace[0].ChannelId - msg.Forwarding = types.NewForwarding(false) - suite.Require().Equal(*msg, *modified, "expected msg and modified msg are different") - }, - }, - { - "failure: no denom set on keeper", - func() {}, - func(modified *types.MsgTransfer, err error) { - suite.Require().ErrorIs(err, types.ErrDenomNotFound) - }, - }, - { - "failure: validateBasic() fails due to invalid channelID", - func() { - denom.Trace[0].ChannelId = "channel/0" - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) - msg.Tokens = coins - suite.chainA.GetSimApp().TransferKeeper.SetDenom(suite.chainA.GetContext(), denom) - }, - func(modified *types.MsgTransfer, err error) { - suite.Require().ErrorContains(err, "invalid source channel ID") - }, - }, - { - "failure: denom is native", - func() { - denom.Trace = nil - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) - msg.Tokens = coins - suite.chainA.GetSimApp().TransferKeeper.SetDenom(suite.chainA.GetContext(), denom) - }, - func(modified *types.MsgTransfer, err error) { - suite.Require().ErrorIs(err, types.ErrInvalidForwarding) - }, - }, - { - "failure: multiple coins with unwind, trace path does not match", - func() { - denom.Trace = append(denom.Trace, types.NewHop(ibctesting.MockPort, "channel-1")) - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) - suite.chainA.GetSimApp().TransferKeeper.SetDenom(suite.chainA.GetContext(), denom) - - denom.Trace = append(denom.Trace, types.NewHop(ibctesting.MockPort, "channel-2"), types.NewHop(ibctesting.MockPort, "channel-3")) - suite.chainA.GetSimApp().TransferKeeper.SetDenom(suite.chainA.GetContext(), denom) - coins = append(coins, sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) - - msg.Tokens = coins - }, - func(modified *types.MsgTransfer, err error) { - suite.Require().ErrorIs(err, types.ErrInvalidForwarding) - suite.Require().ErrorContains(err, "cannot unwind tokens with different traces") - }, - }, - } - - 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, - coins, - suite.chainA.SenderAccount.GetAddress().String(), - suite.chainB.SenderAccount.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), - "memo", - types.NewForwarding(true), - ) - - tc.malleate() - gotMsg, err := suite.chainA.GetSimApp().TransferKeeper.UnwindHops(suite.chainA.GetContext(), msg) - tc.assertResult(gotMsg, err) - }) - } -} diff --git a/modules/apps/transfer/keeper/relay.go b/modules/apps/transfer/keeper/relay.go index 768eacd206a..7824619f8ad 100644 --- a/modules/apps/transfer/keeper/relay.go +++ b/modules/apps/transfer/keeper/relay.go @@ -11,7 +11,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/events" - internaltypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/types" "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors" @@ -53,7 +52,7 @@ func (k Keeper) SendTransfer( ctx sdk.Context, sourcePort, sourceChannel string, - tokens types.Tokens, + token types.Token, sender sdk.AccAddress, ) error { if !k.GetParams(ctx).SendEnabled { @@ -64,47 +63,43 @@ func (k Keeper) SendTransfer( return errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "%s is not allowed to send funds", sender) } - for _, token := range tokens { - coin, err := token.ToCoin() - if err != nil { + coin, err := token.ToCoin() + if err != nil { + return err + } + + if err := k.BankKeeper.IsSendEnabledCoins(ctx, coin); err != nil { + return errorsmod.Wrap(types.ErrSendDisabled, err.Error()) + } + + // NOTE: SendTransfer simply sends the denomination as it exists on its own + // chain inside the packet data. The receiving chain will perform denom + // prefixing as necessary. + + // if the denom is prefixed by the port and channel on which we are sending + // the token, then we must be returning the token back to the chain they originated from + if token.Denom.HasPrefix(sourcePort, sourceChannel) { + // transfer the coins to the module account and burn them + if err := k.BankKeeper.SendCoinsFromAccountToModule( + ctx, sender, types.ModuleName, sdk.NewCoins(coin), + ); err != nil { return err } - if err := k.BankKeeper.IsSendEnabledCoins(ctx, coin); err != nil { - return errorsmod.Wrap(types.ErrSendDisabled, err.Error()) + if err := k.BankKeeper.BurnCoins( + ctx, types.ModuleName, sdk.NewCoins(coin), + ); err != nil { + // NOTE: should not happen as the module account was + // retrieved on the step above and it has enough balance + // to burn. + panic(fmt.Errorf("cannot burn coins after a successful send to a module account: %v", err)) } - - // NOTE: SendTransfer simply sends the denomination as it exists on its own - // chain inside the packet data. The receiving chain will perform denom - // prefixing as necessary. - - // if the denom is prefixed by the port and channel on which we are sending - // the token, then we must be returning the token back to the chain they originated from - if token.Denom.HasPrefix(sourcePort, sourceChannel) { - // transfer the coins to the module account and burn them - if err := k.BankKeeper.SendCoinsFromAccountToModule( - ctx, sender, types.ModuleName, sdk.NewCoins(coin), - ); err != nil { - return err - } - - if err := k.BankKeeper.BurnCoins( - ctx, types.ModuleName, sdk.NewCoins(coin), - ); err != nil { - // NOTE: should not happen as the module account was - // retrieved on the step above and it has enough balance - // to burn. - panic(fmt.Errorf("cannot burn coins after a successful send to a module account: %v", err)) - } - } else { - // obtain the escrow address for the source channel end - escrowAddress := types.GetEscrowAddress(sourcePort, sourceChannel) - if err := k.EscrowCoin(ctx, sender, escrowAddress, coin); err != nil { - return err - } + } else { + // obtain the escrow address for the source channel end + escrowAddress := types.GetEscrowAddress(sourcePort, sourceChannel) + if err := k.EscrowCoin(ctx, sender, escrowAddress, coin); err != nil { + return err } - - tokens = append(tokens, token) } return nil @@ -116,9 +111,6 @@ func (k Keeper) SendTransfer( // and sent to the receiving address. Otherwise if the sender chain is sending // back tokens this chain originally transferred to it, the tokens are // unescrowed and sent to the receiving address. -// -// In the case of packet forwarding, the packet is sent on the next hop as specified -// in the packet's ForwardingPacketData. func (k Keeper) OnRecvPacket( ctx context.Context, data types.FungibleTokenPacketDataV2, @@ -126,96 +118,91 @@ func (k Keeper) OnRecvPacket( sourceChannel string, destPort string, destChannel string, -) (sdk.Coins, error) { +) error { // validate packet data upon receiving if err := data.ValidateBasic(); err != nil { - return nil, errorsmod.Wrapf(err, "error validating ICS-20 transfer packet data") + return errorsmod.Wrapf(err, "error validating ICS-20 transfer packet data") } if !k.GetParams(ctx).ReceiveEnabled { - return nil, types.ErrReceiveDisabled + return types.ErrReceiveDisabled } - receiver, err := k.getReceiverFromPacketData(data) + receiver, err := sdk.AccAddressFromBech32(data.Receiver) if err != nil { - return nil, err + return errorsmod.Wrapf(ibcerrors.ErrInvalidAddress, "failed to decode receiver address: %s", data.Receiver) } if k.IsBlockedAddr(receiver) { - return nil, errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "%s is not allowed to receive funds", receiver) + return errorsmod.Wrapf(ibcerrors.ErrUnauthorized, "%s is not allowed to receive funds", receiver) + } + + token := data.Token + + // parse the transfer amount + transferAmount, ok := sdkmath.NewIntFromString(token.Amount) + if !ok { + return errorsmod.Wrapf(types.ErrInvalidAmount, "unable to parse transfer amount: %s", token.Amount) } - receivedCoins := make(sdk.Coins, 0, len(data.Tokens)) - for _, token := range data.Tokens { - // parse the transfer amount - transferAmount, ok := sdkmath.NewIntFromString(token.Amount) - if !ok { - return nil, errorsmod.Wrapf(types.ErrInvalidAmount, "unable to parse transfer amount: %s", token.Amount) + // This is the prefix that would have been prefixed to the denomination + // on sender chain IF and only if the token originally came from the + // receiving chain. + // + // NOTE: We use SourcePort and SourceChannel here, because the counterparty + // chain would have prefixed with DestPort and DestChannel when originally + // receiving this token. + if token.Denom.HasPrefix(sourcePort, sourceChannel) { + // sender chain is not the source, unescrow tokens + + // remove prefix added by sender chain + token.Denom.Trace = token.Denom.Trace[1:] + + coin := sdk.NewCoin(token.Denom.IBCDenom(), transferAmount) + + escrowAddress := types.GetEscrowAddress(destPort, destChannel) + if err := k.UnescrowCoin(ctx, escrowAddress, receiver, coin); err != nil { + return err } + } else { + // sender chain is the source, mint vouchers + + // since SendPacket did not prefix the denomination, we must add the destination port and channel to the trace + trace := []types.Hop{types.NewHop(destPort, destChannel)} + token.Denom.Trace = append(trace, token.Denom.Trace...) - // This is the prefix that would have been prefixed to the denomination - // on sender chain IF and only if the token originally came from the - // receiving chain. - // - // NOTE: We use SourcePort and SourceChannel here, because the counterparty - // chain would have prefixed with DestPort and DestChannel when originally - // receiving this token. - if token.Denom.HasPrefix(sourcePort, sourceChannel) { - // sender chain is not the source, unescrow tokens - - // remove prefix added by sender chain - token.Denom.Trace = token.Denom.Trace[1:] - - coin := sdk.NewCoin(token.Denom.IBCDenom(), transferAmount) - - escrowAddress := types.GetEscrowAddress(destPort, destChannel) - if err := k.UnescrowCoin(ctx, escrowAddress, receiver, coin); err != nil { - return nil, err - } - - // Appending token. The new denom has been computed - receivedCoins = append(receivedCoins, coin) - } else { - // sender chain is the source, mint vouchers - - // since SendPacket did not prefix the denomination, we must add the destination port and channel to the trace - trace := []types.Hop{types.NewHop(destPort, destChannel)} - token.Denom.Trace = append(trace, token.Denom.Trace...) - - if !k.HasDenom(ctx, token.Denom.Hash()) { - k.SetDenom(ctx, token.Denom) - } - - voucherDenom := token.Denom.IBCDenom() - if !k.BankKeeper.HasDenomMetaData(ctx, voucherDenom) { - k.SetDenomMetadata(ctx, token.Denom) - } - - events.EmitDenomEvent(ctx, token) - - voucher := sdk.NewCoin(voucherDenom, transferAmount) - - // mint new tokens if the source of the transfer is the same chain - if err := k.BankKeeper.MintCoins( - ctx, types.ModuleName, sdk.NewCoins(voucher), - ); err != nil { - return nil, errorsmod.Wrap(err, "failed to mint IBC tokens") - } - - // send to receiver - moduleAddr := k.AuthKeeper.GetModuleAddress(types.ModuleName) - if err := k.BankKeeper.SendCoins( - ctx, moduleAddr, receiver, sdk.NewCoins(voucher), - ); err != nil { - return nil, errorsmod.Wrapf(err, "failed to send coins to receiver %s", receiver.String()) - } - - receivedCoins = append(receivedCoins, voucher) + if !k.HasDenom(ctx, token.Denom.Hash()) { + k.SetDenom(ctx, token.Denom) } + + voucherDenom := token.Denom.IBCDenom() + if !k.BankKeeper.HasDenomMetaData(ctx, voucherDenom) { + k.SetDenomMetadata(ctx, token.Denom) + } + + events.EmitDenomEvent(ctx, token) + + voucher := sdk.NewCoin(voucherDenom, transferAmount) + + // mint new tokens if the source of the transfer is the same chain + if err := k.BankKeeper.MintCoins( + ctx, types.ModuleName, sdk.NewCoins(voucher), + ); err != nil { + return errorsmod.Wrap(err, "failed to mint IBC tokens") + } + + // send to receiver + moduleAddr := k.AuthKeeper.GetModuleAddress(types.ModuleName) + if err := k.BankKeeper.SendCoins( + ctx, moduleAddr, receiver, sdk.NewCoins(voucher), + ); err != nil { + return errorsmod.Wrapf(err, "failed to send coins to receiver %s", receiver.String()) + } + } // The ibc_module.go module will return the proper ack. - return receivedCoins, nil + return nil } // OnAcknowledgementPacket responds to the success or failure of a packet acknowledgment @@ -245,40 +232,6 @@ func (k Keeper) OnAcknowledgementPacket( } } -// HandleForwardedPacketAcknowledgement processes an acknowledgement for a packet that was sent from the chain as an intermediate. -// -// If the acknowledgement was a success, a successful acknowledgement is written -// for the forwarded packet. Otherwise, if the acknowledgement failed, after refunding the sender, the -// tokens of the forwarded packet that were received are in turn either refunded or burned. -func (k Keeper) HandleForwardedPacketAcknowledgement( - ctx context.Context, - packet channeltypes.Packet, - forwardedPacket channeltypes.Packet, - data types.FungibleTokenPacketDataV2, - ack channeltypes.Acknowledgement, -) error { - var forwardAck channeltypes.Acknowledgement - - switch ack.Response.(type) { - case *channeltypes.Acknowledgement_Result: - // Write a successful async ack for the forwardedPacket - forwardAck = channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - case *channeltypes.Acknowledgement_Error: - // the forwarded packet has failed, thus the funds have been refunded to the intermediate address. - // we must revert the changes that came from successfully receiving the tokens on our chain - // before propagating the error acknowledgement back to original sender chain - if err := k.revertForwardedPacket(ctx, forwardedPacket, data); err != nil { - return err - } - - forwardAck = internaltypes.NewForwardErrorAcknowledgement(packet, ack) - default: - return errorsmod.Wrapf(ibcerrors.ErrInvalidType, "expected one of [%T, %T], got %T", channeltypes.Acknowledgement_Result{}, channeltypes.Acknowledgement_Error{}, ack.Response) - } - - return k.acknowledgeForwardedPacket(ctx, forwardedPacket, packet, forwardAck) -} - // OnTimeoutPacket processes a transfer packet timeout by refunding the tokens to the sender func (k Keeper) OnTimeoutPacket( ctx context.Context, @@ -289,19 +242,8 @@ func (k Keeper) OnTimeoutPacket( return k.refundPacketTokens(ctx, sourcePort, sourceChannel, data) } -// HandleForwardedTimeout processes a timeout packet that was sent from the chain as an intermediate. -// The packet is reverted and the tokens are refunded to the sender. -func (k Keeper) HandleForwardedPacketTimeout(ctx context.Context, packet channeltypes.Packet, forwardedPacket channeltypes.Packet, data types.FungibleTokenPacketDataV2) error { - if err := k.revertForwardedPacket(ctx, forwardedPacket, data); err != nil { - return err - } - - forwardAck := internaltypes.NewForwardTimeoutAcknowledgement(packet) - return k.acknowledgeForwardedPacket(ctx, forwardedPacket, packet, forwardAck) -} - -// refundPacketTokens will unescrow and send back the tokens back to sender -// if the sending chain was the source chain. Otherwise, the sent tokens +// refundPacketTokens will unescrow and send back the token back to sender +// if the sending chain was the source chain. Otherwise, the sent token // were burnt in the original send so new tokens are minted and sent to // the sending address. func (k Keeper) refundPacketTokens( @@ -324,29 +266,28 @@ func (k Keeper) refundPacketTokens( escrowAddress := types.GetEscrowAddress(sourcePort, sourceChannel) moduleAccountAddr := k.AuthKeeper.GetModuleAddress(types.ModuleName) - for _, token := range data.Tokens { - coin, err := token.ToCoin() - if err != nil { + token := data.Token + coin, err := token.ToCoin() + if err != nil { + return err + } + + // if the token we must refund is prefixed by the source port and channel + // then the tokens were burnt when the packet was sent and we must mint new tokens + if token.Denom.HasPrefix(sourcePort, sourceChannel) { + // mint vouchers back to sender + if err := k.BankKeeper.MintCoins( + ctx, types.ModuleName, sdk.NewCoins(coin), + ); err != nil { return err } - // if the token we must refund is prefixed by the source port and channel - // then the tokens were burnt when the packet was sent and we must mint new tokens - if token.Denom.HasPrefix(sourcePort, sourceChannel) { - // mint vouchers back to sender - if err := k.BankKeeper.MintCoins( - ctx, types.ModuleName, sdk.NewCoins(coin), - ); err != nil { - return err - } - - if err := k.BankKeeper.SendCoins(ctx, moduleAccountAddr, sender, sdk.NewCoins(coin)); err != nil { - panic(fmt.Errorf("unable to send coins from module to account despite previously minting coins to module account: %v", err)) - } - } else { - if err := k.UnescrowCoin(ctx, escrowAddress, sender, coin); err != nil { - return err - } + if err := k.BankKeeper.SendCoins(ctx, moduleAccountAddr, sender, sdk.NewCoins(coin)); err != nil { + panic(fmt.Errorf("unable to send coins from module to account despite previously minting coins to module account: %v", err)) + } + } else { + if err := k.UnescrowCoin(ctx, escrowAddress, sender, coin); err != nil { + return err } } @@ -418,36 +359,15 @@ func (k Keeper) TokenFromCoin(ctx sdk.Context, coin sdk.Coin) (types.Token, erro } // createPacketDataBytesFromVersion creates the packet data bytes to be sent based on the application version. -func createPacketDataBytesFromVersion(appVersion, sender, receiver, memo string, tokens types.Tokens, hops []types.Hop) ([]byte, error) { +func createPacketDataBytesFromVersion(appVersion, sender, receiver, memo string, token types.Token) ([]byte, error) { switch appVersion { case types.V1: - // Sanity check, tokens must always be of length 1 if using app version V1. - if len(tokens) != 1 { - return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "cannot transfer multiple coins with %s", types.V1) - } - - token := tokens[0] packetData := types.NewFungibleTokenPacketData(token.Denom.Path(), token.Amount, sender, receiver, memo) if err := packetData.ValidateBasic(); err != nil { return nil, errorsmod.Wrapf(err, "failed to validate %s packet data", types.V1) } - return packetData.GetBytes(), nil - case types.V2: - // If forwarding is needed, move memo to forwarding packet data and set packet.Memo to empty string. - var forwardingPacketData types.ForwardingPacketData - if len(hops) > 0 { - forwardingPacketData = types.NewForwardingPacketData(memo, hops...) - memo = "" - } - - packetData := types.NewFungibleTokenPacketDataV2(tokens, sender, receiver, memo, forwardingPacketData) - - if err := packetData.ValidateBasic(); err != nil { - return nil, errorsmod.Wrapf(err, "failed to validate %s packet data", types.V2) - } - return packetData.GetBytes(), nil default: return nil, errorsmod.Wrapf(types.ErrInvalidVersion, "app version must be one of %s", types.SupportedVersions) diff --git a/modules/apps/transfer/keeper/relay_forwarding_test.go b/modules/apps/transfer/keeper/relay_forwarding_test.go deleted file mode 100644 index bdf226f4e8d..00000000000 --- a/modules/apps/transfer/keeper/relay_forwarding_test.go +++ /dev/null @@ -1,1424 +0,0 @@ -package keeper_test - -import ( - "fmt" - "testing" - "time" - - "github.com/cosmos/gogoproto/proto" - testifysuite "github.com/stretchr/testify/suite" - - sdkmath "cosmossdk.io/math" - - sdk "github.com/cosmos/cosmos-sdk/types" - - abci "github.com/cometbft/cometbft/abci/types" - - internaltypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/internal/types" - "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v9/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" - ibctesting "github.com/cosmos/ibc-go/v9/testing" -) - -const ( - escrow amountType = iota - balance -) - -type ForwardingTestSuite struct { - testifysuite.Suite - - coordinator *ibctesting.Coordinator - - // testing chains used for convenience and readability - chainA *ibctesting.TestChain - chainB *ibctesting.TestChain - chainC *ibctesting.TestChain - chainD *ibctesting.TestChain -} - -type amountType int - -func TestForwardingTestSuite(t *testing.T) { - testifysuite.Run(t, new(ForwardingTestSuite)) -} - -func (suite *ForwardingTestSuite) SetupTest() { - suite.coordinator = ibctesting.NewCoordinator(suite.T(), 4) - - suite.chainA = suite.coordinator.GetChain(ibctesting.GetChainID(1)) - suite.chainB = suite.coordinator.GetChain(ibctesting.GetChainID(2)) - suite.chainC = suite.coordinator.GetChain(ibctesting.GetChainID(3)) - suite.chainD = suite.coordinator.GetChain(ibctesting.GetChainID(4)) -} - -func (suite *ForwardingTestSuite) setupForwardingPaths() (pathAtoB, pathBtoC *ibctesting.Path) { - pathAtoB = ibctesting.NewTransferPath(suite.chainA, suite.chainB) - pathBtoC = ibctesting.NewTransferPath(suite.chainB, suite.chainC) - pathAtoB.Setup() - pathBtoC.Setup() - - return pathAtoB, pathBtoC -} - -// TestStoredForwardedPacketAndEscrowAfterFirstHop tests that the forwarded packet -// from chain A to chain B is stored after when the packet is received on chain B -// and then forwarded to chain C, and checks the balance of the escrow accounts -// in chain A nad B. -func (suite *ForwardingTestSuite) TestStoredForwardedPacketAndEscrowAfterFirstHop() { - /* - Given the following topology: - chain A (channel 0) -> (channel-0) chain B (channel-1) -> (channel-0) chain A - stake transfer/channel-0/stake transfer/channel-0/transfer/channel-0/stake - We want to trigger: - 1. A sends B over channel-0. - 2. Receive on B. - At this point we want to assert: - A: escrowA = amount,stake AND packet A to B is stored in forwarded packet - B: escrowB = amount,transfer/channel-0/stake - */ - - amount := sdkmath.NewInt(100) - pathAtoB, pathBtoC := suite.setupForwardingPaths() - - coin := ibctesting.TestCoin - sender := suite.chainA.SenderAccounts[0].SenderAccount - receiver := suite.chainC.SenderAccounts[0].SenderAccount - forwarding := types.NewForwarding(false, types.NewHop( - pathBtoC.EndpointA.ChannelConfig.PortID, - pathBtoC.EndpointA.ChannelID, - )) - - transferMsg := types.NewMsgTransfer( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(coin), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), "", - forwarding, - ) - result, err := suite.chainA.SendMsgs(transferMsg) - suite.Require().NoError(err) // message committed - - // parse the packet from result events and recv packet on chainB - packet, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packet) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packet) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - forwardedPacket, found := suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, packet.Sequence) - suite.Require().True(found) - suite.Require().Equal(packet, forwardedPacket) - - suite.assertAmountOnChain(suite.chainA, escrow, amount, sdk.DefaultBondDenom) - - // denom path: transfer/channel-0 - denom := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - suite.assertAmountOnChain(suite.chainB, escrow, amount, denom.IBCDenom()) -} - -// TestSuccessfulForward tests a successful transfer from A to C through B. -func (suite *ForwardingTestSuite) TestSuccessfulForward() { - /* - Given the following topology: - chain A (channel 0) -> (channel-0) chain B (channel-1) -> (channel-0) chain C - stake transfer/channel-0/stake transfer/channel-0/transfer/channel-0/stake - We want to trigger: - 1. A sends B over channel-0. - 2. Receive on B. - 2.1 B sends C over channel-1 - 3. Receive on C. - At this point we want to assert: - A: escrowA = amount,stake - B: escrowB = amount,transfer/channel-0/denom - C: finalReceiver = amount,transfer/channel-0/transfer/channel-0/denom - */ - - amount := sdkmath.NewInt(100) - - pathAtoB, pathBtoC := suite.setupForwardingPaths() - - coinOnA := ibctesting.TestCoin - sender := suite.chainA.SenderAccounts[0].SenderAccount - receiver := suite.chainC.SenderAccounts[0].SenderAccount - forwarding := types.NewForwarding(false, types.NewHop( - pathBtoC.EndpointA.ChannelConfig.PortID, - pathBtoC.EndpointA.ChannelID, - )) - - transferMsg := types.NewMsgTransfer( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(coinOnA), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), "", - forwarding, - ) - - result, err := suite.chainA.SendMsgs(transferMsg) - suite.Require().NoError(err) // message committed - - // parse the packet from result events and recv packet on chainB - packetFromAtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromAtoB) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packetFromAtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that Escrow A has amount - suite.assertAmountOnChain(suite.chainA, escrow, amount, sdk.DefaultBondDenom) - - // denom path: transfer/channel-0 - denom := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - suite.assertAmountOnChain(suite.chainB, escrow, amount, denom.IBCDenom()) - - packetFromBtoC, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoC) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - // B should have stored the forwarded packet. - _, found := suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), packetFromBtoC.SourcePort, packetFromBtoC.SourceChannel, packetFromBtoC.Sequence) - suite.Require().True(found, "Chain B should have stored the forwarded packet") - - result, err = pathBtoC.EndpointB.RecvPacketWithResult(packetFromBtoC) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // transfer/channel-0/transfer/channel-0/denom - // Check that the final receiver has received the expected tokens. - denomABC := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID), types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - // Check that the final receiver has received the expected tokens. - suite.assertAmountOnChain(suite.chainC, balance, amount, denomABC.IBCDenom()) - - successAck := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - successAckBz := channeltypes.CommitAcknowledgement(successAck.Acknowledgement()) - ackOnC := suite.chainC.GetAcknowledgement(packetFromBtoC) - suite.Require().Equal(successAckBz, ackOnC) - - // Ack back to B - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointA.AcknowledgePacket(packetFromBtoC, successAck.Acknowledgement()) - suite.Require().NoError(err) - - ackOnB := suite.chainB.GetAcknowledgement(packetFromAtoB) - suite.Require().Equal(successAckBz, ackOnB) - - // B should now have deleted the forwarded packet. - _, found = suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), packetFromBtoC.SourcePort, packetFromBtoC.SourceChannel, packetFromBtoC.Sequence) - suite.Require().False(found, "Chain B should have deleted the forwarded packet") - - // Ack back to A - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathAtoB.EndpointA.AcknowledgePacket(packetFromAtoB, successAck.Acknowledgement()) - suite.Require().NoError(err) -} - -// TestSuccessfulForwardWithMemo tests a successful transfer from A to C through B with a memo that should arrive at C. -func (suite *ForwardingTestSuite) TestSuccessfulForwardWithMemo() { - /* - Given the following topology: - chain A (channel 0) -> (channel-0) chain B (channel-1) -> (channel-0) chain C - stake transfer/channel-0/stake transfer/channel-0/transfer/channel-0/stake - We want to trigger: - 1. A sends B over channel-0. - 2. Receive on B. - 2.1 B sends C over channel-1 - 3. Receive on C. - At this point we want to assert: - A: escrowA = amount,stake - B: escrowB = amount,transfer/channel-0/denom - C: finalReceiver = amount,transfer/channel-0/transfer/channel-0/denom,memo - */ - - amount := sdkmath.NewInt(100) - testMemo := "test forwarding memo" - - pathAtoB, pathBtoC := suite.setupForwardingPaths() - - coinOnA := ibctesting.TestCoin - sender := suite.chainA.SenderAccounts[0].SenderAccount - receiver := suite.chainC.SenderAccounts[0].SenderAccount - forwarding := types.NewForwarding(false, types.NewHop( - pathBtoC.EndpointA.ChannelConfig.PortID, - pathBtoC.EndpointA.ChannelID, - )) - - transferMsg := types.NewMsgTransfer( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(coinOnA), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), - testMemo, - forwarding, - ) - - result, err := suite.chainA.SendMsgs(transferMsg) - suite.Require().NoError(err) // message committed - - // parse the packet from result events and recv packet on chainB - packetFromAtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromAtoB) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - // Check that the memo is stored correctly in the packet sent from A - var tokenPacketOnA types.FungibleTokenPacketDataV2 - err = proto.Unmarshal(packetFromAtoB.Data, &tokenPacketOnA) - suite.Require().NoError(err) - suite.Require().Equal("", tokenPacketOnA.Memo) - suite.Require().Equal(testMemo, tokenPacketOnA.Forwarding.DestinationMemo) - - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packetFromAtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that Escrow A has amount - suite.assertAmountOnChain(suite.chainA, escrow, amount, sdk.DefaultBondDenom) - - // denom path: transfer/channel-0 - denom := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - suite.assertAmountOnChain(suite.chainB, escrow, amount, denom.IBCDenom()) - - packetFromBtoC, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoC) - - // Check that the memo is stored correctly in the packet sent from B - var tokenPacketOnB types.FungibleTokenPacketDataV2 - err = proto.Unmarshal(packetFromBtoC.Data, &tokenPacketOnB) - suite.Require().NoError(err) - suite.Require().Equal(testMemo, tokenPacketOnB.Memo) - suite.Require().Equal("", tokenPacketOnB.Forwarding.DestinationMemo) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - // B should have stored the forwarded packet. - _, found := suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), packetFromBtoC.SourcePort, packetFromBtoC.SourceChannel, packetFromBtoC.Sequence) - suite.Require().True(found, "Chain B should have stored the forwarded packet") - - result, err = pathBtoC.EndpointB.RecvPacketWithResult(packetFromBtoC) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - packetOnC, err := ibctesting.ParseRecvPacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetOnC) - - // Check that the memo is stored directly in the memo field on C - var tokenPacketOnC types.FungibleTokenPacketDataV2 - err = proto.Unmarshal(packetOnC.Data, &tokenPacketOnC) - suite.Require().NoError(err) - suite.Require().Equal("", tokenPacketOnC.Forwarding.DestinationMemo) - suite.Require().Equal(testMemo, tokenPacketOnC.Memo) - - // transfer/channel-0/transfer/channel-0/denom - // Check that the final receiver has received the expected tokens. - denomABC := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID), types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - // Check that the final receiver has received the expected tokens. - suite.assertAmountOnChain(suite.chainC, balance, amount, denomABC.IBCDenom()) - - successAck := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - successAckBz := channeltypes.CommitAcknowledgement(successAck.Acknowledgement()) - ackOnC := suite.chainC.GetAcknowledgement(packetFromBtoC) - suite.Require().Equal(successAckBz, ackOnC) - - // Ack back to B - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointA.AcknowledgePacket(packetFromBtoC, successAck.Acknowledgement()) - suite.Require().NoError(err) - - ackOnB := suite.chainB.GetAcknowledgement(packetFromAtoB) - suite.Require().Equal(successAckBz, ackOnB) - - // B should now have deleted the forwarded packet. - _, found = suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), packetFromBtoC.SourcePort, packetFromBtoC.SourceChannel, packetFromBtoC.Sequence) - suite.Require().False(found, "Chain B should have deleted the forwarded packet") - - // Ack back to A - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathAtoB.EndpointA.AcknowledgePacket(packetFromAtoB, successAck.Acknowledgement()) - suite.Require().NoError(err) -} - -// TestSuccessfulForwardWithNonCosmosAccAddress tests that a packet is successfully forwarded with a non-Cosmos account address. -// The test stops before verifying the final receive, because we don't have a non-cosmos chain to test with. -func (suite *ForwardingTestSuite) TestSuccessfulForwardWithNonCosmosAccAddress() { - /* - Given the following topology: - chain A (channel 0) -> (channel-0) chain B (channel-1) -> (channel-0) chain C - stake transfer/channel-0/stake transfer/channel-0/transfer/channel-0/stake - We want to trigger: - 1. A sends B over channel-0. - 2. Receive on B. - 2.1 B sends C over channel-1 - 3. Receive on C. - At this point we want to assert: - A: packet gets relayed properly with final receiver intact - B: packet arrives and is forwarded with final receiver intact - C: no assertions as we don't have a non-cosmos chain to test with, so this would fail here - */ - - amount := sdkmath.NewInt(100) - - pathAtoB, pathBtoC := suite.setupForwardingPaths() - - sender := suite.chainA.SenderAccounts[0].SenderAccount - nonCosmosReceiver := "0x42069163Ac5919fD49e6A67e6c211E0C86397fa2" - forwarding := types.NewForwarding(false, types.NewHop( - pathBtoC.EndpointA.ChannelConfig.PortID, - pathBtoC.EndpointA.ChannelID, - )) - - transferMsg := types.NewMsgTransfer( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(ibctesting.TestCoin), - sender.GetAddress().String(), - nonCosmosReceiver, - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), "", - forwarding, - ) - - result, err := suite.chainA.SendMsgs(transferMsg) - suite.Require().NoError(err) // message committed - - // parse the packet from result events and recv packet on chainB - packetFromAtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromAtoB) - - // Check that the token sent from A has final receiver intact - var tokenPacketOnA types.FungibleTokenPacketDataV2 - err = proto.Unmarshal(packetFromAtoB.Data, &tokenPacketOnA) - suite.Require().NoError(err) - suite.Require().Equal(nonCosmosReceiver, tokenPacketOnA.Receiver) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packetFromAtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that Escrow A has amount - suite.assertAmountOnChain(suite.chainA, escrow, amount, sdk.DefaultBondDenom) - - packetFromBtoC, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoC) - - // Check that the token sent from B has final receiver intact - var tokenPacketOnB types.FungibleTokenPacketDataV2 - err = proto.Unmarshal(packetFromBtoC.Data, &tokenPacketOnB) - suite.Require().NoError(err) - suite.Require().Equal(nonCosmosReceiver, tokenPacketOnB.Receiver) - - // B should have stored the forwarded packet. - _, found := suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), packetFromBtoC.SourcePort, packetFromBtoC.SourceChannel, packetFromBtoC.Sequence) - suite.Require().True(found, "Chain B should have stored the forwarded packet") -} - -// TestSuccessfulUnwind tests unwinding of tokens sent from A -> B -> C by -// forwarding the tokens back from C -> B -> A. -func (suite *ForwardingTestSuite) TestSuccessfulUnwind() { - /* - Given the following topolgy: - chain A (channel 0) -> (channel-0) chain B (channel-1) -> (channel-0) chain C - stake transfer/channel-0/stake transfer/channel-0/transfer/channel-0/stake - We want to trigger: - 1. Set up the initial state as tokens would have been sent from A -> B -> C. - 2. Send vouchers from C back to A through B. - 3. Receive on A. - At this point we want to assert: - - escrow on B and C is zero - - receiver on A has amount,stake - */ - - amount := sdkmath.NewInt(100) - - pathAtoB, pathBtoC := suite.setupForwardingPaths() - - sender := suite.chainC.SenderAccount - receiver := suite.chainA.SenderAccount - - // set sender and escrow accounts with the right balances to set up an initial state - // that should have been the same as sending token from A -> B -> C - denomA := types.NewDenom(sdk.DefaultBondDenom) - denomAB := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - denomABC := types.NewDenom(sdk.DefaultBondDenom, append([]types.Hop{types.NewHop(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID)}, denomAB.Trace...)...) - - coinOnA := sdk.NewCoin(denomA.IBCDenom(), amount) - err := suite.chainA.GetSimApp().BankKeeper.MintCoins(suite.chainA.GetContext(), types.ModuleName, sdk.NewCoins(coinOnA)) - suite.Require().NoError(err) - escrowAddressAtoB := types.GetEscrowAddress(pathAtoB.EndpointA.ChannelConfig.PortID, pathAtoB.EndpointA.ChannelID) - err = suite.chainA.GetSimApp().BankKeeper.MintCoins(suite.chainA.GetContext(), types.ModuleName, sdk.NewCoins(coinOnA)) - suite.Require().NoError(err) - err = suite.chainA.GetSimApp().BankKeeper.SendCoinsFromModuleToAccount(suite.chainA.GetContext(), types.ModuleName, escrowAddressAtoB, sdk.NewCoins(coinOnA)) - suite.Require().NoError(err) - suite.chainA.GetSimApp().TransferKeeper.SetTotalEscrowForDenom(suite.chainA.GetContext(), coinOnA) - - coinOnB := sdk.NewCoin(denomAB.IBCDenom(), amount) - err = suite.chainB.GetSimApp().BankKeeper.MintCoins(suite.chainB.GetContext(), types.ModuleName, sdk.NewCoins(coinOnB)) - suite.Require().NoError(err) - escrowAddressBtoC := types.GetEscrowAddress(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID) - err = suite.chainB.GetSimApp().BankKeeper.MintCoins(suite.chainB.GetContext(), types.ModuleName, sdk.NewCoins(coinOnB)) - suite.Require().NoError(err) - err = suite.chainB.GetSimApp().BankKeeper.SendCoinsFromModuleToAccount(suite.chainB.GetContext(), types.ModuleName, escrowAddressBtoC, sdk.NewCoins(coinOnB)) - suite.Require().NoError(err) - suite.chainB.GetSimApp().TransferKeeper.SetTotalEscrowForDenom(suite.chainB.GetContext(), coinOnB) - suite.chainB.GetSimApp().TransferKeeper.SetDenom(suite.chainB.GetContext(), denomAB) - - coinOnC := sdk.NewCoin(denomABC.IBCDenom(), amount) - err = suite.chainC.GetSimApp().BankKeeper.MintCoins(suite.chainC.GetContext(), types.ModuleName, sdk.NewCoins(coinOnC)) - suite.Require().NoError(err) - err = suite.chainC.GetSimApp().BankKeeper.SendCoinsFromModuleToAccount(suite.chainC.GetContext(), types.ModuleName, sender.GetAddress(), sdk.NewCoins(coinOnC)) - suite.Require().NoError(err) - suite.chainC.GetSimApp().TransferKeeper.SetDenom(suite.chainC.GetContext(), denomABC) - - originalABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), receiver.GetAddress(), coinOnA.Denom) - - forwarding := types.NewForwarding(false, types.NewHop( - pathAtoB.EndpointB.ChannelConfig.PortID, - pathAtoB.EndpointB.ChannelID, - )) - - transferMsg := types.NewMsgTransfer( - pathBtoC.EndpointB.ChannelConfig.PortID, - pathBtoC.EndpointB.ChannelID, - sdk.NewCoins(coinOnC), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainC.GetTimeoutTimestamp(), "", - forwarding, - ) - - result, err := suite.chainC.SendMsgs(transferMsg) - suite.Require().NoError(err) // message committed - - // Sender's balance for vouchers is 0 - suite.assertAmountOnChain(suite.chainC, balance, sdkmath.NewInt(0), denomABC.IBCDenom()) - - // parse the packet from result events and recv packet on chainB - packetFromCtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromCtoB) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - result, err = pathBtoC.EndpointA.RecvPacketWithResult(packetFromCtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Vouchers have been burned on chain B - suite.assertAmountOnChain(suite.chainB, escrow, sdkmath.NewInt(0), denomAB.IBCDenom()) - - // parse the packet from result events and recv packet on chainA - packetFromBtoA, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoA) - - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - // B should have stored the forwarded packet. - forwardedPacket, found := suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), packetFromBtoA.SourcePort, packetFromBtoA.SourceChannel, packetFromBtoA.Sequence) - suite.Require().True(found) - suite.Require().Equal(packetFromCtoB, forwardedPacket) - - result, err = pathAtoB.EndpointA.RecvPacketWithResult(packetFromBtoA) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - successAck := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - successAckBz := channeltypes.CommitAcknowledgement(successAck.Acknowledgement()) - - // Ack back to B - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - err = pathAtoB.EndpointB.AcknowledgePacket(packetFromBtoA, successAck.Acknowledgement()) - suite.Require().NoError(err) - - ackOnB := suite.chainB.GetAcknowledgement(packetFromCtoB) - suite.Require().Equal(successAckBz, ackOnB) - - // Ack back to C - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointB.AcknowledgePacket(packetFromCtoB, successAck.Acknowledgement()) - suite.Require().NoError(err) - - // Check that B deleted the forwarded packet. - _, found = suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), packetFromBtoA.SourcePort, packetFromBtoA.SourceChannel, packetFromBtoA.Sequence) - suite.Require().False(found, "chain B should have deleted the forwarded packet mapping") - - // Check that tokens have been unescrowed and receiver got the tokens - suite.assertAmountOnChain(suite.chainA, escrow, sdkmath.NewInt(0), denomA.IBCDenom()) - suite.assertAmountOnChain(suite.chainA, balance, originalABalance.Amount.Add(amount), denomA.IBCDenom()) -} - -// TestForwardingBackAfterUnwind tests the scenario where tokens are unwound and then forwarded -// back to the sending chain. -func (suite *ForwardingTestSuite) TestForwardingBackAfterUnwind() { - /* - Given the following topology: - chain A (channel 0) -> (channel-0) chain B (channel-0) - stake transfer/channel-0/stake - We want to trigger: - 1. A sends to B over channel-0. - 2. B receives and transfers back to A over channel-0 with unwind set to true. - 3. A receives the packet back. - 4. A sends back to B over channel-0. - At this point we want to assert: - A: finalReceiver = amount,transfer/channel-0/denom - B: no tokens should be held in escrow. - */ - amount := sdkmath.NewInt(100) - pathAtoB, _ := suite.setupForwardingPaths() - - accountA := suite.chainA.SenderAccount - accountB := suite.chainB.SenderAccount - - denomA := types.NewDenom(sdk.DefaultBondDenom) - denomAB := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - - // Send tokens from A to B - coin := ibctesting.TestCoin - transferMsg := types.NewMsgTransfer( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(coin), - accountA.GetAddress().String(), - accountB.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), "", - nil, - ) - - result, err := suite.chainA.SendMsgs(transferMsg) - suite.Require().NoError(err) // message committed - - // parse the packet from result events and recv packet on chainA - packetFromAtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromAtoB) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packetFromAtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that vouchers are received on chain B - suite.assertAmountOnChain(suite.chainB, balance, amount, denomAB.IBCDenom()) - - // Unwind tokens back from B to A - coinOnB := sdk.NewCoin(denomAB.IBCDenom(), amount) - forwarding := types.NewForwarding(true, types.NewHop( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - )) - - transferMsg = types.NewMsgTransfer( - "", - "", - sdk.NewCoins(coinOnB), - accountB.GetAddress().String(), - accountB.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainB.GetTimeoutTimestamp(), "", - forwarding, - ) - - result, err = suite.chainB.SendMsgs(transferMsg) - suite.Require().NoError(err) // message committed - - suite.assertAmountOnChain(suite.chainB, balance, sdkmath.NewInt(0), denomAB.IBCDenom()) - - // parse the packet from result events and recv packet on chainA - packetFromBtoA, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoA) - - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointA.RecvPacketWithResult(packetFromBtoA) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that Escrow A has 100 - suite.assertAmountOnChain(suite.chainA, escrow, sdkmath.NewInt(100), denomA.IBCDenom()) - - // parse the packet from result events and recv packet on chainB - packetFromAtoB, err = ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromAtoB) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packetFromAtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that Escrow A has 100 - suite.assertAmountOnChain(suite.chainA, escrow, amount, denomA.IBCDenom()) - // Check that vouchers are back on chain B - suite.assertAmountOnChain(suite.chainB, balance, amount, denomAB.IBCDenom()) - - successAck := channeltypes.NewResultAcknowledgement([]byte{byte(1)}) - successAckBz := channeltypes.CommitAcknowledgement(successAck.Acknowledgement()) - ackOnB := suite.chainB.GetAcknowledgement(packetFromAtoB) - suite.Require().Equal(successAckBz, ackOnB) - - // Ack back to A - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathAtoB.EndpointA.AcknowledgePacket(packetFromAtoB, successAck.Acknowledgement()) - suite.Require().NoError(err) - - // Ack back to B - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - err = pathAtoB.EndpointB.AcknowledgePacket(packetFromBtoA, successAck.Acknowledgement()) - suite.Require().NoError(err) -} - -// TestAcknowledgementFailureWithMiddleChainAsNativeTokenSource tests a failure in the last hop where the -// middle chain is native source when receiving and sending the packet. In other words, the middle chain's native -// token has been sent to chain C, and the multi-hop transfer from C -> B -> A has chain B being the source of -// the token both when receiving and forwarding (sending). -func (suite *ForwardingTestSuite) TestAcknowledgementFailureWithMiddleChainAsNativeTokenSource() { - /* - Given the following topology: - chain A (channel 0) -> (channel-0) chain B (channel-1) -> (channel-0) chain C - stake transfer/channel-0/stake transfer/channel-0/transfer/channel-0/stake - We want to trigger: - 1. Transfer from B to C - 2. Single transfer forwarding token from C -> B -> A - 2.1 The ack fails on the last hop (chain A) - 2.2 Propagate the error back to C - 3. Verify all the balances are updated as expected - */ - - amount := sdkmath.NewInt(100) - - pathAtoB, pathBtoC := suite.setupForwardingPaths() - - coinOnB := ibctesting.TestCoin - setupSender := suite.chainB.SenderAccounts[0].SenderAccount - setupReceiver := suite.chainC.SenderAccounts[0].SenderAccount - - setupTransferMsg := types.NewMsgTransfer( - pathBtoC.EndpointA.ChannelConfig.PortID, - pathBtoC.EndpointA.ChannelID, - sdk.NewCoins(coinOnB), - setupSender.GetAddress().String(), - setupReceiver.GetAddress().String(), - suite.chainB.GetTimeoutHeight(), - 0, "", - nil, - ) - - result, err := suite.chainB.SendMsgs(setupTransferMsg) - suite.Require().NoError(err) // message committed - - // parse the packet from result events and recv packet on chainC - packetFromBToC, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBToC) - - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathBtoC.EndpointB.RecvPacketWithResult(packetFromBToC) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that EscrowBtoC has amount - escrowAddressBtoC := types.GetEscrowAddress(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID) - escrowBalancBtoC := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), escrowAddressBtoC, coinOnB.GetDenom()) - suite.Require().Equal(amount, escrowBalancBtoC.Amount) - - // Check that receiver has the expected tokens - denomOnC := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID)) - coinOnC := sdk.NewCoin(denomOnC.IBCDenom(), amount) - balanceOnC := suite.chainC.GetSimApp().BankKeeper.GetBalance(suite.chainC.GetContext(), setupReceiver.GetAddress(), coinOnC.GetDenom()) - suite.Require().Equal(amount, balanceOnC.Amount) - - // Now we start the transfer from C -> B -> A - sender := suite.chainC.SenderAccounts[0].SenderAccount - receiver := suite.chainA.SenderAccounts[0].SenderAccount - - forwarding := types.NewForwarding(false, types.NewHop( - pathAtoB.EndpointB.ChannelConfig.PortID, - pathAtoB.EndpointB.ChannelID, - )) - - forwardTransfer := types.NewMsgTransfer( - pathBtoC.EndpointB.ChannelConfig.PortID, - pathBtoC.EndpointB.ChannelID, - sdk.NewCoins(coinOnC), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), - "", - forwarding, - ) - - result, err = suite.chainC.SendMsgs(forwardTransfer) - suite.Require().NoError(err) // message committed - - // Check that Escrow C has unescrowed the amount - totalEscrowChainC := suite.chainC.GetSimApp().TransferKeeper.GetTotalEscrowForDenom(suite.chainC.GetContext(), coinOnC.GetDenom()) - suite.Require().Equal(sdkmath.NewInt(0), totalEscrowChainC.Amount) - - // parse the packet from result events and recv packet on chainB - packetFromCtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromCtoB) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - result, err = pathBtoC.EndpointA.RecvPacketWithResult(packetFromCtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that escrow has been moved from EscrowBtoC to EscrowBtoA - escrowBalancBtoC = suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), escrowAddressBtoC, coinOnB.GetDenom()) - suite.Require().Equal(sdkmath.NewInt(0), escrowBalancBtoC.Amount) - - escrowAddressBtoA := types.GetEscrowAddress(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID) - escrowBalanceBtoA := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), escrowAddressBtoA, coinOnB.GetDenom()) - suite.Require().Equal(amount, escrowBalanceBtoA.Amount) - - forwardedPacket, found := suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID, packetFromCtoB.Sequence) - suite.Require().True(found) - suite.Require().Equal(packetFromCtoB, forwardedPacket) - - // Now we can receive the packet on A where we want to trigger an error - packetFromBtoA, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoA) - - // turn off receive on chain A to trigger an error - suite.chainA.GetSimApp().TransferKeeper.SetParams(suite.chainA.GetContext(), types.Params{ - SendEnabled: true, - ReceiveEnabled: false, - }) - - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointA.RecvPacketWithResult(packetFromBtoA) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - ack, err := ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointB.AcknowledgePacketWithResult(packetFromBtoA, ack) - suite.Require().NoError(err) - - ack, err = ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - - // Check that escrow has been moved back from EscrowBtoA to EscrowBtoC - escrowBalanceBtoA = suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), escrowAddressBtoA, coinOnB.GetDenom()) - suite.Require().Equal(sdkmath.NewInt(0), escrowBalanceBtoA.Amount) - - escrowBalancBtoC = suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), escrowAddressBtoC, coinOnB.GetDenom()) - suite.Require().Equal(amount, escrowBalancBtoC.Amount) - - // Check the status of account on chain C before executing ack. - balanceOnC = suite.chainC.GetSimApp().BankKeeper.GetBalance(suite.chainC.GetContext(), setupReceiver.GetAddress(), coinOnC.GetDenom()) - suite.Require().Equal(sdkmath.NewInt(0), balanceOnC.Amount) - - // Propagate the error to C - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointB.AcknowledgePacket(packetFromCtoB, ack) - suite.Require().NoError(err) - - // Check that everything has been reverted - // - // Check the vouchers have been refunded on C - balanceOnC = suite.chainC.GetSimApp().BankKeeper.GetBalance(suite.chainC.GetContext(), setupReceiver.GetAddress(), coinOnC.GetDenom()) - suite.Require().Equal(amount, balanceOnC.Amount, "final receiver balance has not increased") -} - -// TestAcknowledgementFailureWithMiddleChainAsNotBeingTokenSource tests a failure in the last hop where the middle chain -// is not source of the token when receiving or sending the packet. In other words, the middle chain's is sent -// (and forwarding) someone else's native token (in this case chain C). -func (suite *ForwardingTestSuite) TestAcknowledgementFailureWithMiddleChainAsNotBeingTokenSource() { - /* - Given the following topology: - chain A (channel 0) <- (channel-0) chain B (channel-1) <- (channel-0) chain C - transfer/channel-0/transfer/channel-1/stake transfer/channel-1/stake stake - We want to trigger: - 1. Single transfer forwarding token from C -> B -> A - 1.1 The ack fails on the last hop - 1.2 Propagate the error back to C - 2. Verify all the balances are updated as expected - */ - - amount := sdkmath.NewInt(100) - - pathAtoB, pathBtoC := suite.setupForwardingPaths() - - // Now we start the transfer from C -> B -> A - coinOnC := ibctesting.TestCoin - sender := suite.chainC.SenderAccounts[0].SenderAccount - receiver := suite.chainA.SenderAccounts[0].SenderAccount - - forwarding := types.NewForwarding(false, types.NewHop( - pathAtoB.EndpointB.ChannelConfig.PortID, - pathAtoB.EndpointB.ChannelID, - )) - - forwardTransfer := types.NewMsgTransfer( - pathBtoC.EndpointB.ChannelConfig.PortID, - pathBtoC.EndpointB.ChannelID, - sdk.NewCoins(coinOnC), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), - "", - forwarding, - ) - - balanceOnCBefore := suite.chainC.GetSimApp().BankKeeper.GetBalance(suite.chainC.GetContext(), sender.GetAddress(), coinOnC.GetDenom()) - - result, err := suite.chainC.SendMsgs(forwardTransfer) - suite.Require().NoError(err) // message committed - - // Check that Escrow C has amount - totalEscrowChainC := suite.chainC.GetSimApp().TransferKeeper.GetTotalEscrowForDenom(suite.chainC.GetContext(), coinOnC.GetDenom()) - suite.Require().Equal(amount, totalEscrowChainC.Amount) - - packetFromCtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromCtoB) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - result, err = pathBtoC.EndpointA.RecvPacketWithResult(packetFromCtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that Escrow B has amount - denomOnB := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID)) - suite.assertAmountOnChain(suite.chainB, escrow, amount, denomOnB.IBCDenom()) - - forwardedPacket, found := suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID, packetFromCtoB.Sequence) - suite.Require().True(found) - suite.Require().Equal(packetFromCtoB, forwardedPacket) - - // Now we can receive the packet on A where we want to trigger an error - packetFromBtoA, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoA) - - // turn off receive on chain A to trigger an error - suite.chainA.GetSimApp().TransferKeeper.SetParams(suite.chainA.GetContext(), types.Params{ - SendEnabled: true, - ReceiveEnabled: false, - }) - - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointA.RecvPacketWithResult(packetFromBtoA) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - ack, err := ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointB.AcknowledgePacketWithResult(packetFromBtoA, ack) - suite.Require().NoError(err) - - ack, err = ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - - // Check that escrow has been burnt on B - suite.assertAmountOnChain(suite.chainB, escrow, sdkmath.NewInt(0), denomOnB.IBCDenom()) - - // Check the status of account on chain C before executing ack. - balanceOnC := suite.chainC.GetSimApp().BankKeeper.GetBalance(suite.chainC.GetContext(), sender.GetAddress(), coinOnC.GetDenom()) - suite.Require().Equal(balanceOnCBefore.SubAmount(amount).Amount, balanceOnC.Amount) - - // Propagate the error to C - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointB.AcknowledgePacket(packetFromCtoB, ack) - suite.Require().NoError(err) - - // Check that everything has been reverted - // - // Check the token has been returned to the sender on C - suite.assertAmountOnChain(suite.chainC, escrow, sdkmath.NewInt(0), coinOnC.GetDenom()) - suite.assertAmountOnChain(suite.chainC, balance, balanceOnCBefore.Amount, coinOnC.GetDenom()) -} - -// TestOnTimeoutPacketForwarding tests the scenario in which a packet goes from -// A to C, using B as a forwarding hop. The packet times out when going to C -// from B and we verify that funds are properly returned to A. -func (suite *ForwardingTestSuite) TestOnTimeoutPacketForwarding() { - pathAtoB, pathBtoC := suite.setupForwardingPaths() - - amount := sdkmath.NewInt(100) - coin := ibctesting.TestCoin - sender := suite.chainA.SenderAccounts[0].SenderAccount - receiver := suite.chainC.SenderAccounts[0].SenderAccount - - denomA := types.NewDenom(coin.Denom) - denomAB := types.NewDenom(coin.Denom, types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - denomABC := types.NewDenom(coin.Denom, append([]types.Hop{types.NewHop(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID)}, denomAB.Trace...)...) - - originalABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), sender.GetAddress(), coin.Denom) - - forwarding := types.NewForwarding(false, types.NewHop(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID)) - - transferMsg := types.NewMsgTransfer( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(coin), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - uint64(suite.chainA.GetContext().BlockTime().Add(time.Minute*5).UnixNano()), - "", - forwarding, - ) - - result, err := suite.chainA.SendMsgs(transferMsg) - suite.Require().NoError(err) // message committed - - // parse the packet from result events and recv packet on chainB - packetFromAToB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromAToB) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - // Receive packet on B. - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packetFromAToB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - packetFromBToC, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBToC) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - // Make sure funds went from A to B's escrow account. - suite.assertAmountOnChain(suite.chainA, balance, originalABalance.Amount.Sub(amount), denomA.IBCDenom()) - suite.assertAmountOnChain(suite.chainB, escrow, amount, denomAB.IBCDenom()) - - // Check that forwarded packet exists - forwardedPacket, found := suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, packetFromAToB.Sequence) - suite.Require().True(found, "Chain B has no forwarded packet") - suite.Require().Equal(packetFromAToB, forwardedPacket, "ForwardedPacket stored in ChainB is not the same that was sent") - - // Time out packet - suite.coordinator.IncrementTimeBy(time.Minute * 5) - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - result, err = pathBtoC.EndpointA.TimeoutPacketWithResult(packetFromBToC) - suite.Require().NoError(err) - ack, err := ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - - // Ensure that chainB has an ack. - storedAck, found := suite.chainB.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(suite.chainB.GetContext(), pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID, packetFromBToC.GetSequence()) - suite.Require().True(found, "chainB does not have an ack") - - // And that this ack is of the type we expect (Error due to time out) - expectedAck := internaltypes.NewForwardTimeoutAcknowledgement(packetFromBToC) - expectedAckBytes := channeltypes.CommitAcknowledgement(expectedAck.Acknowledgement()) - suite.Require().Equal(expectedAckBytes, storedAck) - suite.Require().Equal(expectedAck.Acknowledgement(), ack) - - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - err = pathAtoB.EndpointA.AcknowledgePacket(packetFromAToB, ack) - suite.Require().NoError(err) - - // Finally, check that A,B, and C escrow accounts do not have fund. - suite.assertAmountOnChain(suite.chainC, escrow, sdkmath.NewInt(0), denomABC.IBCDenom()) - suite.assertAmountOnChain(suite.chainB, escrow, sdkmath.NewInt(0), denomAB.IBCDenom()) - suite.assertAmountOnChain(suite.chainA, escrow, sdkmath.NewInt(0), denomA.IBCDenom()) - - // And that A has its original balance back. - suite.assertAmountOnChain(suite.chainA, balance, originalABalance.Amount, coin.Denom) -} - -// TestForwardingWithMoreThanOneHop tests the scenario in which we -// forward with more than one forwarding hop. -func (suite *ForwardingTestSuite) TestForwardingWithMoreThanOneHop() { - // Setup A->B->C->D - coinOnA := ibctesting.TestCoin - - pathAtoB := ibctesting.NewTransferPath(suite.chainA, suite.chainB) - pathAtoB.Setup() - - pathBtoC := ibctesting.NewTransferPath(suite.chainB, suite.chainC) - pathBtoC.Setup() - - pathCtoD := ibctesting.NewTransferPath(suite.chainC, suite.chainD) - pathCtoD.Setup() - - sender := suite.chainA.SenderAccounts[0].SenderAccount - receiver := suite.chainD.SenderAccounts[0].SenderAccount - - forwarding := types.NewForwarding(false, - types.NewHop(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID), - types.NewHop(pathCtoD.EndpointA.ChannelConfig.PortID, pathCtoD.EndpointA.ChannelID), - ) - - transferMsg := types.NewMsgTransfer( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(coinOnA), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), - "", - forwarding) - - // Send message to A and verify. - result, err := suite.chainA.SendMsgs(transferMsg) - suite.Require().NoError(err) - - packetFromAtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromAtoB) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - // Receive from B and verify. - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packetFromAtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that Escrow A has amount - suite.assertAmountOnChain(suite.chainA, escrow, coinOnA.Amount, coinOnA.Denom) - - // Check that Escrow B has amount - denomTrace := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - suite.assertAmountOnChain(suite.chainB, escrow, coinOnA.Amount, denomTrace.IBCDenom()) - - // Receive on C the packet sent from B, verify amount. - packetFromBtoC, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoC) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathBtoC.EndpointB.RecvPacketWithResult(packetFromBtoC) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // Check that Escrow C has amount - denomTraceABC := types.NewDenom(denomTrace.Base, append([]types.Hop{types.NewHop(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID)}, denomTrace.Trace...)...) - suite.assertAmountOnChain(suite.chainC, escrow, coinOnA.Amount, denomTraceABC.IBCDenom()) - - // Finally, receive on D and verify that D has the desired amount. - packetFromCtoD, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromCtoD) - - err = pathCtoD.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathCtoD.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathCtoD.EndpointB.RecvPacketWithResult(packetFromCtoD) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - denomTraceABCD := types.NewDenom(denomTraceABC.Base, append([]types.Hop{types.NewHop(pathCtoD.EndpointB.ChannelConfig.PortID, pathCtoD.EndpointB.ChannelID)}, denomTraceABC.Trace...)...) - suite.assertAmountOnChain(suite.chainD, balance, coinOnA.Amount, denomTraceABCD.IBCDenom()) - - // Propagate the ack back from D to A. - ack, err := ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(ack) - - err = pathCtoD.EndpointA.AcknowledgePacket(packetFromCtoD, ack) - suite.Require().NoError(err) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointA.AcknowledgePacket(packetFromBtoC, ack) - suite.Require().NoError(err) - - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathAtoB.EndpointA.AcknowledgePacket(packetFromAtoB, ack) - suite.Require().NoError(err) -} - -// TestMultihopForwardingErrorAcknowledgement tests the scenario in which a packet goes from -// A to D, using B and C as forwarding hops. The packet fails on D where we set the ReceiveEnabled -// param to false. We verify that funds are properly returned to A. -func (suite *ForwardingTestSuite) TestMultihopForwardingErrorAcknowledgement() { - // Setup A->B->C->D - coinOnA := ibctesting.TestCoin - - pathAtoB := ibctesting.NewTransferPath(suite.chainA, suite.chainB) - pathAtoB.Setup() - - pathBtoC := ibctesting.NewTransferPath(suite.chainB, suite.chainC) - pathBtoC.Setup() - - pathCtoD := ibctesting.NewTransferPath(suite.chainC, suite.chainD) - pathCtoD.Setup() - - sender := suite.chainA.SenderAccounts[0].SenderAccount - receiver := suite.chainD.SenderAccounts[0].SenderAccount - - forwarding := types.NewForwarding(false, - types.NewHop(pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID), - types.NewHop(pathCtoD.EndpointA.ChannelConfig.PortID, pathCtoD.EndpointA.ChannelID), - ) - - transferMsg := types.NewMsgTransfer( - pathAtoB.EndpointA.ChannelConfig.PortID, - pathAtoB.EndpointA.ChannelID, - sdk.NewCoins(coinOnA), - sender.GetAddress().String(), - receiver.GetAddress().String(), - clienttypes.ZeroHeight(), - suite.chainA.GetTimeoutTimestamp(), - "", - forwarding) - - result, err := suite.chainA.SendMsgs(transferMsg) - suite.Require().NoError(err) - - packetFromAtoB, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromAtoB) - - err = pathAtoB.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointB.RecvPacketWithResult(packetFromAtoB) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // assert escrow on chain A. - suite.assertAmountOnChain(suite.chainA, escrow, coinOnA.Amount, coinOnA.Denom) - - // assert escrow on chain B. - denomAB := types.NewDenom(sdk.DefaultBondDenom, types.NewHop(pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID)) - suite.assertAmountOnChain(suite.chainB, escrow, coinOnA.Amount, denomAB.IBCDenom()) - - packetFromBtoC, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromBtoC) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathBtoC.EndpointB.UpdateClient() - suite.Require().NoError(err) - - result, err = pathBtoC.EndpointB.RecvPacketWithResult(packetFromBtoC) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // assert escrow on chain C. - denomABC := types.NewDenom(denomAB.Base, append([]types.Hop{types.NewHop(pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID)}, denomAB.Trace...)...) - suite.assertAmountOnChain(suite.chainC, escrow, coinOnA.Amount, denomABC.IBCDenom()) - - packetFromCtoD, err := ibctesting.ParsePacketFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(packetFromCtoD) - - err = pathCtoD.EndpointA.UpdateClient() - suite.Require().NoError(err) - - err = pathCtoD.EndpointB.UpdateClient() - suite.Require().NoError(err) - - // force an error acknowledgement by disabling the ReceiveEnabled param on chain D. - ctx := pathCtoD.EndpointB.Chain.GetContext() - pathCtoD.EndpointB.Chain.GetSimApp().TransferKeeper.SetParams(ctx, types.NewParams(true, false)) - - result, err = pathCtoD.EndpointB.RecvPacketWithResult(packetFromCtoD) - suite.Require().NoError(err) - suite.Require().NotNil(result) - - // forward packet exists on C before ack - _, found := suite.chainC.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainC.GetContext(), pathCtoD.EndpointA.ChannelConfig.PortID, pathCtoD.EndpointA.ChannelID, packetFromBtoC.GetSequence()) - suite.Require().True(found) - - // propagate the acknowledgement from chain D to chain A. - ack, err := ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - suite.Require().NotNil(ack) - - result, err = pathCtoD.EndpointA.AcknowledgePacketWithResult(packetFromCtoD, ack) - suite.Require().NoError(err) - - // forward packet is deleted after ack - _, found = suite.chainC.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainC.GetContext(), pathCtoD.EndpointA.ChannelConfig.PortID, pathCtoD.EndpointA.ChannelID, packetFromBtoC.GetSequence()) - suite.Require().False(found) - - // Ensure that chainC has an ack. - storedAck, found := suite.chainC.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(suite.chainC.GetContext(), pathBtoC.EndpointB.ChannelConfig.PortID, pathBtoC.EndpointB.ChannelID, packetFromBtoC.GetSequence()) - suite.Require().True(found, "chainC does not have an ack") - - // And that this ack is of the type we expect (Error due to ReceiveEnabled param being false) - initialErrorAck := channeltypes.NewErrorAcknowledgement(types.ErrReceiveDisabled) - forwardErrorAck := internaltypes.NewForwardErrorAcknowledgement(packetFromCtoD, initialErrorAck) - ackbytes := channeltypes.CommitAcknowledgement(forwardErrorAck.Acknowledgement()) - suite.Require().Equal(ackbytes, storedAck) - - ack, err = ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - - err = pathBtoC.EndpointA.UpdateClient() - suite.Require().NoError(err) - - // forward packet exists on B before ack - _, found = suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, packetFromAtoB.GetSequence()) - suite.Require().True(found) - - result, err = pathBtoC.EndpointA.AcknowledgePacketWithResult(packetFromBtoC, ack) - suite.Require().NoError(err) - - // forward packet is deleted after ack - _, found = suite.chainB.GetSimApp().TransferKeeper.GetForwardedPacket(suite.chainB.GetContext(), pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, packetFromAtoB.GetSequence()) - suite.Require().False(found) - - // Ensure that chainB has an ack. - storedAck, found = suite.chainB.App.GetIBCKeeper().ChannelKeeper.GetPacketAcknowledgement(suite.chainB.GetContext(), pathAtoB.EndpointB.ChannelConfig.PortID, pathAtoB.EndpointB.ChannelID, packetFromAtoB.GetSequence()) - suite.Require().True(found, "chainB does not have an ack") - - // And that this ack is of the type we expect (Error due to ReceiveEnabled param being false) - forwardErrorAck = internaltypes.NewForwardErrorAcknowledgement(packetFromBtoC, forwardErrorAck) - ackbytes = channeltypes.CommitAcknowledgement(forwardErrorAck.Acknowledgement()) - suite.Require().Equal(ackbytes, storedAck) - - ack, err = ibctesting.ParseAckFromEvents(result.Events) - suite.Require().NoError(err) - - err = pathAtoB.EndpointA.UpdateClient() - suite.Require().NoError(err) - - result, err = pathAtoB.EndpointA.AcknowledgePacketWithResult(packetFromAtoB, ack) - suite.Require().NoError(err) - - // NOTE: parse acknowledgement from transfer events as ack is not emitted in core AcknowledgePacket events. - ackStr, err := parseAckFromTransferEvents(result.Events) - suite.Require().NoError(err) - - expected := fmt.Sprintf(`error:"forwarding packet failed on %s/%s: forwarding packet failed on %s/%s: ABCI code: 8: error handling packet: see events for details" `, pathBtoC.EndpointA.ChannelConfig.PortID, pathBtoC.EndpointA.ChannelID, pathCtoD.EndpointA.ChannelConfig.PortID, pathCtoD.EndpointA.ChannelID) - suite.Require().Equal(expected, ackStr) -} - -func parseAckFromTransferEvents(events []abci.Event) (string, error) { - for _, ev := range events { - if ev.Type == types.EventTypePacket { - for _, attr := range ev.Attributes { - if attr.Key == types.AttributeKeyAck { - return attr.Value, nil - } - } - } - } - - return "", fmt.Errorf("acknowledgement event attribute not found") -} - -func (suite *ForwardingTestSuite) assertAmountOnChain(chain *ibctesting.TestChain, balanceType amountType, amount sdkmath.Int, denom string) { - var total sdk.Coin - switch balanceType { - case escrow: - total = chain.GetSimApp().TransferKeeper.GetTotalEscrowForDenom(chain.GetContext(), denom) - case balance: - total = chain.GetSimApp().BankKeeper.GetBalance(chain.GetContext(), chain.SenderAccounts[0].SenderAccount.GetAddress(), denom) - default: - suite.Fail("invalid amountType %s", balanceType) - } - suite.Require().Equal(amount, total.Amount, fmt.Sprintf("Chain %s: got balance of %d, wanted %d", chain.Name(), total.Amount, amount)) -} diff --git a/modules/apps/transfer/keeper/relay_test.go b/modules/apps/transfer/keeper/relay_test.go index 6c7372e3a84..e13a3e2c400 100644 --- a/modules/apps/transfer/keeper/relay_test.go +++ b/modules/apps/transfer/keeper/relay_test.go @@ -34,12 +34,11 @@ var ( // that originate on chainA and coin that originate on chainB. func (suite *KeeperTestSuite) TestSendTransfer() { var ( - coins sdk.Coins - path *ibctesting.Path - sender sdk.AccAddress - memo string - forwarding *types.Forwarding - expEscrowAmounts []sdkmath.Int // total amounts in escrow for denom on receiving chain + coin sdk.Coin + path *ibctesting.Path + sender sdk.AccAddress + memo string + expEscrowAmount sdkmath.Int // total amounts in escrow for denom on receiving chain ) testCases := []struct { @@ -59,24 +58,14 @@ func (suite *KeeperTestSuite) TestSendTransfer() { }, nil, }, - { - "successful transfer with non-empty forwarding hops and ics20-2", - func() { - forwarding = types.NewForwarding(false, types.NewHop( - path.EndpointA.ChannelConfig.PortID, - path.EndpointA.ChannelID, - )) - }, - nil, - }, { "successful transfer of IBC token", func() { // send IBC token back to chainB denom := types.NewDenom(ibctesting.TestCoin.Denom, types.NewHop(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)) - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) + coin = sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount) - expEscrowAmounts = []sdkmath.Int{zeroAmount} + expEscrowAmount = zeroAmount }, nil, }, @@ -85,34 +74,19 @@ func (suite *KeeperTestSuite) TestSendTransfer() { func() { // send IBC token back to chainB denom := types.NewDenom(ibctesting.TestCoin.Denom, types.NewHop(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)) - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) + coin = sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount) memo = "memo" - expEscrowAmounts = []sdkmath.Int{zeroAmount} - }, - nil, - }, - { - "successful transfer of native token with ics20-1", - func() { - denom := types.NewDenom(ibctesting.TestCoin.Denom) - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) - - // Set version to isc20-1. - path.EndpointA.UpdateChannel(func(channel *channeltypes.Channel) { - channel.Version = types.V1 - }) - - expEscrowAmounts = []sdkmath.Int{defaultAmount} + expEscrowAmount = zeroAmount }, nil, }, { "successful transfer of entire balance", func() { - coins = sdk.NewCoins(sdk.NewCoin(coins[0].Denom, types.UnboundedSpendLimit())) + coin = sdk.NewCoin(coin.Denom, types.UnboundedSpendLimit()) var ok bool - expEscrowAmounts[0], ok = sdkmath.NewIntFromString(ibctesting.DefaultGenesisAccBalance) + expEscrowAmount, ok = sdkmath.NewIntFromString(ibctesting.DefaultGenesisAccBalance) suite.Require().True(ok) }, nil, @@ -124,7 +98,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() { vestingAccPrivKey := secp256k1.GenPrivKey() vestingAccAddress := sdk.AccAddress(vestingAccPrivKey.PubKey().Address()) - vestingCoins := sdk.NewCoins(sdk.NewCoin(coins[0].Denom, ibctesting.DefaultCoinAmount)) + vestingCoins := sdk.NewCoins(sdk.NewCoin(coin.Denom, ibctesting.DefaultCoinAmount)) _, err := suite.chainA.SendMsgs(vestingtypes.NewMsgCreateVestingAccount( suite.chainA.SenderAccount.GetAddress(), vestingAccAddress, @@ -136,12 +110,12 @@ func (suite *KeeperTestSuite) TestSendTransfer() { sender = vestingAccAddress // transfer some spendable coins to vesting account - transferCoins := sdk.NewCoins(sdk.NewCoin(coins[0].Denom, sdkmath.NewInt(42))) - _, err = suite.chainA.SendMsgs(banktypes.NewMsgSend(suite.chainA.SenderAccount.GetAddress(), vestingAccAddress, transferCoins)) + transferCoin := sdk.NewCoin(coin.Denom, sdkmath.NewInt(42)) + _, err = suite.chainA.SendMsgs(banktypes.NewMsgSend(suite.chainA.SenderAccount.GetAddress(), vestingAccAddress, sdk.NewCoins(transferCoin))) suite.Require().NoError(err) - coins = sdk.NewCoins(sdk.NewCoin(coins[0].Denom, types.UnboundedSpendLimit())) - expEscrowAmounts[0] = transferCoins[0].Amount + coin = sdk.NewCoin(coin.Denom, types.UnboundedSpendLimit()) + expEscrowAmount = transferCoin.Amount }, nil, }, @@ -152,11 +126,11 @@ func (suite *KeeperTestSuite) TestSendTransfer() { vestingAccPrivKey := secp256k1.GenPrivKey() vestingAccAddress := sdk.AccAddress(vestingAccPrivKey.PubKey().Address()) - vestingCoins := sdk.NewCoins(sdk.NewCoin(coins[0].Denom, ibctesting.DefaultCoinAmount)) + vestingCoin := sdk.NewCoin(coin.Denom, ibctesting.DefaultCoinAmount) _, err := suite.chainA.SendMsgs(vestingtypes.NewMsgCreateVestingAccount( suite.chainA.SenderAccount.GetAddress(), vestingAccAddress, - vestingCoins, + sdk.NewCoins(vestingCoin), suite.chainA.GetContext().BlockTime().Add(time.Hour).Unix(), false, )) @@ -164,12 +138,12 @@ func (suite *KeeperTestSuite) TestSendTransfer() { sender = vestingAccAddress // just to prove that the vesting account has a balance (but not spendable) - vestingAccBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), vestingAccAddress, coins[0].Denom) - suite.Require().Equal(vestingCoins[0].Amount.Int64(), vestingAccBalance.Amount.Int64()) + vestingAccBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), vestingAccAddress, coin.Denom) + suite.Require().Equal(vestingCoin.Amount.Int64(), vestingAccBalance.Amount.Int64()) vestinSpendableBalance := suite.chainA.GetSimApp().BankKeeper.SpendableCoins(suite.chainA.GetContext(), vestingAccAddress) - suite.Require().Zero(vestinSpendableBalance.AmountOf(coins[0].Denom).Int64()) + suite.Require().Zero(vestinSpendableBalance.AmountOf(coin.Denom).Int64()) - coins = sdk.NewCoins(sdk.NewCoin(coins[0].Denom, types.UnboundedSpendLimit())) + coin = sdk.NewCoin(coin.Denom, types.UnboundedSpendLimit()) }, types.ErrInvalidAmount, }, @@ -191,7 +165,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() { { "failure: bank send from sender account failed, insufficient balance", func() { - coins = sdk.NewCoins(sdk.NewCoin("randomdenom", defaultAmount)) + coin = sdk.NewCoin("randomdenom", defaultAmount) }, sdkerrors.ErrInsufficientFunds, }, @@ -199,7 +173,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() { "failure: denom trace not found", func() { denom := types.NewDenom("randomdenom", types.NewHop(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)) - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount)) + coin = sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount) }, types.ErrDenomNotFound, }, @@ -207,25 +181,10 @@ func (suite *KeeperTestSuite) TestSendTransfer() { "failure: bank send from module account failed, insufficient balance", func() { denom := types.NewDenom(ibctesting.TestCoin.Denom, types.NewHop(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID)) - coins = sdk.NewCoins(sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount.Add(sdkmath.NewInt(1)))) + coin = sdk.NewCoin(denom.IBCDenom(), ibctesting.TestCoin.Amount.Add(sdkmath.NewInt(1))) }, sdkerrors.ErrInsufficientFunds, }, - { - "failure: forwarding hops is not empty with ics20-1", - func() { - // Set version to isc20-1. - path.EndpointA.UpdateChannel(func(channel *channeltypes.Channel) { - channel.Version = types.V1 - }) - - forwarding = types.NewForwarding(false, types.NewHop( - path.EndpointA.ChannelConfig.PortID, - path.EndpointA.ChannelID, - )) - }, - ibcerrors.ErrInvalidRequest, - }, } for _, tc := range testCases { @@ -238,7 +197,7 @@ func (suite *KeeperTestSuite) TestSendTransfer() { path.Setup() // create IBC token on chainA - transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, sdk.NewCoins(ibctesting.TestCoin), suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), suite.chainA.GetTimeoutHeight(), 0, "", nil) + transferMsg := types.NewMsgTransfer(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, ibctesting.TestCoin, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), suite.chainA.GetTimeoutHeight(), 0, "") result, err := suite.chainB.SendMsgs(transferMsg) suite.Require().NoError(err) // message committed @@ -250,23 +209,21 @@ func (suite *KeeperTestSuite) TestSendTransfer() { suite.Require().NoError(err) // Value that can malleated for Transfer we are testing. - coins = ibctesting.TestCoins + coin = ibctesting.TestCoin sender = suite.chainA.SenderAccount.GetAddress() memo = "" - expEscrowAmounts = []sdkmath.Int{defaultAmount, defaultAmount} - forwarding = nil + expEscrowAmount = defaultAmount tc.malleate() msg := types.NewMsgTransfer( path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, - coins, + coin, sender.String(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainB.GetTimeoutHeight(), 0, // only use timeout height memo, - forwarding, ) res, err := suite.chainA.GetSimApp().TransferKeeper.Transfer(suite.chainA.GetContext(), msg) @@ -280,10 +237,10 @@ func (suite *KeeperTestSuite) TestSendTransfer() { suite.Require().ErrorIs(err, tc.expError) // We do not expect escrowed amounts in error cases. - expEscrowAmounts = []sdkmath.Int{zeroAmount, zeroAmount} + expEscrowAmount = zeroAmount } // Assert amounts escrowed are as expected. - suite.assertEscrowEqual(suite.chainA, coins, expEscrowAmounts) + suite.assertEscrowEqual(suite.chainA, coin, expEscrowAmount) }) } } @@ -330,11 +287,10 @@ func (suite *KeeperTestSuite) TestSendTransferSetsTotalEscrowAmountForSourceIBCT transferMsg := types.NewMsgTransfer( path1.EndpointA.ChannelConfig.PortID, path1.EndpointA.ChannelID, - sdk.NewCoins(coin), + coin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), suite.chainB.GetTimeoutHeight(), 0, "", - nil, ) result, err := suite.chainA.SendMsgs(transferMsg) suite.Require().NoError(err) // message committed @@ -351,11 +307,10 @@ func (suite *KeeperTestSuite) TestSendTransferSetsTotalEscrowAmountForSourceIBCT msg := types.NewMsgTransfer( path2.EndpointB.ChannelConfig.PortID, path2.EndpointB.ChannelID, - sdk.NewCoins(coin), + coin, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), suite.chainA.GetTimeoutHeight(), 0, "", - nil, ) res, err := suite.chainB.GetSimApp().TransferKeeper.Transfer(suite.chainB.GetContext(), msg) @@ -394,7 +349,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsNotSource() { { "failure: mint zero coin", func() { - packetData.Tokens[0].Amount = zeroAmount.String() + packetData.Token.Amount = zeroAmount.String() }, types.ErrInvalidAmount, }, @@ -436,26 +391,19 @@ func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsNotSource() { receiver := suite.chainB.SenderAccount.GetAddress().String() // must be explicitly changed in malleate // send coins from chainA to chainB - transferMsg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.TestCoins, suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(1, 110), 0, "", nil) + transferMsg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(1, 110), 0, "") _, err := suite.chainA.SendMsgs(transferMsg) suite.Require().NoError(err) // message committed - var tokens []types.Token - for _, coin := range ibctesting.TestCoins { - tokens = append(tokens, types.Token{Denom: types.NewDenom(coin.Denom), Amount: coin.Amount.String()}) - } - packetData = types.NewFungibleTokenPacketDataV2(tokens, suite.chainA.SenderAccount.GetAddress().String(), receiver, "", ibctesting.EmptyForwardingPacketData) + token := types.Token{Denom: types.NewDenom(transferMsg.Token.Denom), Amount: transferMsg.Token.Amount.String()} + packetData = types.NewFungibleTokenPacketDataV2(token, suite.chainA.SenderAccount.GetAddress().String(), receiver, "") packet := channeltypes.NewPacket(packetData.GetBytes(), uint64(1), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0) tc.malleate() - var denoms []types.Denom - for _, token := range packetData.Tokens { - // construct expected denom B will construct after running Recv logic. - denoms = append(denoms, types.NewDenom(token.Denom.Base, types.NewHop(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID))) - } + denom := types.NewDenom(token.Denom.Base, types.NewHop(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)) - _, err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket( + err = suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket( suite.chainB.GetContext(), packetData, packet.SourcePort, @@ -468,22 +416,18 @@ func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsNotSource() { suite.Require().NoError(err) // Check denom metadata for of tokens received on chain B. - for _, denom := range denoms { - actualMetadata, found := suite.chainB.GetSimApp().BankKeeper.GetDenomMetaData(suite.chainB.GetContext(), denom.IBCDenom()) + actualMetadata, found := suite.chainB.GetSimApp().BankKeeper.GetDenomMetaData(suite.chainB.GetContext(), denom.IBCDenom()) - suite.Require().True(found) - suite.Require().Equal(metadataFromDenom(denom), actualMetadata) - } + suite.Require().True(found) + suite.Require().Equal(metadataFromDenom(denom), actualMetadata) } else { suite.Require().Error(err) suite.Require().ErrorIs(err, tc.expError) // Check denom metadata absence for cases where recv fails. - for _, denom := range denoms { - _, found := suite.chainB.GetSimApp().BankKeeper.GetDenomMetaData(suite.chainB.GetContext(), denom.IBCDenom()) + _, found := suite.chainB.GetSimApp().BankKeeper.GetDenomMetaData(suite.chainB.GetContext(), denom.IBCDenom()) - suite.Require().False(found) - } + suite.Require().False(found) } }) } @@ -495,8 +439,8 @@ func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsNotSource() { // for all cases. The malleate function allows for testing invalid cases. func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsSource() { var ( - packetData types.FungibleTokenPacketDataV2 - expEscrowAmounts []sdkmath.Int // total amount in escrow for denom on receiving chain + packetData types.FungibleTokenPacketDataV2 + expEscrowAmount sdkmath.Int // total amount in escrow for denom on receiving chain ) testCases := []struct { @@ -519,30 +463,30 @@ func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsSource() { { "successful receive of half the amount", func() { - packetData.Tokens[0].Amount = sdkmath.NewInt(50).String() - // expect 50 remaining for coin 1, nothing for coin 2. - expEscrowAmounts = []sdkmath.Int{sdkmath.NewInt(50), zeroAmount} + packetData.Token.Amount = sdkmath.NewInt(50).String() + // expect 50 remaining + expEscrowAmount = sdkmath.NewInt(50) }, nil, }, { "failure: empty coin", func() { - packetData.Tokens[0].Amount = zeroAmount.String() + packetData.Token.Amount = zeroAmount.String() }, types.ErrInvalidAmount, }, { "failure: tries to unescrow more tokens than allowed", func() { - packetData.Tokens[0].Amount = sdkmath.NewInt(1000000).String() + packetData.Token.Amount = sdkmath.NewInt(1000000).String() }, sdkerrors.ErrInsufficientFunds, }, { "failure: empty denom", func() { - packetData.Tokens[0].Denom = types.Denom{} + packetData.Token.Denom = types.Denom{} }, types.ErrInvalidDenomForTransfer, }, @@ -572,23 +516,20 @@ func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsSource() { path.Setup() receiver := suite.chainB.SenderAccount.GetAddress().String() // must be explicitly changed in malleate - expEscrowAmounts = []sdkmath.Int{zeroAmount, zeroAmount} // total amount in escrow of voucher denom on receiving chain + expEscrowAmount = zeroAmount // total amount in escrow of voucher denom on receiving chain // send coins from chainA to chainB, receive them, acknowledge them - transferMsg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.TestCoins, suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(1, 110), 0, "", nil) + transferMsg := types.NewMsgTransfer(path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress().String(), receiver, clienttypes.NewHeight(1, 110), 0, "") _, err := suite.chainA.SendMsgs(transferMsg) suite.Require().NoError(err) // message committed - var tokens []types.Token - for _, coin := range ibctesting.TestCoins { - tokens = append(tokens, types.Token{Denom: types.NewDenom(coin.Denom, types.NewHop(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)), Amount: coin.Amount.String()}) - } - packetData = types.NewFungibleTokenPacketDataV2(tokens, suite.chainA.SenderAccount.GetAddress().String(), receiver, "", ibctesting.EmptyForwardingPacketData) + token := types.Token{Denom: types.NewDenom(transferMsg.Token.Denom, types.NewHop(path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID)), Amount: transferMsg.Token.Amount.String()} + packetData = types.NewFungibleTokenPacketDataV2(token, suite.chainA.SenderAccount.GetAddress().String(), receiver, "") tc.malleate() packet := channeltypes.NewPacket(packetData.GetBytes(), uint64(1), path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, clienttypes.NewHeight(1, 100), 0) - _, err = suite.chainA.GetSimApp().TransferKeeper.OnRecvPacket( + err = suite.chainA.GetSimApp().TransferKeeper.OnRecvPacket( suite.chainA.GetContext(), packetData, packet.SourcePort, @@ -607,11 +548,11 @@ func (suite *KeeperTestSuite) TestOnRecvPacket_ReceiverIsSource() { suite.Require().ErrorContains(err, tc.expError.Error()) // Expect escrowed amount to stay same on failure. - expEscrowAmounts = []sdkmath.Int{defaultAmount, defaultAmount} + expEscrowAmount = defaultAmount } // Assert amounts escrowed are as expected, we do not malleate amount escrowed in initial transfer. - suite.assertEscrowEqual(suite.chainA, ibctesting.TestCoins, expEscrowAmounts) + suite.assertEscrowEqual(suite.chainA, ibctesting.TestCoin, expEscrowAmount) }) } } @@ -666,12 +607,10 @@ func (suite *KeeperTestSuite) TestOnRecvPacketSetsTotalEscrowAmountForSourceIBCT ) data := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: denom, - Amount: amount.String(), - }, - }, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), "", ibctesting.EmptyForwardingPacketData) + types.Token{ + Denom: denom, + Amount: amount.String(), + }, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), "") packet := channeltypes.NewPacket( data.GetBytes(), seq, @@ -705,7 +644,7 @@ func (suite *KeeperTestSuite) TestOnRecvPacketSetsTotalEscrowAmountForSourceIBCT suite.Require().Equal(defaultAmount, totalEscrowChainB.Amount) // execute onRecvPacket, when chaninB receives the source token the escrow amount should decrease - _, err := suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket( + err := suite.chainB.GetSimApp().TransferKeeper.OnRecvPacket( suite.chainB.GetContext(), data, packet.SourcePort, @@ -804,12 +743,10 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacket() { tc.malleate() data := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: denom, - Amount: amount.String(), - }, - }, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), "", ibctesting.EmptyForwardingPacketData) + types.Token{ + Denom: denom, + Amount: amount.String(), + }, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), "") packet := channeltypes.NewPacket(data.GetBytes(), 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0) preAcknowledgementBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), denom.IBCDenom()) @@ -894,16 +831,13 @@ func (suite *KeeperTestSuite) TestOnAcknowledgementPacketSetsTotalEscrowAmountFo ) data := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: denom, - Amount: amount.String(), - }, + types.Token{ + Denom: denom, + Amount: amount.String(), }, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), "", - ibctesting.EmptyForwardingPacketData, ) packet := channeltypes.NewPacket( data.GetBytes(), @@ -1038,12 +972,10 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacket() { tc.malleate() data := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: denom, - Amount: amount, - }, - }, sender, suite.chainB.SenderAccount.GetAddress().String(), "", ibctesting.EmptyForwardingPacketData) + types.Token{ + Denom: denom, + Amount: amount, + }, sender, suite.chainB.SenderAccount.GetAddress().String(), "") packet := channeltypes.NewPacket(data.GetBytes(), 1, path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, path.EndpointB.ChannelConfig.PortID, path.EndpointB.ChannelID, clienttypes.NewHeight(1, 100), 0) preTimeoutBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), denom.IBCDenom()) @@ -1123,12 +1055,10 @@ func (suite *KeeperTestSuite) TestOnTimeoutPacketSetsTotalEscrowAmountForSourceI ) data := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: denom, - Amount: amount.String(), - }, - }, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), "", ibctesting.EmptyForwardingPacketData) + types.Token{ + Denom: denom, + Amount: amount.String(), + }, suite.chainB.SenderAccount.GetAddress().String(), suite.chainA.SenderAccount.GetAddress().String(), "") packet := channeltypes.NewPacket( data.GetBytes(), seq, @@ -1256,7 +1186,7 @@ func (suite *KeeperTestSuite) TestPacketForwardsCompatibility() { func (suite *KeeperTestSuite) TestCreatePacketDataBytesFromVersion() { var ( - tokens types.Tokens + token types.Token sender, receiver string ) @@ -1277,13 +1207,12 @@ func (suite *KeeperTestSuite) TestCreatePacketDataBytesFromVersion() { }, }, { - "success: version 2", - types.V2, + "failure: version 2", + "ics20-2", func() {}, func(bz []byte, err error) { - expPacketData := types.NewFungibleTokenPacketDataV2(tokens, sender, receiver, "", ibctesting.EmptyForwardingPacketData) - suite.Require().Equal(bz, expPacketData.GetBytes()) - suite.Require().NoError(err) + suite.Require().Nil(bz) + suite.Require().Error(err, ibcerrors.ErrInvalidVersion) }, }, { @@ -1297,28 +1226,6 @@ func (suite *KeeperTestSuite) TestCreatePacketDataBytesFromVersion() { suite.Require().ErrorIs(err, ibcerrors.ErrInvalidAddress) }, }, - { - "failure: fails v2 validation", - types.V2, - func() { - sender = "" - }, - func(bz []byte, err error) { - suite.Require().Nil(bz) - suite.Require().ErrorIs(err, ibcerrors.ErrInvalidAddress) - }, - }, - { - "failure: must have single coin if using version 1.", - types.V1, - func() { - tokens = types.Tokens{} - }, - func(bz []byte, err error) { - suite.Require().Nil(bz) - suite.Require().ErrorIs(err, ibcerrors.ErrInvalidRequest) - }, - }, { "failure: invalid version", ibcmock.Version, @@ -1337,11 +1244,9 @@ func (suite *KeeperTestSuite) TestCreatePacketDataBytesFromVersion() { path := ibctesting.NewTransferPath(suite.chainA, suite.chainB) path.Setup() - tokens = types.Tokens{ - { - Amount: ibctesting.TestCoin.Amount.String(), - Denom: types.NewDenom(ibctesting.TestCoin.Denom), - }, + token = types.Token{ + Amount: ibctesting.TestCoin.Amount.String(), + Denom: types.NewDenom(ibctesting.TestCoin.Denom), } sender = suite.chainA.SenderAccount.GetAddress().String() @@ -1349,7 +1254,7 @@ func (suite *KeeperTestSuite) TestCreatePacketDataBytesFromVersion() { tc.malleate() - bz, err := transferkeeper.CreatePacketDataBytesFromVersion(tc.appVersion, sender, receiver, "", tokens, nil) + bz, err := transferkeeper.CreatePacketDataBytesFromVersion(tc.appVersion, sender, receiver, "", token) tc.expResult(bz, err) }) @@ -1374,9 +1279,7 @@ func metadataFromDenom(denom types.Denom) banktypes.Metadata { } // assertEscrowEqual asserts that the amounts escrowed for each of the coins on chain matches the expectedAmounts -func (suite *KeeperTestSuite) assertEscrowEqual(chain *ibctesting.TestChain, coins sdk.Coins, expectedAmounts []sdkmath.Int) { - for i, coin := range coins { - amount := chain.GetSimApp().TransferKeeper.GetTotalEscrowForDenom(chain.GetContext(), coin.GetDenom()) - suite.Require().Equal(expectedAmounts[i], amount.Amount) - } +func (suite *KeeperTestSuite) assertEscrowEqual(chain *ibctesting.TestChain, coin sdk.Coin, expectedAmount sdkmath.Int) { + amount := chain.GetSimApp().TransferKeeper.GetTotalEscrowForDenom(chain.GetContext(), coin.GetDenom()) + suite.Require().Equal(expectedAmount, amount.Amount) } diff --git a/modules/apps/transfer/transfer_test.go b/modules/apps/transfer/transfer_test.go index cd8e78d47d4..8a98e4ac805 100644 --- a/modules/apps/transfer/transfer_test.go +++ b/modules/apps/transfer/transfer_test.go @@ -38,8 +38,8 @@ func (suite *TransferTestSuite) SetupTest() { // 3 - from chainC to chainB func (suite *TransferTestSuite) TestHandleMsgTransfer() { var ( - sourceDenomsToTransfer []string - msgAmount sdkmath.Int + sourceDenomToTransfer string + msgAmount sdkmath.Int ) testCases := []struct { @@ -58,12 +58,6 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { suite.Require().True(ok) }, }, - { - "transfer multiple denoms", - func() { - sourceDenomsToTransfer = []string{sdk.DefaultBondDenom, ibctesting.SecondaryDenom} - }, - }, { "transfer entire balance", func() { @@ -84,27 +78,19 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { pathAToB.Setup() traceAToB := types.NewHop(pathAToB.EndpointB.ChannelConfig.PortID, pathAToB.EndpointB.ChannelID) - sourceDenomsToTransfer = []string{sdk.DefaultBondDenom} + sourceDenomToTransfer = sdk.DefaultBondDenom msgAmount = ibctesting.DefaultCoinAmount tc.malleate() - originalBalances := sdk.NewCoins() - for _, denom := range sourceDenomsToTransfer { - originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), denom) - originalBalances = originalBalances.Add(originalBalance) - } + originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), sourceDenomToTransfer) timeoutHeight := clienttypes.NewHeight(1, 110) - originalCoins := sdk.NewCoins() - for _, denom := range sourceDenomsToTransfer { - coinToSendToB := sdk.NewCoin(denom, msgAmount) - originalCoins = originalCoins.Add(coinToSendToB) - } + originalCoin := sdk.NewCoin(sourceDenomToTransfer, msgAmount) // send from chainA to chainB - msg := types.NewMsgTransfer(pathAToB.EndpointA.ChannelConfig.PortID, pathAToB.EndpointA.ChannelID, originalCoins, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0, "", nil) + msg := types.NewMsgTransfer(pathAToB.EndpointA.ChannelConfig.PortID, pathAToB.EndpointA.ChannelID, originalCoin, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0, "") res, err := suite.chainA.SendMsgs(msg) suite.Require().NoError(err) // message committed @@ -114,7 +100,7 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { // Get the packet data to determine the amount of tokens being transferred (needed for sending entire balance) packetData, err := types.UnmarshalPacketData(packet.GetData(), pathAToB.EndpointA.GetChannel().Version, "") suite.Require().NoError(err) - transferAmount, ok := sdkmath.NewIntFromString(packetData.Tokens[0].Amount) + transferAmount, ok := sdkmath.NewIntFromString(packetData.Token.Amount) suite.Require().True(ok) // relay send @@ -122,24 +108,19 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { suite.Require().NoError(err) // relay committed escrowAddress := types.GetEscrowAddress(packet.GetSourcePort(), packet.GetSourceChannel()) - coinsSentFromAToB := sdk.NewCoins() - for _, coin := range originalCoins { - // check that the balance for chainA is updated - chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), coin.Denom) - suite.Require().True(originalBalances.AmountOf(coin.Denom).Sub(transferAmount).Equal(chainABalance.Amount)) - - // check that module account escrow address has locked the tokens - chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, coin.Denom) - suite.Require().True(transferAmount.Equal(chainAEscrowBalance.Amount)) - - // check that voucher exists on chain B - chainBDenom := types.NewDenom(coin.Denom, traceAToB) - chainBBalance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), chainBDenom.IBCDenom()) - coinSentFromAToB := sdk.NewCoin(chainBDenom.IBCDenom(), transferAmount) - suite.Require().Equal(coinSentFromAToB, chainBBalance) - - coinsSentFromAToB = coinsSentFromAToB.Add(coinSentFromAToB) - } + // check that the balance for chainA is updated + chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), originalCoin.Denom) + suite.Require().True(originalBalance.Amount.Sub(transferAmount).Equal(chainABalance.Amount)) + + // check that module account escrow address has locked the tokens + chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, originalCoin.Denom) + suite.Require().True(transferAmount.Equal(chainAEscrowBalance.Amount)) + + // check that voucher exists on chain B + chainBDenom := types.NewDenom(originalCoin.Denom, traceAToB) + chainBBalance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), chainBDenom.IBCDenom()) + coinSentFromAToB := sdk.NewCoin(chainBDenom.IBCDenom(), transferAmount) + suite.Require().Equal(coinSentFromAToB, chainBBalance) // setup between chainB to chainC // NOTE: @@ -150,7 +131,7 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { traceBToC := types.NewHop(pathBToC.EndpointB.ChannelConfig.PortID, pathBToC.EndpointB.ChannelID) // send from chainB to chainC - msg = types.NewMsgTransfer(pathBToC.EndpointA.ChannelConfig.PortID, pathBToC.EndpointA.ChannelID, coinsSentFromAToB, suite.chainB.SenderAccount.GetAddress().String(), suite.chainC.SenderAccount.GetAddress().String(), timeoutHeight, 0, "", nil) + msg = types.NewMsgTransfer(pathBToC.EndpointA.ChannelConfig.PortID, pathBToC.EndpointA.ChannelID, coinSentFromAToB, suite.chainB.SenderAccount.GetAddress().String(), suite.chainC.SenderAccount.GetAddress().String(), timeoutHeight, 0, "") res, err = suite.chainB.SendMsgs(msg) suite.Require().NoError(err) // message committed @@ -162,24 +143,20 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { coinsSentFromBToC := sdk.NewCoins() // check balances for chainB and chainC after transfer from chainB to chainC - for _, coin := range originalCoins { - // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment - chainCDenom := types.NewDenom(coin.Denom, traceBToC, traceAToB) + // NOTE: fungible token is prefixed with the full trace in order to verify the packet commitment + chainCDenom := types.NewDenom(originalCoin.Denom, traceBToC, traceAToB) - // check that the balance is updated on chainC - coinSentFromBToC := sdk.NewCoin(chainCDenom.IBCDenom(), transferAmount) - chainCBalance := suite.chainC.GetSimApp().BankKeeper.GetBalance(suite.chainC.GetContext(), suite.chainC.SenderAccount.GetAddress(), coinSentFromBToC.Denom) - suite.Require().Equal(coinSentFromBToC, chainCBalance) + // check that the balance is updated on chainC + coinSentFromBToC := sdk.NewCoin(chainCDenom.IBCDenom(), transferAmount) + chainCBalance := suite.chainC.GetSimApp().BankKeeper.GetBalance(suite.chainC.GetContext(), suite.chainC.SenderAccount.GetAddress(), coinSentFromBToC.Denom) + suite.Require().Equal(coinSentFromBToC, chainCBalance) - // check that balance on chain B is empty - chainBBalance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), coinSentFromBToC.Denom) - suite.Require().Zero(chainBBalance.Amount.Int64()) - - coinsSentFromBToC = coinsSentFromBToC.Add(coinSentFromBToC) - } + // check that balance on chain B is empty + chainBBalance = suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), coinSentFromBToC.Denom) + suite.Require().Zero(chainBBalance.Amount.Int64()) // send from chainC back to chainB - msg = types.NewMsgTransfer(pathBToC.EndpointB.ChannelConfig.PortID, pathBToC.EndpointB.ChannelID, coinsSentFromBToC, suite.chainC.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0, "", nil) + msg = types.NewMsgTransfer(pathBToC.EndpointB.ChannelConfig.PortID, pathBToC.EndpointB.ChannelID, coinSentFromBToC, suite.chainC.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), timeoutHeight, 0, "") res, err = suite.chainC.SendMsgs(msg) suite.Require().NoError(err) // message committed @@ -197,28 +174,24 @@ func (suite *TransferTestSuite) TestHandleMsgTransfer() { } // check balances for chainB after transfer from chainC to chainB - for _, coin := range coinsSentFromAToB { - // check that balance on chain B has the transferred amount - chainBBalance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), coin.Denom) - suite.Require().Equal(coin, chainBBalance) - - // check that module account escrow address is empty - escrowAddress = types.GetEscrowAddress(traceBToC.PortId, traceBToC.ChannelId) - chainBEscrowBalance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), escrowAddress, coin.Denom) - suite.Require().Zero(chainBEscrowBalance.Amount.Int64()) - } + // check that balance on chain B has the transferred amount + chainBBalance = suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), coinSentFromAToB.Denom) + suite.Require().Equal(coinSentFromAToB, chainBBalance) + + // check that module account escrow address is empty + escrowAddress = types.GetEscrowAddress(traceBToC.PortId, traceBToC.ChannelId) + chainBEscrowBalance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), escrowAddress, coinSentFromAToB.Denom) + suite.Require().Zero(chainBEscrowBalance.Amount.Int64()) // check balances for chainA after transfer from chainC to chainB - for _, coin := range originalCoins { - // check that the balance is unchanged - chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), coin.Denom) - suite.Require().True(originalBalances.AmountOf(coin.Denom).Sub(transferAmount).Equal(chainABalance.Amount)) - - // check that module account escrow address is unchanged - escrowAddress = types.GetEscrowAddress(pathAToB.EndpointA.ChannelConfig.PortID, pathAToB.EndpointA.ChannelID) - chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, coin.Denom) - suite.Require().True(transferAmount.Equal(chainAEscrowBalance.Amount)) - } + // check that the balance is unchanged + chainABalance = suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), originalCoin.Denom) + suite.Require().True(originalBalance.Amount.Sub(transferAmount).Equal(chainABalance.Amount)) + + // check that module account escrow address is unchanged + escrowAddress = types.GetEscrowAddress(pathAToB.EndpointA.ChannelConfig.PortID, pathAToB.EndpointA.ChannelID) + chainAEscrowBalance = suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, originalCoin.Denom) + suite.Require().True(transferAmount.Equal(chainAEscrowBalance.Amount)) }) } } diff --git a/modules/apps/transfer/types/authz.pb.go b/modules/apps/transfer/types/authz.pb.go index babcacc9d10..5032ca413d8 100644 --- a/modules/apps/transfer/types/authz.pb.go +++ b/modules/apps/transfer/types/authz.pb.go @@ -39,8 +39,6 @@ type Allocation struct { // allow list of memo strings, an empty list prohibits all memo strings; // a list only with "*" permits any memo string AllowedPacketData []string `protobuf:"bytes,5,rep,name=allowed_packet_data,json=allowedPacketData,proto3" json:"allowed_packet_data,omitempty"` - // Forwarding options that are allowed. - AllowedForwarding []AllowedForwarding `protobuf:"bytes,6,rep,name=allowed_forwarding,json=allowedForwarding,proto3" json:"allowed_forwarding"` } func (m *Allocation) Reset() { *m = Allocation{} } @@ -111,60 +109,6 @@ func (m *Allocation) GetAllowedPacketData() []string { return nil } -func (m *Allocation) GetAllowedForwarding() []AllowedForwarding { - if m != nil { - return m.AllowedForwarding - } - return nil -} - -// AllowedForwarding defines which options are allowed for forwarding. -type AllowedForwarding struct { - // a list of allowed source port ID/channel ID pairs through which the packet is allowed to be forwarded until final - // destination - Hops []Hop `protobuf:"bytes,1,rep,name=hops,proto3" json:"hops"` -} - -func (m *AllowedForwarding) Reset() { *m = AllowedForwarding{} } -func (m *AllowedForwarding) String() string { return proto.CompactTextString(m) } -func (*AllowedForwarding) ProtoMessage() {} -func (*AllowedForwarding) Descriptor() ([]byte, []int) { - return fileDescriptor_b1a28b55d17325aa, []int{1} -} -func (m *AllowedForwarding) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *AllowedForwarding) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_AllowedForwarding.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *AllowedForwarding) XXX_Merge(src proto.Message) { - xxx_messageInfo_AllowedForwarding.Merge(m, src) -} -func (m *AllowedForwarding) XXX_Size() int { - return m.Size() -} -func (m *AllowedForwarding) XXX_DiscardUnknown() { - xxx_messageInfo_AllowedForwarding.DiscardUnknown(m) -} - -var xxx_messageInfo_AllowedForwarding proto.InternalMessageInfo - -func (m *AllowedForwarding) GetHops() []Hop { - if m != nil { - return m.Hops - } - return nil -} - // TransferAuthorization allows the grantee to spend up to spend_limit coins from // the granter's account for ibc transfer on a specific channel type TransferAuthorization struct { @@ -176,7 +120,7 @@ func (m *TransferAuthorization) Reset() { *m = TransferAuthorization{} } func (m *TransferAuthorization) String() string { return proto.CompactTextString(m) } func (*TransferAuthorization) ProtoMessage() {} func (*TransferAuthorization) Descriptor() ([]byte, []int) { - return fileDescriptor_b1a28b55d17325aa, []int{2} + return fileDescriptor_b1a28b55d17325aa, []int{1} } func (m *TransferAuthorization) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -214,7 +158,6 @@ func (m *TransferAuthorization) GetAllocations() []Allocation { func init() { proto.RegisterType((*Allocation)(nil), "ibc.applications.transfer.v1.Allocation") - proto.RegisterType((*AllowedForwarding)(nil), "ibc.applications.transfer.v1.AllowedForwarding") proto.RegisterType((*TransferAuthorization)(nil), "ibc.applications.transfer.v1.TransferAuthorization") } @@ -223,38 +166,35 @@ func init() { } var fileDescriptor_b1a28b55d17325aa = []byte{ - // 496 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x92, 0x4f, 0x8b, 0xd3, 0x40, - 0x18, 0xc6, 0x9b, 0x6d, 0x5d, 0xe8, 0x14, 0x85, 0x8d, 0x0a, 0xd9, 0x45, 0xd3, 0x5a, 0x50, 0x02, - 0xd2, 0x19, 0xab, 0x07, 0x51, 0x4f, 0xed, 0x8a, 0x78, 0xd8, 0x43, 0x2d, 0x9e, 0xbc, 0x84, 0xc9, - 0x64, 0xb6, 0x19, 0x76, 0x9a, 0x37, 0x64, 0x26, 0x5d, 0xdc, 0x4f, 0xa1, 0x5f, 0xc3, 0xb3, 0x1f, - 0x62, 0xf1, 0xb4, 0x47, 0x4f, 0x2a, 0xed, 0x87, 0xf0, 0x2a, 0x99, 0x99, 0xd6, 0xca, 0x42, 0x3d, - 0xb5, 0xf3, 0xbc, 0xbf, 0xf7, 0x5f, 0x9e, 0x17, 0x45, 0x22, 0x61, 0x84, 0x16, 0x85, 0x14, 0x8c, - 0x6a, 0x01, 0xb9, 0x22, 0xba, 0xa4, 0xb9, 0x3a, 0xe5, 0x25, 0x59, 0x0c, 0x09, 0xad, 0x74, 0x76, - 0x81, 0x8b, 0x12, 0x34, 0xf8, 0xf7, 0x44, 0xc2, 0xf0, 0x36, 0x89, 0xd7, 0x24, 0x5e, 0x0c, 0x8f, - 0x0e, 0x19, 0xa8, 0x39, 0xa8, 0xd8, 0xb0, 0xc4, 0x3e, 0x6c, 0xe2, 0xd1, 0x9d, 0x19, 0xcc, 0xc0, - 0xea, 0xf5, 0x3f, 0xa7, 0x86, 0x96, 0x21, 0x09, 0x55, 0x9c, 0x2c, 0x86, 0x09, 0xd7, 0x74, 0x48, - 0x18, 0x88, 0xdc, 0xc5, 0x1f, 0xef, 0x1c, 0x6c, 0xd3, 0xda, 0xc0, 0xfd, 0xdf, 0x7b, 0x08, 0x8d, - 0xa4, 0x04, 0x8b, 0xfa, 0x5d, 0xd4, 0x51, 0x50, 0x95, 0x8c, 0xc7, 0x05, 0x94, 0x3a, 0xf0, 0x7a, - 0x5e, 0xd4, 0x9e, 0x22, 0x2b, 0x4d, 0xa0, 0xd4, 0xfe, 0x43, 0x74, 0xcb, 0x01, 0x2c, 0xa3, 0x79, - 0xce, 0x65, 0xb0, 0x67, 0x98, 0x9b, 0x56, 0x3d, 0xb6, 0xa2, 0x2f, 0x51, 0x47, 0x15, 0x3c, 0x4f, - 0x63, 0x29, 0xe6, 0x42, 0x07, 0xcd, 0x5e, 0x33, 0xea, 0x3c, 0x3d, 0xc4, 0x6e, 0xbb, 0x7a, 0x72, - 0xec, 0x26, 0xc7, 0xc7, 0x20, 0xf2, 0xf1, 0x93, 0xcb, 0x1f, 0xdd, 0xc6, 0x97, 0x9f, 0xdd, 0x68, - 0x26, 0x74, 0x56, 0x25, 0x98, 0xc1, 0xdc, 0x7d, 0x0a, 0xf7, 0x33, 0x50, 0xe9, 0x19, 0xd1, 0x1f, - 0x0b, 0xae, 0x4c, 0x82, 0x9a, 0x22, 0x53, 0xff, 0xa4, 0x2e, 0xef, 0xdf, 0x47, 0x88, 0x4a, 0x09, - 0xe7, 0xb1, 0x14, 0x4a, 0x07, 0xad, 0x5e, 0x33, 0x6a, 0x4f, 0xdb, 0x46, 0x39, 0x11, 0x4a, 0xfb, - 0x18, 0xdd, 0x36, 0x0f, 0x9e, 0xc6, 0x05, 0x65, 0x67, 0x5c, 0xc7, 0x29, 0xd5, 0x34, 0xb8, 0x61, - 0xb8, 0x03, 0x17, 0x9a, 0x98, 0xc8, 0x6b, 0xaa, 0xa9, 0x9f, 0x22, 0x7f, 0xcd, 0x9f, 0x42, 0x79, - 0x4e, 0xcb, 0x54, 0xe4, 0xb3, 0x60, 0xdf, 0xec, 0x40, 0xf0, 0x2e, 0x33, 0xf1, 0xc8, 0xe6, 0xbd, - 0xd9, 0xa4, 0x8d, 0x5b, 0xf5, 0x66, 0x9b, 0x2e, 0x7f, 0x03, 0xfd, 0x09, 0x3a, 0xb8, 0x46, 0xfb, - 0xaf, 0x50, 0x2b, 0x83, 0x42, 0x05, 0x9e, 0x69, 0xf6, 0x60, 0x77, 0xb3, 0xb7, 0x50, 0xb8, 0xf2, - 0x26, 0xa9, 0xff, 0xd9, 0x43, 0x77, 0xdf, 0xbb, 0xf8, 0xa8, 0xd2, 0x19, 0x94, 0xe2, 0xc2, 0xda, - 0x3a, 0x41, 0x1d, 0xba, 0x31, 0x79, 0x5d, 0x3d, 0xfa, 0xff, 0x2a, 0x56, 0x77, 0x4d, 0xb6, 0x4b, - 0xbc, 0x7c, 0xf4, 0xed, 0xeb, 0xa0, 0xef, 0xec, 0xb4, 0xb7, 0xbe, 0xf6, 0xf3, 0x9f, 0xce, 0xe3, - 0x77, 0x97, 0xcb, 0xd0, 0xbb, 0x5a, 0x86, 0xde, 0xaf, 0x65, 0xe8, 0x7d, 0x5a, 0x85, 0x8d, 0xab, - 0x55, 0xd8, 0xf8, 0xbe, 0x0a, 0x1b, 0x1f, 0x9e, 0x5f, 0xb7, 0x5a, 0x24, 0x6c, 0x30, 0x03, 0xb2, - 0x78, 0x41, 0xe6, 0x90, 0x56, 0x92, 0xab, 0xfa, 0x8c, 0xb7, 0xce, 0xd7, 0xf8, 0x9f, 0xec, 0x9b, - 0xcb, 0x7d, 0xf6, 0x27, 0x00, 0x00, 0xff, 0xff, 0x66, 0x4e, 0x45, 0x23, 0x81, 0x03, 0x00, 0x00, + // 443 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x4f, 0x6f, 0xd3, 0x30, + 0x18, 0xc6, 0x9b, 0x75, 0x20, 0xd5, 0x15, 0x48, 0x04, 0x90, 0xb2, 0x09, 0xd2, 0xaa, 0x12, 0x28, + 0x12, 0xaa, 0x4d, 0xe1, 0x80, 0xe0, 0xb6, 0x8e, 0xe3, 0x0e, 0xa5, 0xe2, 0xc4, 0x25, 0x72, 0x1c, + 0xd3, 0x5a, 0x73, 0xf2, 0x46, 0xf1, 0x9b, 0x20, 0xf6, 0x29, 0xd8, 0xd7, 0xe0, 0xcc, 0x87, 0x98, + 0x38, 0xed, 0xc8, 0x09, 0x50, 0xfb, 0x45, 0x50, 0x6c, 0x6f, 0x14, 0x21, 0xed, 0x94, 0xf8, 0x79, + 0x1f, 0xbf, 0x7f, 0x7e, 0x7e, 0x49, 0xa2, 0x32, 0xc1, 0x78, 0x55, 0x69, 0x25, 0x38, 0x2a, 0x28, + 0x0d, 0xc3, 0x9a, 0x97, 0xe6, 0xa3, 0xac, 0x59, 0x3b, 0x63, 0xbc, 0xc1, 0xf5, 0x19, 0xad, 0x6a, + 0x40, 0x08, 0x1f, 0xa9, 0x4c, 0xd0, 0x5d, 0x27, 0xbd, 0x72, 0xd2, 0x76, 0x76, 0x78, 0x20, 0xc0, + 0x14, 0x60, 0x52, 0xeb, 0x65, 0xee, 0xe0, 0x2e, 0x1e, 0x3e, 0x58, 0xc1, 0x0a, 0x9c, 0xde, 0xfd, + 0x79, 0x35, 0x76, 0x1e, 0x96, 0x71, 0x23, 0x59, 0x3b, 0xcb, 0x24, 0xf2, 0x19, 0x13, 0xa0, 0x4a, + 0x1f, 0x7f, 0x76, 0x63, 0x63, 0xd7, 0xa5, 0xad, 0x79, 0x72, 0xbe, 0x47, 0xc8, 0x91, 0xd6, 0xe0, + 0xac, 0xe1, 0x88, 0x0c, 0x0d, 0x34, 0xb5, 0x90, 0x69, 0x05, 0x35, 0x46, 0xc1, 0x38, 0x48, 0x06, + 0x4b, 0xe2, 0xa4, 0x05, 0xd4, 0x18, 0x3e, 0x21, 0x77, 0xbd, 0x41, 0xac, 0x79, 0x59, 0x4a, 0x1d, + 0xed, 0x59, 0xcf, 0x1d, 0xa7, 0x1e, 0x3b, 0x31, 0xd4, 0x64, 0x68, 0x2a, 0x59, 0xe6, 0xa9, 0x56, + 0x85, 0xc2, 0xa8, 0x3f, 0xee, 0x27, 0xc3, 0x17, 0x07, 0xd4, 0x4f, 0xd7, 0x75, 0x4e, 0x7d, 0xe7, + 0xf4, 0x18, 0x54, 0x39, 0x7f, 0x7e, 0xf1, 0x73, 0xd4, 0xfb, 0xfa, 0x6b, 0x94, 0xac, 0x14, 0xae, + 0x9b, 0x8c, 0x0a, 0x28, 0x3c, 0x0a, 0xff, 0x99, 0x9a, 0xfc, 0x94, 0xe1, 0xe7, 0x4a, 0x1a, 0x7b, + 0xc1, 0x2c, 0x89, 0xcd, 0x7f, 0xd2, 0xa5, 0x0f, 0x1f, 0x13, 0xc2, 0xb5, 0x86, 0x4f, 0xa9, 0x56, + 0x06, 0xa3, 0xfd, 0x71, 0x3f, 0x19, 0x2c, 0x07, 0x56, 0x39, 0x51, 0x06, 0x43, 0x4a, 0xee, 0xdb, + 0x83, 0xcc, 0xd3, 0x8a, 0x8b, 0x53, 0x89, 0x69, 0xce, 0x91, 0x47, 0xb7, 0xac, 0xef, 0x9e, 0x0f, + 0x2d, 0x6c, 0xe4, 0x2d, 0x47, 0x3e, 0x39, 0x0f, 0xc8, 0xc3, 0xf7, 0x1e, 0xd3, 0x51, 0x83, 0x6b, + 0xa8, 0xd5, 0x99, 0xc3, 0xb3, 0x20, 0x43, 0x7e, 0x0d, 0xcb, 0x44, 0x81, 0x1d, 0x2b, 0xa1, 0x37, + 0xbd, 0x2f, 0xfd, 0x4b, 0x77, 0xbe, 0xdf, 0x4d, 0xb9, 0xdc, 0x4d, 0xf1, 0xe6, 0xe9, 0xf7, 0x6f, + 0xd3, 0x89, 0xc7, 0xe2, 0x76, 0xe6, 0x8a, 0xcb, 0x3f, 0x95, 0xe7, 0xef, 0x2e, 0x36, 0x71, 0x70, + 0xb9, 0x89, 0x83, 0xdf, 0x9b, 0x38, 0xf8, 0xb2, 0x8d, 0x7b, 0x97, 0xdb, 0xb8, 0xf7, 0x63, 0x1b, + 0xf7, 0x3e, 0xbc, 0xfa, 0x1f, 0x99, 0xca, 0xc4, 0x74, 0x05, 0xac, 0x7d, 0xcd, 0x0a, 0xc8, 0x1b, + 0x2d, 0x4d, 0xb7, 0x0e, 0x3b, 0x6b, 0x60, 0x39, 0x66, 0xb7, 0xed, 0x06, 0xbc, 0xfc, 0x13, 0x00, + 0x00, 0xff, 0xff, 0x89, 0xe3, 0xe3, 0x15, 0xc9, 0x02, 0x00, 0x00, } func (m *Allocation) Marshal() (dAtA []byte, err error) { @@ -277,20 +217,6 @@ func (m *Allocation) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.AllowedForwarding) > 0 { - for iNdEx := len(m.AllowedForwarding) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.AllowedForwarding[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintAuthz(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x32 - } - } if len(m.AllowedPacketData) > 0 { for iNdEx := len(m.AllowedPacketData) - 1; iNdEx >= 0; iNdEx-- { i -= len(m.AllowedPacketData[iNdEx]) @@ -340,43 +266,6 @@ func (m *Allocation) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *AllowedForwarding) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *AllowedForwarding) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *AllowedForwarding) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Hops) > 0 { - for iNdEx := len(m.Hops) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Hops[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintAuthz(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - func (m *TransferAuthorization) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -457,27 +346,6 @@ func (m *Allocation) Size() (n int) { n += 1 + l + sovAuthz(uint64(l)) } } - if len(m.AllowedForwarding) > 0 { - for _, e := range m.AllowedForwarding { - l = e.Size() - n += 1 + l + sovAuthz(uint64(l)) - } - } - return n -} - -func (m *AllowedForwarding) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if len(m.Hops) > 0 { - for _, e := range m.Hops { - l = e.Size() - n += 1 + l + sovAuthz(uint64(l)) - } - } return n } @@ -693,124 +561,6 @@ func (m *Allocation) Unmarshal(dAtA []byte) error { } m.AllowedPacketData = append(m.AllowedPacketData, string(dAtA[iNdEx:postIndex])) iNdEx = postIndex - case 6: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowedForwarding", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAuthz - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthAuthz - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthAuthz - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.AllowedForwarding = append(m.AllowedForwarding, AllowedForwarding{}) - if err := m.AllowedForwarding[len(m.AllowedForwarding)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipAuthz(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthAuthz - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *AllowedForwarding) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAuthz - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: AllowedForwarding: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: AllowedForwarding: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Hops", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowAuthz - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthAuthz - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthAuthz - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Hops = append(m.Hops, Hop{}) - if err := m.Hops[len(m.Hops)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipAuthz(dAtA[iNdEx:]) diff --git a/modules/apps/transfer/types/errors.go b/modules/apps/transfer/types/errors.go index 39b01b0e373..34a43dd8c62 100644 --- a/modules/apps/transfer/types/errors.go +++ b/modules/apps/transfer/types/errors.go @@ -16,10 +16,9 @@ var ( ErrMaxTransferChannels = errorsmod.Register(ModuleName, 9, "max transfer channels") ErrInvalidAuthorization = errorsmod.Register(ModuleName, 10, "invalid transfer authorization") ErrInvalidMemo = errorsmod.Register(ModuleName, 11, "invalid memo") - ErrInvalidForwarding = errorsmod.Register(ModuleName, 12, "invalid token forwarding") - ErrForwardedPacketTimedOut = errorsmod.Register(ModuleName, 13, "forwarded packet timed out") - ErrForwardedPacketFailed = errorsmod.Register(ModuleName, 14, "forwarded packet failed") - ErrAbiEncoding = errorsmod.Register(ModuleName, 15, "encoding abi failed") - ErrAbiDecoding = errorsmod.Register(ModuleName, 16, "decoding abi failed") - ErrReceiveFailed = errorsmod.Register(ModuleName, 17, "receive packet failed") + ErrForwardedPacketTimedOut = errorsmod.Register(ModuleName, 12, "forwarded packet timed out") + ErrForwardedPacketFailed = errorsmod.Register(ModuleName, 13, "forwarded packet failed") + ErrAbiEncoding = errorsmod.Register(ModuleName, 14, "encoding abi failed") + ErrAbiDecoding = errorsmod.Register(ModuleName, 15, "decoding abi failed") + ErrReceiveFailed = errorsmod.Register(ModuleName, 16, "receive packet failed") ) diff --git a/modules/apps/transfer/types/events.go b/modules/apps/transfer/types/events.go index f5ad7210431..d921572b4e2 100644 --- a/modules/apps/transfer/types/events.go +++ b/modules/apps/transfer/types/events.go @@ -12,12 +12,11 @@ const ( AttributeKeyReceiver = "receiver" AttributeKeyDenom = "denom" AttributeKeyDenomHash = "denom_hash" - AttributeKeyTokens = "tokens" + AttributeKeyAmount = "amount" AttributeKeyRefundReceiver = "refund_receiver" AttributeKeyRefundTokens = "refund_tokens" AttributeKeyAckSuccess = "success" AttributeKeyAck = "acknowledgement" AttributeKeyAckError = "error" AttributeKeyMemo = "memo" - AttributeKeyForwardingHops = "forwarding_hops" ) diff --git a/modules/apps/transfer/types/forwarding.go b/modules/apps/transfer/types/forwarding.go deleted file mode 100644 index 7fa75e11c2c..00000000000 --- a/modules/apps/transfer/types/forwarding.go +++ /dev/null @@ -1,93 +0,0 @@ -package types - -import ( - "fmt" - - errorsmod "cosmossdk.io/errors" - - host "github.com/cosmos/ibc-go/v9/modules/core/24-host" -) - -const MaximumNumberOfForwardingHops = 8 // denotes the maximum number of forwarding hops allowed - -// NewForwarding creates a new Forwarding instance given an unwind value and a variable number of hops. -func NewForwarding(unwind bool, hops ...Hop) *Forwarding { - return &Forwarding{ - Unwind: unwind, - Hops: hops, - } -} - -// Validate performs a basic validation of the Forwarding fields. -func (f Forwarding) Validate() error { - if err := validateHops(f.GetHops()); err != nil { - return errorsmod.Wrapf(ErrInvalidForwarding, "invalid hops in forwarding") - } - - return nil -} - -// NewForwardingPacketData creates a new ForwardingPacketData instance given a memo and a variable number of hops. -func NewForwardingPacketData(destinationMemo string, hops ...Hop) ForwardingPacketData { - return ForwardingPacketData{ - DestinationMemo: destinationMemo, - Hops: hops, - } -} - -// Validate performs a basic validation of the ForwardingPacketData fields. -func (fpd ForwardingPacketData) Validate() error { - if err := validateHops(fpd.Hops); err != nil { - return errorsmod.Wrapf(ErrInvalidForwarding, "invalid hops in forwarding packet data") - } - - if len(fpd.DestinationMemo) > MaximumMemoLength { - return errorsmod.Wrapf(ErrInvalidMemo, "memo length cannot exceed %d", MaximumMemoLength) - } - - if len(fpd.Hops) == 0 && fpd.DestinationMemo != "" { - return errorsmod.Wrap(ErrInvalidForwarding, "memo specified when forwarding packet data hops is empty") - } - - return nil -} - -// NewHop creates a Hop with the given port ID and channel ID. -func NewHop(portID, channelID string) Hop { - return Hop{portID, channelID} -} - -// Validate performs a basic validation of the Hop fields. -func (h Hop) Validate() error { - if err := host.PortIdentifierValidator(h.PortId); err != nil { - return errorsmod.Wrapf(err, "invalid hop source port ID %s", h.PortId) - } - if err := host.ChannelIdentifierValidator(h.ChannelId); err != nil { - return errorsmod.Wrapf(err, "invalid hop source channel ID %s", h.ChannelId) - } - - return nil -} - -// String returns the Hop in the format: -// / -func (h Hop) String() string { - return fmt.Sprintf("%s/%s", h.PortId, h.ChannelId) -} - -// validateHops performs a basic validation of the hops. -// It checks that the number of hops does not exceed the maximum allowed and that each hop is valid. -// It will not return any errors if hops is empty. -func validateHops(hops []Hop) error { - if len(hops) > MaximumNumberOfForwardingHops { - return errorsmod.Wrapf(ErrInvalidForwarding, "number of hops cannot exceed %d", MaximumNumberOfForwardingHops) - } - - for _, hop := range hops { - if err := hop.Validate(); err != nil { - return err - } - } - - return nil -} diff --git a/modules/apps/transfer/types/forwarding_test.go b/modules/apps/transfer/types/forwarding_test.go deleted file mode 100644 index e1b0a102dbf..00000000000 --- a/modules/apps/transfer/types/forwarding_test.go +++ /dev/null @@ -1,284 +0,0 @@ -package types_test - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" - host "github.com/cosmos/ibc-go/v9/modules/core/24-host" - ibctesting "github.com/cosmos/ibc-go/v9/testing" -) - -var validHop = types.NewHop(types.PortID, ibctesting.FirstChannelID) - -func TestForwarding_Validate(t *testing.T) { - tests := []struct { - name string - forwarding *types.Forwarding - expError error - }{ - { - "valid forwarding with no hops", - types.NewForwarding(false), - nil, - }, - { - "valid forwarding with hops", - types.NewForwarding(false, validHop), - nil, - }, - { - "valid forwarding with max hops", - types.NewForwarding(false, generateHops(types.MaximumNumberOfForwardingHops)...), - nil, - }, - { - "invalid forwarding with too many hops", - types.NewForwarding(false, generateHops(types.MaximumNumberOfForwardingHops+1)...), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too short hop port ID", - types.NewForwarding( - false, - types.NewHop(invalidShortPort, ibctesting.FirstChannelID), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too long hop port ID", - types.NewForwarding( - false, - types.NewHop(invalidLongPort, ibctesting.FirstChannelID), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with non-alpha hop port ID", - types.NewForwarding( - false, - types.NewHop(invalidPort, ibctesting.FirstChannelID), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too long hop channel ID", - types.NewForwarding( - false, - types.NewHop(types.PortID, invalidLongChannel), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too short hop channel ID", - types.NewForwarding( - false, - types.NewHop(types.PortID, invalidShortChannel), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with non-alpha hop channel ID", - types.NewForwarding( - false, - types.NewHop(types.PortID, invalidChannel), - ), - types.ErrInvalidForwarding, - }, - { - "unwind with hop forwarding back to itself", - types.NewForwarding(true, types.NewHop(types.PortID, types.PortID)), - nil, - }, - } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - tc := tc - - err := tc.forwarding.Validate() - - if tc.expError == nil { - require.NoError(t, err) - } else { - require.ErrorIs(t, err, tc.expError) - } - }) - } -} - -func TestForwardingPacketData_Validate(t *testing.T) { - tests := []struct { - name string - forwarding types.ForwardingPacketData - expError error - }{ - { - "valid forwarding with no hops", - types.NewForwardingPacketData(""), - nil, - }, - { - "valid forwarding with hops", - types.NewForwardingPacketData("", validHop), - nil, - }, - { - "valid forwarding with memo", - types.NewForwardingPacketData(testMemo1, validHop, validHop), - nil, - }, - { - "valid forwarding with max hops", - types.NewForwardingPacketData("", generateHops(types.MaximumNumberOfForwardingHops)...), - nil, - }, - { - "valid forwarding with max memo length", - types.NewForwardingPacketData(ibctesting.GenerateString(types.MaximumMemoLength), validHop), - nil, - }, - { - "invalid forwarding with too many hops", - types.NewForwardingPacketData("", generateHops(types.MaximumNumberOfForwardingHops+1)...), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too long memo", - types.NewForwardingPacketData(ibctesting.GenerateString(types.MaximumMemoLength+1), validHop), - types.ErrInvalidMemo, - }, - { - "invalid forwarding with empty hops and specified memo", - types.NewForwardingPacketData("memo"), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too short hop port ID", - types.NewForwardingPacketData( - "", - types.NewHop(invalidShortPort, ibctesting.FirstChannelID), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too long hop port ID", - types.NewForwardingPacketData( - "", - types.NewHop(invalidLongPort, ibctesting.FirstChannelID), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with non-alpha hop port ID", - types.NewForwardingPacketData( - "", - types.NewHop(invalidPort, ibctesting.FirstChannelID), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too long hop channel ID", - types.NewForwardingPacketData( - "", - types.NewHop(types.PortID, invalidLongChannel), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with too short hop channel ID", - types.NewForwardingPacketData( - "", - types.NewHop(types.PortID, invalidShortChannel), - ), - types.ErrInvalidForwarding, - }, - { - "invalid forwarding with non-alpha hop channel ID", - types.NewForwardingPacketData( - "", - types.NewHop(types.PortID, invalidChannel), - ), - types.ErrInvalidForwarding, - }, - } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - tc := tc - - err := tc.forwarding.Validate() - - if tc.expError == nil { - require.NoError(t, err) - } else { - require.ErrorIs(t, err, tc.expError) - } - }) - } -} - -func TestValidateHop(t *testing.T) { - tests := []struct { - name string - hop types.Hop - expError error - }{ - { - "valid hop", - validHop, - nil, - }, - { - "invalid hop with too short port ID", - types.NewHop(invalidShortPort, ibctesting.FirstChannelID), - host.ErrInvalidID, - }, - { - "invalid hop with too long port ID", - types.NewHop(invalidLongPort, ibctesting.FirstChannelID), - host.ErrInvalidID, - }, - { - "invalid hop with non-alpha port ID", - types.NewHop(invalidPort, ibctesting.FirstChannelID), - host.ErrInvalidID, - }, - { - "invalid hop with too long channel ID", - types.NewHop(types.PortID, invalidLongChannel), - host.ErrInvalidID, - }, - { - "invalid hop with too short channel ID", - types.NewHop(types.PortID, invalidShortChannel), - host.ErrInvalidID, - }, - { - "invalid hop with non-alpha channel ID", - types.NewHop(types.PortID, invalidChannel), - host.ErrInvalidID, - }, - } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - tc := tc - - err := tc.hop.Validate() - - if tc.expError == nil { - require.NoError(t, err) - } else { - require.ErrorIs(t, err, tc.expError) - } - }) - } -} - -// generateHops generates a slice of n correctly initialized hops. -func generateHops(n int) []types.Hop { - hops := make([]types.Hop, n) - for i := 0; i < n; i++ { - hops[i] = types.NewHop(types.PortID, ibctesting.FirstChannelID) - } - return hops -} diff --git a/modules/apps/transfer/types/genesis.pb.go b/modules/apps/transfer/types/genesis.pb.go index e2ca67140b9..c639d8d1976 100644 --- a/modules/apps/transfer/types/genesis.pb.go +++ b/modules/apps/transfer/types/genesis.pb.go @@ -9,7 +9,7 @@ import ( types "github.com/cosmos/cosmos-sdk/types" _ "github.com/cosmos/gogoproto/gogoproto" proto "github.com/cosmos/gogoproto/proto" - types1 "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" + _ "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" io "io" math "math" math_bits "math/bits" @@ -34,9 +34,6 @@ type GenesisState struct { // total_escrowed contains the total amount of tokens escrowed // by the transfer module TotalEscrowed github_com_cosmos_cosmos_sdk_types.Coins `protobuf:"bytes,4,rep,name=total_escrowed,json=totalEscrowed,proto3,castrepeated=github.com/cosmos/cosmos-sdk/types.Coins" json:"total_escrowed"` - // forwarded_packets contains the forwarded packets stored as part of the - // packet forwarding lifecycle - ForwardedPackets []ForwardedPacket `protobuf:"bytes,5,rep,name=forwarded_packets,json=forwardedPackets,proto3" json:"forwarded_packets"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -100,69 +97,8 @@ func (m *GenesisState) GetTotalEscrowed() github_com_cosmos_cosmos_sdk_types.Coi return nil } -func (m *GenesisState) GetForwardedPackets() []ForwardedPacket { - if m != nil { - return m.ForwardedPackets - } - return nil -} - -// ForwardedPacket defines the genesis type necessary to retrieve and store forwarded packets. -type ForwardedPacket struct { - ForwardKey types1.PacketId `protobuf:"bytes,1,opt,name=forward_key,json=forwardKey,proto3" json:"forward_key"` - Packet types1.Packet `protobuf:"bytes,2,opt,name=packet,proto3" json:"packet"` -} - -func (m *ForwardedPacket) Reset() { *m = ForwardedPacket{} } -func (m *ForwardedPacket) String() string { return proto.CompactTextString(m) } -func (*ForwardedPacket) ProtoMessage() {} -func (*ForwardedPacket) Descriptor() ([]byte, []int) { - return fileDescriptor_62efebb47a9093ed, []int{1} -} -func (m *ForwardedPacket) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ForwardedPacket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ForwardedPacket.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ForwardedPacket) XXX_Merge(src proto.Message) { - xxx_messageInfo_ForwardedPacket.Merge(m, src) -} -func (m *ForwardedPacket) XXX_Size() int { - return m.Size() -} -func (m *ForwardedPacket) XXX_DiscardUnknown() { - xxx_messageInfo_ForwardedPacket.DiscardUnknown(m) -} - -var xxx_messageInfo_ForwardedPacket proto.InternalMessageInfo - -func (m *ForwardedPacket) GetForwardKey() types1.PacketId { - if m != nil { - return m.ForwardKey - } - return types1.PacketId{} -} - -func (m *ForwardedPacket) GetPacket() types1.Packet { - if m != nil { - return m.Packet - } - return types1.Packet{} -} - func init() { proto.RegisterType((*GenesisState)(nil), "ibc.applications.transfer.v2.GenesisState") - proto.RegisterType((*ForwardedPacket)(nil), "ibc.applications.transfer.v2.ForwardedPacket") } func init() { @@ -170,38 +106,32 @@ func init() { } var fileDescriptor_62efebb47a9093ed = []byte{ - // 485 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x41, 0x6f, 0xd3, 0x30, - 0x14, 0xc7, 0x9b, 0x6d, 0x04, 0xe1, 0xc2, 0x80, 0x08, 0x89, 0x30, 0x20, 0x2b, 0x83, 0x43, 0x04, - 0xaa, 0x4d, 0xc3, 0x01, 0xed, 0x5a, 0x06, 0x68, 0xda, 0x65, 0x94, 0x1b, 0x97, 0xe2, 0xd8, 0x6e, - 0x66, 0xb5, 0xc9, 0x8b, 0x6c, 0xaf, 0x53, 0xbf, 0x04, 0x42, 0x7c, 0x0c, 0x3e, 0xc9, 0x8e, 0x3b, - 0x72, 0x02, 0xd4, 0x7e, 0x11, 0x64, 0xc7, 0x85, 0x01, 0x52, 0x4e, 0x7d, 0xcf, 0xfd, 0xff, 0xff, - 0xcf, 0xfe, 0xe5, 0xa1, 0xa7, 0x32, 0x67, 0x84, 0xd6, 0xf5, 0x4c, 0x32, 0x6a, 0x24, 0x54, 0x9a, - 0x18, 0x45, 0x2b, 0x3d, 0x11, 0x8a, 0xcc, 0x33, 0x52, 0x88, 0x4a, 0x68, 0xa9, 0x71, 0xad, 0xc0, - 0x40, 0xf4, 0x40, 0xe6, 0x0c, 0x5f, 0xd6, 0xe2, 0xb5, 0x16, 0xcf, 0xb3, 0x9d, 0x67, 0x2d, 0x49, - 0x83, 0xdf, 0x75, 0x13, 0xb5, 0x93, 0xb6, 0x8e, 0x35, 0x30, 0x15, 0x95, 0x57, 0x3e, 0xb2, 0x4a, - 0x06, 0x4a, 0x10, 0x76, 0x42, 0xab, 0x4a, 0xcc, 0x6c, 0x9a, 0x2f, 0xbd, 0x24, 0x61, 0xa0, 0x4b, - 0xd0, 0x24, 0xa7, 0x5a, 0x90, 0xf9, 0x20, 0x17, 0x86, 0x0e, 0x08, 0x03, 0xb9, 0x8e, 0xb8, 0x53, - 0x40, 0x01, 0xae, 0x24, 0xb6, 0x6a, 0x4e, 0xf7, 0x3e, 0x6d, 0xa2, 0xeb, 0x6f, 0x9b, 0xf7, 0xbd, - 0x37, 0xd4, 0x88, 0xe8, 0x2e, 0xba, 0x5a, 0x83, 0x32, 0x63, 0xc9, 0xe3, 0xa0, 0x17, 0xa4, 0xd7, - 0x46, 0xa1, 0x6d, 0x0f, 0x79, 0x74, 0x84, 0x42, 0x2e, 0x2a, 0x28, 0x75, 0xbc, 0xd1, 0xdb, 0x4c, - 0xbb, 0xd9, 0x63, 0xdc, 0x06, 0x02, 0x1f, 0x58, 0xed, 0x70, 0xfb, 0xfc, 0xfb, 0x6e, 0xe7, 0xeb, - 0x8f, 0xdd, 0xd0, 0xb5, 0x7a, 0xe4, 0x23, 0xa2, 0x21, 0x0a, 0x6b, 0xaa, 0x68, 0xa9, 0xe3, 0xcd, - 0x5e, 0x90, 0x76, 0xb3, 0x27, 0x6d, 0x61, 0x03, 0x7c, 0xec, 0xb4, 0xc3, 0x2d, 0x9b, 0x36, 0xf2, - 0xce, 0x48, 0xa1, 0x6d, 0x03, 0x86, 0xce, 0xc6, 0x42, 0x33, 0x05, 0x67, 0x82, 0xc7, 0x5b, 0xee, - 0x62, 0xf7, 0x70, 0x43, 0x02, 0x5b, 0x12, 0xd8, 0x93, 0xc0, 0xaf, 0x40, 0x56, 0xc3, 0xe7, 0xfe, - 0x3a, 0x69, 0x21, 0xcd, 0xc9, 0x69, 0x8e, 0x19, 0x94, 0xc4, 0x63, 0x6b, 0x7e, 0xfa, 0x9a, 0x4f, - 0x89, 0x59, 0xd4, 0x42, 0x3b, 0x83, 0x1e, 0xdd, 0x70, 0x23, 0x5e, 0xfb, 0x09, 0xd1, 0x47, 0x74, - 0x7b, 0x02, 0xea, 0x8c, 0x2a, 0x2e, 0xf8, 0xb8, 0xa6, 0x6c, 0x2a, 0x8c, 0x8e, 0xaf, 0xb8, 0xb1, - 0xfd, 0x76, 0x1e, 0x6f, 0xd6, 0xb6, 0x63, 0xe7, 0xf2, 0x6f, 0xb9, 0x35, 0xf9, 0xfb, 0x58, 0xef, - 0x7d, 0x09, 0xd0, 0xcd, 0x7f, 0xb4, 0xd1, 0x01, 0xea, 0x7a, 0xdd, 0x78, 0x2a, 0x16, 0xee, 0xbb, - 0x74, 0xb3, 0x87, 0x6e, 0x9e, 0xdd, 0x09, 0xbc, 0x5e, 0x04, 0x47, 0xca, 0x3a, 0x0e, 0xb9, 0xcf, - 0x47, 0xde, 0x77, 0x24, 0x16, 0xd1, 0xbe, 0x65, 0x6e, 0xff, 0x8d, 0x37, 0x5c, 0xc0, 0xfd, 0x96, - 0x80, 0x3f, 0xa8, 0x5d, 0xf7, 0xee, 0x7c, 0x99, 0x04, 0x17, 0xcb, 0x24, 0xf8, 0xb9, 0x4c, 0x82, - 0xcf, 0xab, 0xa4, 0x73, 0xb1, 0x4a, 0x3a, 0xdf, 0x56, 0x49, 0xe7, 0xc3, 0xcb, 0xff, 0x49, 0xca, - 0x9c, 0xf5, 0x0b, 0x20, 0xf3, 0x7d, 0x52, 0x02, 0x3f, 0x9d, 0x09, 0x6d, 0x57, 0xfc, 0xd2, 0x6a, - 0x3b, 0xbc, 0x79, 0xe8, 0xf6, 0xef, 0xc5, 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfb, 0x97, 0x02, - 0x93, 0x7b, 0x03, 0x00, 0x00, + // 393 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0x4f, 0x8b, 0xd4, 0x30, + 0x18, 0xc6, 0xdb, 0xdd, 0xa5, 0x62, 0x57, 0xf7, 0x50, 0x04, 0xeb, 0x22, 0xdd, 0xf1, 0xcf, 0xa1, + 0x28, 0x93, 0xd8, 0x7a, 0x10, 0xaf, 0x55, 0x11, 0xf1, 0xa2, 0xf5, 0xe6, 0x65, 0x48, 0xd3, 0xd8, + 0x09, 0xd3, 0xe6, 0x2d, 0x49, 0xa6, 0xe2, 0xb7, 0xf0, 0x73, 0x88, 0x1f, 0x64, 0x8e, 0x73, 0xf4, + 0xa4, 0x32, 0xf3, 0x45, 0x24, 0x69, 0x46, 0x06, 0x16, 0x7a, 0xea, 0x93, 0xf2, 0xe4, 0xf7, 0xbc, + 0x79, 0xde, 0xf0, 0x09, 0xaf, 0x28, 0x26, 0x7d, 0xdf, 0x72, 0x4a, 0x34, 0x07, 0xa1, 0xb0, 0x96, + 0x44, 0xa8, 0x2f, 0x4c, 0xe2, 0x21, 0xc7, 0x0d, 0x13, 0x4c, 0x71, 0x85, 0x7a, 0x09, 0x1a, 0xa2, + 0xfb, 0xbc, 0xa2, 0xe8, 0xd8, 0x8b, 0x0e, 0x5e, 0x34, 0xe4, 0x97, 0x4f, 0x27, 0x48, 0xd9, 0x7f, + 0x3d, 0xa2, 0x2e, 0xd3, 0xc9, 0x58, 0x0d, 0x2b, 0x26, 0x9c, 0xf3, 0x81, 0x71, 0x52, 0x90, 0x0c, + 0xd3, 0x25, 0x11, 0x82, 0xb5, 0x86, 0xe6, 0xa4, 0xb3, 0x24, 0x14, 0x54, 0x07, 0x0a, 0x57, 0x44, + 0x31, 0x3c, 0x64, 0x15, 0xd3, 0x24, 0xc3, 0x14, 0xf8, 0x01, 0x71, 0xa7, 0x81, 0x06, 0xac, 0xc4, + 0x46, 0x8d, 0x7f, 0x1f, 0xfe, 0x3c, 0x09, 0x6f, 0xbd, 0x1d, 0xdf, 0xf7, 0x49, 0x13, 0xcd, 0xa2, + 0xbb, 0xe1, 0x8d, 0x1e, 0xa4, 0x5e, 0xf0, 0x3a, 0xf6, 0x67, 0x7e, 0x7a, 0xb3, 0x0c, 0xcc, 0xf1, + 0x5d, 0x1d, 0xbd, 0x0f, 0x83, 0x9a, 0x09, 0xe8, 0x54, 0x7c, 0x32, 0x3b, 0x4d, 0xcf, 0xf3, 0x47, + 0x68, 0xaa, 0x08, 0xf4, 0xda, 0x78, 0x8b, 0x8b, 0xcd, 0xef, 0x2b, 0xef, 0xc7, 0x9f, 0xab, 0xc0, + 0x1e, 0x55, 0xe9, 0x10, 0x51, 0x11, 0x06, 0x3d, 0x91, 0xa4, 0x53, 0xf1, 0xe9, 0xcc, 0x4f, 0xcf, + 0xf3, 0xc7, 0x53, 0xb0, 0x0c, 0x7d, 0xb0, 0xde, 0xe2, 0xcc, 0xd0, 0x4a, 0x77, 0x33, 0x92, 0xe1, + 0x85, 0x06, 0x4d, 0xda, 0x05, 0x53, 0x54, 0xc2, 0x57, 0x56, 0xc7, 0x67, 0x76, 0xb0, 0x7b, 0x68, + 0x6c, 0x02, 0x99, 0x26, 0x90, 0x6b, 0x02, 0xbd, 0x02, 0x2e, 0x8a, 0x67, 0x6e, 0x9c, 0xb4, 0xe1, + 0x7a, 0xb9, 0xae, 0x10, 0x85, 0x0e, 0xbb, 0xda, 0xc6, 0xcf, 0x5c, 0xd5, 0x2b, 0xac, 0xbf, 0xf5, + 0x4c, 0xd9, 0x0b, 0xaa, 0xbc, 0x6d, 0x23, 0xde, 0xb8, 0x84, 0xe2, 0xe3, 0x66, 0x97, 0xf8, 0xdb, + 0x5d, 0xe2, 0xff, 0xdd, 0x25, 0xfe, 0xf7, 0x7d, 0xe2, 0x6d, 0xf7, 0x89, 0xf7, 0x6b, 0x9f, 0x78, + 0x9f, 0x5f, 0x5c, 0x47, 0xf2, 0x8a, 0xce, 0x1b, 0xc0, 0xc3, 0x4b, 0xdc, 0x41, 0xbd, 0x6e, 0x99, + 0x32, 0xbb, 0x3e, 0xda, 0xb1, 0xcd, 0xa9, 0x02, 0xbb, 0x88, 0xe7, 0xff, 0x02, 0x00, 0x00, 0xff, + 0xff, 0x5e, 0x2f, 0x07, 0x34, 0x84, 0x02, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -224,20 +154,6 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.ForwardedPackets) > 0 { - for iNdEx := len(m.ForwardedPackets) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.ForwardedPackets[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a - } - } if len(m.TotalEscrowed) > 0 { for iNdEx := len(m.TotalEscrowed) - 1; iNdEx >= 0; iNdEx-- { { @@ -286,49 +202,6 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *ForwardedPacket) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ForwardedPacket) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ForwardedPacket) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - { - size, err := m.Packet.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - { - size, err := m.ForwardKey.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintGenesis(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - return len(dAtA) - i, nil -} - func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { offset -= sovGenesis(v) base := offset @@ -364,25 +237,6 @@ func (m *GenesisState) Size() (n int) { n += 1 + l + sovGenesis(uint64(l)) } } - if len(m.ForwardedPackets) > 0 { - for _, e := range m.ForwardedPackets { - l = e.Size() - n += 1 + l + sovGenesis(uint64(l)) - } - } - return n -} - -func (m *ForwardedPacket) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = m.ForwardKey.Size() - n += 1 + l + sovGenesis(uint64(l)) - l = m.Packet.Size() - n += 1 + l + sovGenesis(uint64(l)) return n } @@ -554,156 +408,6 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ForwardedPackets", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ForwardedPackets = append(m.ForwardedPackets, ForwardedPacket{}) - if err := m.ForwardedPackets[len(m.ForwardedPackets)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipGenesis(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthGenesis - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ForwardedPacket) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ForwardedPacket: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ForwardedPacket: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ForwardKey", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.ForwardKey.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Packet", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowGenesis - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthGenesis - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthGenesis - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Packet.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/modules/apps/transfer/types/hop.go b/modules/apps/transfer/types/hop.go new file mode 100644 index 00000000000..807e2797b54 --- /dev/null +++ b/modules/apps/transfer/types/hop.go @@ -0,0 +1,32 @@ +package types + +import ( + fmt "fmt" + + errorsmod "cosmossdk.io/errors" + + host "github.com/cosmos/ibc-go/v9/modules/core/24-host" +) + +// NewHop creates a Hop with the given port ID and channel ID. +func NewHop(portID, channelID string) Hop { + return Hop{portID, channelID} +} + +// Validate performs a basic validation of the Hop fields. +func (h Hop) Validate() error { + if err := host.PortIdentifierValidator(h.PortId); err != nil { + return errorsmod.Wrapf(err, "invalid hop source port ID %s", h.PortId) + } + if err := host.ChannelIdentifierValidator(h.ChannelId); err != nil { + return errorsmod.Wrapf(err, "invalid hop source channel ID %s", h.ChannelId) + } + + return nil +} + +// String returns the Hop in the format: +// / +func (h Hop) String() string { + return fmt.Sprintf("%s/%s", h.PortId, h.ChannelId) +} diff --git a/modules/apps/transfer/types/hop_test.go b/modules/apps/transfer/types/hop_test.go new file mode 100644 index 00000000000..d0494761f06 --- /dev/null +++ b/modules/apps/transfer/types/hop_test.go @@ -0,0 +1,68 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" + host "github.com/cosmos/ibc-go/v9/modules/core/24-host" + ibctesting "github.com/cosmos/ibc-go/v9/testing" +) + +func TestValidateHop(t *testing.T) { + tests := []struct { + name string + hop types.Hop + expError error + }{ + { + "valid hop", + types.NewHop(types.PortID, ibctesting.FirstChannelID), + nil, + }, + { + "invalid hop with too short port ID", + types.NewHop(invalidShortPort, ibctesting.FirstChannelID), + host.ErrInvalidID, + }, + { + "invalid hop with too long port ID", + types.NewHop(invalidLongPort, ibctesting.FirstChannelID), + host.ErrInvalidID, + }, + { + "invalid hop with non-alpha port ID", + types.NewHop(invalidPort, ibctesting.FirstChannelID), + host.ErrInvalidID, + }, + { + "invalid hop with too long channel ID", + types.NewHop(types.PortID, invalidLongChannel), + host.ErrInvalidID, + }, + { + "invalid hop with too short channel ID", + types.NewHop(types.PortID, invalidShortChannel), + host.ErrInvalidID, + }, + { + "invalid hop with non-alpha channel ID", + types.NewHop(types.PortID, invalidChannel), + host.ErrInvalidID, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tc := tc + + err := tc.hop.Validate() + + if tc.expError == nil { + require.NoError(t, err) + } else { + require.ErrorIs(t, err, tc.expError) + } + }) + } +} diff --git a/modules/apps/transfer/types/keys.go b/modules/apps/transfer/types/keys.go index 23a53f2ea46..a0226f28cb2 100644 --- a/modules/apps/transfer/types/keys.go +++ b/modules/apps/transfer/types/keys.go @@ -36,10 +36,6 @@ const ( // V1 defines first version of the IBC transfer module V1 = "ics20-1" - // V2 defines the transfer version which introduces multidenom support - // through the FungibleTokenPacketDataV2. It is the latest version. - V2 = "ics20-2" - // escrowAddressVersion should remain as ics20-1 to avoid the address changing. // this address has been reasoned about to avoid collisions with other addresses // https://github.com/cosmos/cosmos-sdk/issues/7737#issuecomment-735671951 @@ -53,11 +49,9 @@ var ( DenomTraceKey = []byte{0x02} // DenomKey defines the key to store the token denomination in store DenomKey = []byte{0x03} - // ForwardedPacketKey defines the key to store the forwarded packet in store - ForwardedPacketKey = []byte{0x04} // SupportedVersions defines all versions that are supported by the module - SupportedVersions = []string{V2, V1} + SupportedVersions = []string{V1} ) // GetEscrowAddress returns the escrow address for the specified channel. @@ -81,9 +75,3 @@ func GetEscrowAddress(portID, channelID string) sdk.AccAddress { func TotalEscrowForDenomKey(denom string) []byte { return []byte(fmt.Sprintf("%s/%s", KeyTotalEscrowPrefix, denom)) } - -// PacketForwardKey returns the store key under which the forwarded packet is stored -// for the provided portID, channelID, and packet sequence. -func PacketForwardKey(portID, channelID string, sequence uint64) []byte { - return []byte(fmt.Sprintf("%s/%s/%s/%s", ForwardedPacketKey, portID, channelID, sdk.Uint64ToBigEndian(sequence))) -} diff --git a/modules/apps/transfer/types/msgs.go b/modules/apps/transfer/types/msgs.go index a9392292191..c04ee0f9bdc 100644 --- a/modules/apps/transfer/types/msgs.go +++ b/modules/apps/transfer/types/msgs.go @@ -15,7 +15,6 @@ import ( const ( MaximumReceiverLength = 2048 // maximum length of the receiver address in bytes (value chosen arbitrarily) MaximumMemoLength = 32768 // maximum length of the memo in bytes (value chosen arbitrarily) - MaximumTokensLength = 100 // maximum number of tokens that can be transferred in a single message (value chosen arbitrarily) ) var ( @@ -46,21 +45,19 @@ func (msg MsgUpdateParams) ValidateBasic() error { // NewMsgTransfer creates a new MsgTransfer instance func NewMsgTransfer( sourcePort, sourceChannel string, - tokens sdk.Coins, sender, receiver string, + token sdk.Coin, sender, receiver string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, memo string, - forwarding *Forwarding, ) *MsgTransfer { return &MsgTransfer{ SourcePort: sourcePort, SourceChannel: sourceChannel, + Token: token, Sender: sender, Receiver: receiver, TimeoutHeight: timeoutHeight, TimeoutTimestamp: timeoutTimestamp, Memo: memo, - Tokens: tokens, - Forwarding: forwarding, } } @@ -69,24 +66,12 @@ func NewMsgTransfer( // NOTE: The recipient addresses format is not validated as the format defined by // the chain is not known to IBC. func (msg MsgTransfer) ValidateBasic() error { - if err := msg.validateForwarding(); err != nil { - return err - } - if err := msg.validateIdentifiers(); err != nil { return err } - if len(msg.Tokens) == 0 && !isValidIBCCoin(msg.Token) { - return errorsmod.Wrap(ibcerrors.ErrInvalidCoins, "either token or token array must be filled") - } - - if len(msg.Tokens) != 0 && isValidIBCCoin(msg.Token) { - return errorsmod.Wrap(ibcerrors.ErrInvalidCoins, "cannot fill both token and token array") - } - - if len(msg.Tokens) > MaximumTokensLength { - return errorsmod.Wrapf(ibcerrors.ErrInvalidCoins, "number of tokens must not exceed %d", MaximumTokensLength) + if !isValidIBCCoin(msg.Token) { + return errorsmod.Wrap(ibcerrors.ErrInvalidCoins, msg.Token.String()) } _, err := sdk.AccAddressFromBech32(msg.Sender) @@ -103,70 +88,11 @@ func (msg MsgTransfer) ValidateBasic() error { return errorsmod.Wrapf(ErrInvalidMemo, "memo must not exceed %d bytes", MaximumMemoLength) } - for _, coin := range msg.GetCoins() { - if err := validateIBCCoin(coin); err != nil { - return errorsmod.Wrapf(ibcerrors.ErrInvalidCoins, "%s: %s", err.Error(), coin.String()) - } - } - - return nil -} - -// validateForwarding ensures that forwarding is set up correctly. -func (msg MsgTransfer) validateForwarding() error { - if !msg.HasForwarding() { - return nil - } - - if err := msg.Forwarding.Validate(); err != nil { - return err - } - - if !msg.TimeoutHeight.IsZero() { - // when forwarding, the timeout height must not be set - return errorsmod.Wrapf(ErrInvalidPacketTimeout, "timeout height must be zero if forwarding path hops is not empty: %s, %s", msg.TimeoutHeight, msg.Forwarding.GetHops()) - } - return nil } -// GetCoins returns the tokens which will be transferred. -// If MsgTransfer is populated in the Token field, only that field -// will be returned in the coin array. -func (msg MsgTransfer) GetCoins() sdk.Coins { - coins := msg.Tokens - if isValidIBCCoin(msg.Token) { - coins = []sdk.Coin{msg.Token} - } - return coins -} - -// HasForwarding determines if the transfer should be forwarded to the next hop. -func (msg MsgTransfer) HasForwarding() bool { - if msg.Forwarding == nil { - return false - } - - return len(msg.Forwarding.GetHops()) > 0 || msg.Forwarding.GetUnwind() -} - -// validateIdentifiers validates the source port and channel identifiers based on the -// forwarding information present in the message. If forwarding information is missing -// or unwinding isn't performed, we do normal validation, else, we assert that both -// fields must be empty. +// validateIdentifiers checks if the source port and channel identifiers are valid func (msg MsgTransfer) validateIdentifiers() error { - if msg.Forwarding.GetUnwind() { - if msg.SourcePort != "" { - return errorsmod.Wrapf(ErrInvalidForwarding, "source port must be empty when unwind is set, got %s instead", msg.SourcePort) - } - if msg.SourceChannel != "" { - return errorsmod.Wrapf(ErrInvalidForwarding, "source channel must be empty when unwind is set, got %s instead", msg.SourceChannel) - } - - return nil - } - - // If forwarding is nil or if no unwinding occurs, validate port, channel. if err := host.PortIdentifierValidator(msg.SourcePort); err != nil { return errorsmod.Wrapf(err, "invalid source port ID %s", msg.SourcePort) } diff --git a/modules/apps/transfer/types/msgs_test.go b/modules/apps/transfer/types/msgs_test.go index e26b69c2d63..4fcb6a0fd01 100644 --- a/modules/apps/transfer/types/msgs_test.go +++ b/modules/apps/transfer/types/msgs_test.go @@ -40,12 +40,11 @@ var ( receiver = sdk.AccAddress("testaddr2").String() emptyAddr string - coin = ibctesting.TestCoin - coins = ibctesting.TestCoins - ibcCoins = sdk.NewCoins(sdk.NewCoin("ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", sdkmath.NewInt(100))) - invalidIBCCoins = sdk.NewCoins(sdk.NewCoin("ibc/7F1D3FCF4AE79E1554", sdkmath.NewInt(100))) - invalidDenomCoins = []sdk.Coin{{Denom: "0atom", Amount: sdkmath.NewInt(100)}} - zeroCoins = []sdk.Coin{{Denom: "atoms", Amount: sdkmath.NewInt(0)}} + coin = ibctesting.TestCoin + ibcCoin = sdk.NewCoin("ibc/7F1D3FCF4AE79E1554D670D1AD949A9BA4E4A3C76C63093E17E446A46061A7A2", sdkmath.NewInt(100)) + invalidIBCCoin = sdk.NewCoin("ibc/7F1D3FCF4AE79E1554", sdkmath.NewInt(100)) + invalidDenomCoin = sdk.Coin{Denom: "0atom", Amount: sdkmath.NewInt(100)} + zeroCoin = sdk.Coin{Denom: "atoms", Amount: sdkmath.NewInt(0)} timeoutHeight = clienttypes.NewHeight(0, 10) ) @@ -57,39 +56,22 @@ func TestMsgTransferValidation(t *testing.T) { msg *types.MsgTransfer expError error }{ - {"valid msg with base denom", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), nil}, - {"valid msg with unwind", types.NewMsgTransfer("", "", sdk.NewCoins(coin), sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(true)), nil}, - {"valid msg with trace hash", types.NewMsgTransfer(validPort, validChannel, ibcCoins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), nil}, - {"multidenom", types.NewMsgTransfer(validPort, validChannel, coins.Add(ibcCoins...), sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), nil}, - {"memo with forwarding path hops not empty", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "memo", types.NewForwarding(false, validHop)), nil}, - {"memo with forwarding unwind set to true", types.NewMsgTransfer("", "", sdk.NewCoins(coin), sender, receiver, clienttypes.ZeroHeight(), 100, "memo", types.NewForwarding(true)), nil}, - {"invalid ibc denom", types.NewMsgTransfer(validPort, validChannel, invalidIBCCoins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidCoins}, - {"too short port id", types.NewMsgTransfer(invalidShortPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), host.ErrInvalidID}, - {"too long port id", types.NewMsgTransfer(invalidLongPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), host.ErrInvalidID}, - {"port id contains non-alpha", types.NewMsgTransfer(invalidPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), host.ErrInvalidID}, - {"too short channel id", types.NewMsgTransfer(validPort, invalidShortChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), host.ErrInvalidID}, - {"too long channel id", types.NewMsgTransfer(validPort, invalidLongChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), host.ErrInvalidID}, - {"too long memo", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, ibctesting.GenerateString(types.MaximumMemoLength+1), nil), types.ErrInvalidMemo}, - {"channel id contains non-alpha", types.NewMsgTransfer(validPort, invalidChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), host.ErrInvalidID}, - {"invalid denom", types.NewMsgTransfer(validPort, validChannel, invalidDenomCoins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidCoins}, - {"zero coins", types.NewMsgTransfer(validPort, validChannel, zeroCoins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidCoins}, - {"missing sender address", types.NewMsgTransfer(validPort, validChannel, coins, emptyAddr, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidAddress}, - {"missing recipient address", types.NewMsgTransfer(validPort, validChannel, coins, sender, "", clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidAddress}, - {"too long recipient address", types.NewMsgTransfer(validPort, validChannel, coins, sender, ibctesting.GenerateString(types.MaximumReceiverLength+1), clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidAddress}, - {"empty coins", types.NewMsgTransfer(validPort, validChannel, sdk.NewCoins(), sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidCoins}, - {"multidenom: invalid denom", types.NewMsgTransfer(validPort, validChannel, coins.Add(invalidDenomCoins...), sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidCoins}, - {"multidenom: invalid ibc denom", types.NewMsgTransfer(validPort, validChannel, coins.Add(invalidIBCCoins...), sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidCoins}, - {"multidenom: zero coins", types.NewMsgTransfer(validPort, validChannel, zeroCoins, sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidCoins}, - {"multidenom: too many coins", types.NewMsgTransfer(validPort, validChannel, make([]sdk.Coin, types.MaximumTokensLength+1), sender, receiver, clienttypes.ZeroHeight(), 100, "", nil), ibcerrors.ErrInvalidCoins}, - {"multidenom: both token and tokens are set", &types.MsgTransfer{validPort, validChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, "", coins, nil}, ibcerrors.ErrInvalidCoins}, - {"timeout height must be zero if forwarding path hops is not empty", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, timeoutHeight, 100, "memo", types.NewForwarding(false, validHop)), types.ErrInvalidPacketTimeout}, - {"invalid forwarding info port", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, types.NewHop(invalidPort, validChannel))), types.ErrInvalidForwarding}, - {"invalid forwarding info channel", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, types.NewHop(validPort, invalidChannel))), types.ErrInvalidForwarding}, - {"invalid forwarding info too many hops", types.NewMsgTransfer(validPort, validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, generateHops(types.MaximumNumberOfForwardingHops+1)...)), types.ErrInvalidForwarding}, - {"invalid portID when forwarding is set but unwind is not", types.NewMsgTransfer("", validChannel, coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, validHop)), host.ErrInvalidID}, - {"invalid channelID when forwarding is set but unwind is not", types.NewMsgTransfer(validPort, "", coins, sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(false, validHop)), host.ErrInvalidID}, - {"unwind specified but source port is not empty", types.NewMsgTransfer(validPort, "", sdk.NewCoins(coin), sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(true)), types.ErrInvalidForwarding}, - {"unwind specified but source channel is not empty", types.NewMsgTransfer("", validChannel, sdk.NewCoins(coin), sender, receiver, clienttypes.ZeroHeight(), 100, "", types.NewForwarding(true)), types.ErrInvalidForwarding}, + {"valid msg with base denom", types.NewMsgTransfer(validPort, validChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), nil}, + {"valid msg with trace hash", types.NewMsgTransfer(validPort, validChannel, ibcCoin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), nil}, + {"invalid ibc denom", types.NewMsgTransfer(validPort, validChannel, invalidIBCCoin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), ibcerrors.ErrInvalidCoins}, + {"too short port id", types.NewMsgTransfer(invalidShortPort, validChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), host.ErrInvalidID}, + {"too long port id", types.NewMsgTransfer(invalidLongPort, validChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), host.ErrInvalidID}, + {"port id contains non-alpha", types.NewMsgTransfer(invalidPort, validChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), host.ErrInvalidID}, + {"too short channel id", types.NewMsgTransfer(validPort, invalidShortChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), host.ErrInvalidID}, + {"too long channel id", types.NewMsgTransfer(validPort, invalidLongChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), host.ErrInvalidID}, + {"too long memo", types.NewMsgTransfer(validPort, validChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, ibctesting.GenerateString(types.MaximumMemoLength+1)), types.ErrInvalidMemo}, + {"channel id contains non-alpha", types.NewMsgTransfer(validPort, invalidChannel, coin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), host.ErrInvalidID}, + {"invalid denom", types.NewMsgTransfer(validPort, validChannel, invalidDenomCoin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), ibcerrors.ErrInvalidCoins}, + {"zero coin", types.NewMsgTransfer(validPort, validChannel, zeroCoin, sender, receiver, clienttypes.ZeroHeight(), 100, ""), ibcerrors.ErrInvalidCoins}, + {"missing sender address", types.NewMsgTransfer(validPort, validChannel, coin, emptyAddr, receiver, clienttypes.ZeroHeight(), 100, ""), ibcerrors.ErrInvalidAddress}, + {"missing recipient address", types.NewMsgTransfer(validPort, validChannel, coin, sender, "", clienttypes.ZeroHeight(), 100, ""), ibcerrors.ErrInvalidAddress}, + {"too long recipient address", types.NewMsgTransfer(validPort, validChannel, coin, sender, ibctesting.GenerateString(types.MaximumReceiverLength+1), clienttypes.ZeroHeight(), 100, ""), ibcerrors.ErrInvalidAddress}, + {"empty coin", types.NewMsgTransfer(validPort, validChannel, sdk.Coin{}, sender, receiver, clienttypes.ZeroHeight(), 100, ""), ibcerrors.ErrInvalidCoins}, } for _, tc := range testCases { @@ -108,7 +90,7 @@ func TestMsgTransferValidation(t *testing.T) { // TestMsgTransferGetSigners tests GetSigners for MsgTransfer func TestMsgTransferGetSigners(t *testing.T) { addr := sdk.AccAddress(secp256k1.GenPrivKey().PubKey().Address()) - msg := types.NewMsgTransfer(validPort, validChannel, coins, addr.String(), receiver, timeoutHeight, 0, "", nil) + msg := types.NewMsgTransfer(validPort, validChannel, coin, addr.String(), receiver, timeoutHeight, 0, "") encodingCfg := moduletestutil.MakeTestEncodingConfig(transfer.AppModuleBasic{}) signers, _, err := encodingCfg.Codec.GetMsgV1Signers(msg) diff --git a/modules/apps/transfer/types/packet.go b/modules/apps/transfer/types/packet.go index d2845be4f01..39d3502278e 100644 --- a/modules/apps/transfer/types/packet.go +++ b/modules/apps/transfer/types/packet.go @@ -19,8 +19,6 @@ import ( var ( _ ibcexported.PacketData = (*FungibleTokenPacketData)(nil) _ ibcexported.PacketDataProvider = (*FungibleTokenPacketData)(nil) - _ ibcexported.PacketData = (*FungibleTokenPacketDataV2)(nil) - _ ibcexported.PacketDataProvider = (*FungibleTokenPacketDataV2)(nil) ) const ( @@ -112,17 +110,15 @@ func (ftpd FungibleTokenPacketData) GetCustomPacketData(key string) interface{} // NewFungibleTokenPacketDataV2 constructs a new FungibleTokenPacketDataV2 instance func NewFungibleTokenPacketDataV2( - tokens []Token, + token Token, sender, receiver string, memo string, - forwarding ForwardingPacketData, ) FungibleTokenPacketDataV2 { return FungibleTokenPacketDataV2{ - Tokens: tokens, - Sender: sender, - Receiver: receiver, - Memo: memo, - Forwarding: forwarding, + Token: token, + Sender: sender, + Receiver: receiver, + Memo: memo, } } @@ -138,29 +134,14 @@ func (ftpd FungibleTokenPacketDataV2) ValidateBasic() error { return errorsmod.Wrap(ibcerrors.ErrInvalidAddress, "receiver address cannot be blank") } - if len(ftpd.Tokens) == 0 { - return errorsmod.Wrap(ErrInvalidAmount, "tokens cannot be empty") - } - - for _, token := range ftpd.Tokens { - if err := token.Validate(); err != nil { - return err - } + if err := ftpd.Token.Validate(); err != nil { + return err } if len(ftpd.Memo) > MaximumMemoLength { return errorsmod.Wrapf(ErrInvalidMemo, "memo must not exceed %d bytes", MaximumMemoLength) } - if err := ftpd.Forwarding.Validate(); err != nil { - return err - } - - // We cannot have non-empty memo and non-empty forwarding path hops at the same time. - if ftpd.HasForwarding() && ftpd.Memo != "" { - return errorsmod.Wrapf(ErrInvalidMemo, "memo must be empty if forwarding path hops is not empty: %s, %s", ftpd.Memo, ftpd.Forwarding.Hops) - } - return nil } @@ -208,11 +189,6 @@ func (ftpd FungibleTokenPacketDataV2) GetPacketSender(sourcePortID string) strin return ftpd.Sender } -// HasForwarding determines if the packet should be forwarded to the next hop. -func (ftpd FungibleTokenPacketDataV2) HasForwarding() bool { - return len(ftpd.Forwarding.Hops) > 0 -} - // UnmarshalPacketData attempts to unmarshal the provided packet data bytes into a FungibleTokenPacketDataV2. func UnmarshalPacketData(bz []byte, ics20Version string, encoding string) (FungibleTokenPacketDataV2, error) { const failedUnmarshalingErrorMsg = "cannot unmarshal %s transfer packet data: %s" @@ -226,19 +202,11 @@ func UnmarshalPacketData(bz []byte, ics20Version string, encoding string) (Fungi encoding = EncodingJSON } data = &FungibleTokenPacketData{} - case V2: - if encoding == "" { - encoding = EncodingProtobuf - } - data = &FungibleTokenPacketDataV2{} default: return FungibleTokenPacketDataV2{}, errorsmod.Wrap(ErrInvalidVersion, ics20Version) } - errorMsgVersion := "ICS20-V2" - if ics20Version == V1 { - errorMsgVersion = "ICS20-V1" - } + errorMsgVersion := "ICS20-V1" // Here we perform the unmarshaling based on the specified encoding. // The functions act on the generic "data" variable which is of type proto.Message (an interface). @@ -271,29 +239,15 @@ func UnmarshalPacketData(bz []byte, ics20Version string, encoding string) (Fungi } // When the unmarshaling is done, we want to retrieve the underlying data type based on the value of ics20Version - // If it's v1, we convert the data to FungibleTokenPacketData and then call the conversion function to construct + // Since it has to be v1, we convert the data to FungibleTokenPacketData and then call the conversion function to construct // the v2 type. - if ics20Version == V1 { - datav1, ok := data.(*FungibleTokenPacketData) - if !ok { - // We should never get here, as we manually constructed the type at the beginning of the file - return FungibleTokenPacketDataV2{}, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "cannot convert proto message into FungibleTokenPacketData") - } - // The call to ValidateBasic for V1 is done inside PacketDataV1toV2. - return PacketDataV1ToV2(*datav1) - } - - // If it's v2, we convert the data to FungibleTokenPacketDataV2, validate it and return it. - datav2, ok := data.(*FungibleTokenPacketDataV2) + datav1, ok := data.(*FungibleTokenPacketData) if !ok { // We should never get here, as we manually constructed the type at the beginning of the file - return FungibleTokenPacketDataV2{}, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "cannot convert proto message into FungibleTokenPacketDataV2") - } - - if err := datav2.ValidateBasic(); err != nil { - return FungibleTokenPacketDataV2{}, err + return FungibleTokenPacketDataV2{}, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "cannot convert proto message into FungibleTokenPacketData") } - return *datav2, nil + // The call to ValidateBasic for V1 is done inside PacketDataV1toV2. + return PacketDataV1ToV2(*datav1) } // PacketDataV1ToV2 converts a v1 packet data to a v2 packet data. The packet data is validated @@ -305,15 +259,12 @@ func PacketDataV1ToV2(packetData FungibleTokenPacketData) (FungibleTokenPacketDa denom := ExtractDenomFromPath(packetData.Denom) return FungibleTokenPacketDataV2{ - Tokens: []Token{ - { - Denom: denom, - Amount: packetData.Amount, - }, + Token: Token{ + Denom: denom, + Amount: packetData.Amount, }, - Sender: packetData.Sender, - Receiver: packetData.Receiver, - Memo: packetData.Memo, - Forwarding: ForwardingPacketData{}, + Sender: packetData.Sender, + Receiver: packetData.Receiver, + Memo: packetData.Memo, }, nil } diff --git a/modules/apps/transfer/types/packet.pb.go b/modules/apps/transfer/types/packet.pb.go index 2cf81795e7b..f5ca8844b2d 100644 --- a/modules/apps/transfer/types/packet.pb.go +++ b/modules/apps/transfer/types/packet.pb.go @@ -112,15 +112,13 @@ func (m *FungibleTokenPacketData) GetMemo() string { // https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#data-structures type FungibleTokenPacketDataV2 struct { // the tokens to be transferred - Tokens []Token `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens"` + Token Token `protobuf:"bytes,1,opt,name=token,proto3" json:"token"` // the sender address Sender string `protobuf:"bytes,2,opt,name=sender,proto3" json:"sender,omitempty"` // the recipient address on the destination chain Receiver string `protobuf:"bytes,3,opt,name=receiver,proto3" json:"receiver,omitempty"` // optional memo Memo string `protobuf:"bytes,4,opt,name=memo,proto3" json:"memo,omitempty"` - // optional forwarding information - Forwarding ForwardingPacketData `protobuf:"bytes,5,opt,name=forwarding,proto3" json:"forwarding"` } func (m *FungibleTokenPacketDataV2) Reset() { *m = FungibleTokenPacketDataV2{} } @@ -156,11 +154,11 @@ func (m *FungibleTokenPacketDataV2) XXX_DiscardUnknown() { var xxx_messageInfo_FungibleTokenPacketDataV2 proto.InternalMessageInfo -func (m *FungibleTokenPacketDataV2) GetTokens() []Token { +func (m *FungibleTokenPacketDataV2) GetToken() Token { if m != nil { - return m.Tokens + return m.Token } - return nil + return Token{} } func (m *FungibleTokenPacketDataV2) GetSender() string { @@ -184,74 +182,9 @@ func (m *FungibleTokenPacketDataV2) GetMemo() string { return "" } -func (m *FungibleTokenPacketDataV2) GetForwarding() ForwardingPacketData { - if m != nil { - return m.Forwarding - } - return ForwardingPacketData{} -} - -// ForwardingPacketData defines a list of port ID, channel ID pairs determining the path -// through which a packet must be forwarded, and the destination memo string to be used in the -// final destination of the tokens. -type ForwardingPacketData struct { - // optional memo consumed by final destination chain - DestinationMemo string `protobuf:"bytes,1,opt,name=destination_memo,json=destinationMemo,proto3" json:"destination_memo,omitempty"` - // optional intermediate path through which packet will be forwarded. - Hops []Hop `protobuf:"bytes,2,rep,name=hops,proto3" json:"hops"` -} - -func (m *ForwardingPacketData) Reset() { *m = ForwardingPacketData{} } -func (m *ForwardingPacketData) String() string { return proto.CompactTextString(m) } -func (*ForwardingPacketData) ProtoMessage() {} -func (*ForwardingPacketData) Descriptor() ([]byte, []int) { - return fileDescriptor_653ca2ce9a5ca313, []int{2} -} -func (m *ForwardingPacketData) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *ForwardingPacketData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_ForwardingPacketData.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *ForwardingPacketData) XXX_Merge(src proto.Message) { - xxx_messageInfo_ForwardingPacketData.Merge(m, src) -} -func (m *ForwardingPacketData) XXX_Size() int { - return m.Size() -} -func (m *ForwardingPacketData) XXX_DiscardUnknown() { - xxx_messageInfo_ForwardingPacketData.DiscardUnknown(m) -} - -var xxx_messageInfo_ForwardingPacketData proto.InternalMessageInfo - -func (m *ForwardingPacketData) GetDestinationMemo() string { - if m != nil { - return m.DestinationMemo - } - return "" -} - -func (m *ForwardingPacketData) GetHops() []Hop { - if m != nil { - return m.Hops - } - return nil -} - func init() { proto.RegisterType((*FungibleTokenPacketData)(nil), "ibc.applications.transfer.v2.FungibleTokenPacketData") proto.RegisterType((*FungibleTokenPacketDataV2)(nil), "ibc.applications.transfer.v2.FungibleTokenPacketDataV2") - proto.RegisterType((*ForwardingPacketData)(nil), "ibc.applications.transfer.v2.ForwardingPacketData") } func init() { @@ -259,34 +192,28 @@ func init() { } var fileDescriptor_653ca2ce9a5ca313 = []byte{ - // 418 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0x41, 0x8b, 0xd3, 0x40, - 0x14, 0xc7, 0x93, 0x34, 0x5b, 0x74, 0xf6, 0xa0, 0x0c, 0x45, 0x63, 0x91, 0xb8, 0xd6, 0x4b, 0x17, - 0x71, 0x86, 0x8d, 0x07, 0x11, 0x4f, 0x2e, 0xb2, 0x78, 0x11, 0x74, 0x11, 0x11, 0x2f, 0x32, 0x99, - 0xcc, 0x66, 0x87, 0x36, 0xf3, 0xc2, 0xcc, 0x24, 0xe2, 0x45, 0xfc, 0x06, 0xfa, 0xb1, 0x7a, 0xec, - 0xd1, 0x93, 0x48, 0xfb, 0x45, 0x24, 0x93, 0xd8, 0xe6, 0x60, 0x73, 0x7b, 0xef, 0x9f, 0xff, 0xfb, - 0xf3, 0x9b, 0x97, 0x87, 0x4e, 0x65, 0xca, 0x29, 0x2b, 0xcb, 0xa5, 0xe4, 0xcc, 0x4a, 0x50, 0x86, - 0x5a, 0xcd, 0x94, 0xb9, 0x12, 0x9a, 0xd6, 0x09, 0x2d, 0x19, 0x5f, 0x08, 0x4b, 0x4a, 0x0d, 0x16, - 0xf0, 0x7d, 0x99, 0x72, 0xd2, 0xb7, 0x92, 0x7f, 0x56, 0x52, 0x27, 0xd3, 0xf9, 0x60, 0x90, 0x85, - 0x85, 0x50, 0x6d, 0xce, 0x74, 0x92, 0x43, 0x0e, 0xae, 0xa4, 0x4d, 0xd5, 0xa9, 0x8f, 0x07, 0xe6, - 0xcf, 0x76, 0x75, 0x6b, 0x9e, 0xfd, 0xf0, 0xd1, 0xdd, 0x8b, 0x4a, 0xe5, 0x32, 0x5d, 0x8a, 0xf7, - 0x4d, 0xf4, 0x5b, 0x07, 0xfa, 0x8a, 0x59, 0x86, 0x27, 0xe8, 0x28, 0x13, 0x0a, 0x8a, 0xc8, 0x3f, - 0xf1, 0xe7, 0x37, 0x2f, 0xdb, 0x06, 0xdf, 0x41, 0x63, 0x56, 0x40, 0xa5, 0x6c, 0x14, 0x38, 0xb9, - 0xeb, 0x1a, 0xdd, 0x08, 0x95, 0x09, 0x1d, 0x8d, 0x5a, 0xbd, 0xed, 0xf0, 0x14, 0xdd, 0xd0, 0x82, - 0x0b, 0x59, 0x0b, 0x1d, 0x85, 0xee, 0xcb, 0xae, 0xc7, 0x18, 0x85, 0x85, 0x28, 0x20, 0x3a, 0x72, - 0xba, 0xab, 0x67, 0xdf, 0x03, 0x74, 0xef, 0x00, 0xd1, 0x87, 0x04, 0xbf, 0x44, 0x63, 0xb7, 0x01, - 0x13, 0xf9, 0x27, 0xa3, 0xf9, 0x71, 0xf2, 0x88, 0x0c, 0xed, 0x92, 0xb8, 0x80, 0xf3, 0x70, 0xf5, - 0xfb, 0x81, 0x77, 0xd9, 0x0d, 0xf6, 0x40, 0x83, 0x83, 0xa0, 0xa3, 0x03, 0xa0, 0xe1, 0x1e, 0x14, - 0x7f, 0x44, 0xe8, 0x0a, 0xf4, 0x17, 0xa6, 0x33, 0xa9, 0x72, 0xf7, 0x84, 0xe3, 0x24, 0x19, 0xc6, - 0xb9, 0xd8, 0xf9, 0xf7, 0x8f, 0xea, 0xe8, 0x7a, 0x59, 0xb3, 0x6f, 0x68, 0xf2, 0x3f, 0x27, 0x3e, - 0x45, 0xb7, 0x33, 0x61, 0xac, 0x54, 0x2e, 0xfa, 0xb3, 0x23, 0x6a, 0xff, 0xcd, 0xad, 0x9e, 0xfe, - 0xa6, 0x81, 0x7b, 0x81, 0xc2, 0x6b, 0x28, 0x4d, 0x14, 0xb8, 0x2d, 0x3d, 0x1c, 0xc2, 0x3a, 0x23, - 0xaf, 0xa1, 0xec, 0x28, 0xdc, 0xd0, 0xf9, 0xbb, 0xd5, 0x26, 0xf6, 0xd7, 0x9b, 0xd8, 0xff, 0xb3, - 0x89, 0xfd, 0x9f, 0xdb, 0xd8, 0x5b, 0x6f, 0x63, 0xef, 0xd7, 0x36, 0xf6, 0x3e, 0x3d, 0xcb, 0xa5, - 0xbd, 0xae, 0x52, 0xc2, 0xa1, 0xa0, 0x1c, 0x4c, 0x01, 0x86, 0xca, 0x94, 0x3f, 0xc9, 0x81, 0xd6, - 0xcf, 0x69, 0x01, 0x59, 0xb5, 0x14, 0xa6, 0xb9, 0xbd, 0xde, 0xcd, 0xd9, 0xaf, 0xa5, 0x30, 0xe9, - 0xd8, 0x9d, 0xdb, 0xd3, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe7, 0x73, 0xe7, 0x36, 0x26, 0x03, - 0x00, 0x00, + // 335 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xb1, 0x4e, 0xf3, 0x30, + 0x14, 0x85, 0x93, 0x36, 0xad, 0xfe, 0xdf, 0x6c, 0x56, 0x05, 0xa1, 0x42, 0x01, 0x95, 0xa5, 0x08, + 0x61, 0x8b, 0x30, 0x20, 0x26, 0xa4, 0x0a, 0x31, 0x43, 0x85, 0x18, 0xd8, 0x1c, 0xd7, 0x04, 0xab, + 0xb5, 0x6f, 0x14, 0x3b, 0x91, 0x78, 0x0a, 0x78, 0x08, 0x1e, 0xa6, 0x63, 0x47, 0x26, 0x84, 0xda, + 0x17, 0x41, 0x71, 0x4a, 0xe9, 0xd2, 0x6e, 0xe7, 0x1c, 0xdf, 0x7b, 0xf5, 0xc9, 0x07, 0x9d, 0xc8, + 0x84, 0x53, 0x96, 0x65, 0x13, 0xc9, 0x99, 0x95, 0xa0, 0x0d, 0xb5, 0x39, 0xd3, 0xe6, 0x59, 0xe4, + 0xb4, 0x8c, 0x69, 0xc6, 0xf8, 0x58, 0x58, 0x92, 0xe5, 0x60, 0x01, 0x1f, 0xc8, 0x84, 0x93, 0xf5, + 0x51, 0xf2, 0x3b, 0x4a, 0xca, 0xb8, 0xdb, 0xdf, 0x7a, 0xc8, 0xc2, 0x58, 0xe8, 0xfa, 0x4e, 0xb7, + 0x93, 0x42, 0x0a, 0x4e, 0xd2, 0x4a, 0x2d, 0xd3, 0xd3, 0x2d, 0xfb, 0xe7, 0x2b, 0x5d, 0x0f, 0xf7, + 0xde, 0x7c, 0xb4, 0x77, 0x5b, 0xe8, 0x54, 0x26, 0x13, 0xf1, 0x50, 0x9d, 0xbe, 0x73, 0xa0, 0x37, + 0xcc, 0x32, 0xdc, 0x41, 0xad, 0x91, 0xd0, 0xa0, 0x42, 0xff, 0xc8, 0xef, 0xff, 0x1f, 0xd6, 0x06, + 0xef, 0xa2, 0x36, 0x53, 0x50, 0x68, 0x1b, 0x36, 0x5c, 0xbc, 0x74, 0x55, 0x6e, 0x84, 0x1e, 0x89, + 0x3c, 0x6c, 0xd6, 0x79, 0xed, 0x70, 0x17, 0xfd, 0xcb, 0x05, 0x17, 0xb2, 0x14, 0x79, 0x18, 0xb8, + 0x97, 0x95, 0xc7, 0x18, 0x05, 0x4a, 0x28, 0x08, 0x5b, 0x2e, 0x77, 0xba, 0xf7, 0xe1, 0xa3, 0xfd, + 0x0d, 0x44, 0x8f, 0x31, 0xbe, 0x46, 0x2d, 0xf7, 0x03, 0x8e, 0x69, 0x27, 0x3e, 0x26, 0xdb, 0xbe, + 0x92, 0xb8, 0xfd, 0x41, 0x30, 0xfd, 0x3a, 0xf4, 0x86, 0xf5, 0xde, 0x1a, 0x66, 0x63, 0x23, 0x66, + 0x73, 0x03, 0x66, 0xf0, 0x87, 0x39, 0xb8, 0x9f, 0xce, 0x23, 0x7f, 0x36, 0x8f, 0xfc, 0xef, 0x79, + 0xe4, 0xbf, 0x2f, 0x22, 0x6f, 0xb6, 0x88, 0xbc, 0xcf, 0x45, 0xe4, 0x3d, 0x5d, 0xa6, 0xd2, 0xbe, + 0x14, 0x09, 0xe1, 0xa0, 0x28, 0x07, 0xa3, 0xc0, 0x50, 0x99, 0xf0, 0xb3, 0x14, 0x68, 0x79, 0x45, + 0x15, 0x8c, 0x8a, 0x89, 0x30, 0x55, 0x3f, 0x6b, 0xbd, 0xd8, 0xd7, 0x4c, 0x98, 0xa4, 0xed, 0x2a, + 0xb9, 0xf8, 0x09, 0x00, 0x00, 0xff, 0xff, 0x9a, 0x22, 0x72, 0x8c, 0x4a, 0x02, 0x00, 0x00, } func (m *FungibleTokenPacketData) Marshal() (dAtA []byte, err error) { @@ -367,16 +294,6 @@ func (m *FungibleTokenPacketDataV2) MarshalToSizedBuffer(dAtA []byte) (int, erro _ = i var l int _ = l - { - size, err := m.Forwarding.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintPacket(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x2a if len(m.Memo) > 0 { i -= len(m.Memo) copy(dAtA[i:], m.Memo) @@ -398,64 +315,16 @@ func (m *FungibleTokenPacketDataV2) MarshalToSizedBuffer(dAtA []byte) (int, erro i-- dAtA[i] = 0x12 } - if len(m.Tokens) > 0 { - for iNdEx := len(m.Tokens) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Tokens[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintPacket(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0xa - } - } - return len(dAtA) - i, nil -} - -func (m *ForwardingPacketData) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *ForwardingPacketData) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *ForwardingPacketData) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Hops) > 0 { - for iNdEx := len(m.Hops) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Hops[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintPacket(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 + { + size, err := m.Token.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err } + i -= size + i = encodeVarintPacket(dAtA, i, uint64(size)) } - if len(m.DestinationMemo) > 0 { - i -= len(m.DestinationMemo) - copy(dAtA[i:], m.DestinationMemo) - i = encodeVarintPacket(dAtA, i, uint64(len(m.DestinationMemo))) - i-- - dAtA[i] = 0xa - } + i-- + dAtA[i] = 0xa return len(dAtA) - i, nil } @@ -505,12 +374,8 @@ func (m *FungibleTokenPacketDataV2) Size() (n int) { } var l int _ = l - if len(m.Tokens) > 0 { - for _, e := range m.Tokens { - l = e.Size() - n += 1 + l + sovPacket(uint64(l)) - } - } + l = m.Token.Size() + n += 1 + l + sovPacket(uint64(l)) l = len(m.Sender) if l > 0 { n += 1 + l + sovPacket(uint64(l)) @@ -523,27 +388,6 @@ func (m *FungibleTokenPacketDataV2) Size() (n int) { if l > 0 { n += 1 + l + sovPacket(uint64(l)) } - l = m.Forwarding.Size() - n += 1 + l + sovPacket(uint64(l)) - return n -} - -func (m *ForwardingPacketData) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.DestinationMemo) - if l > 0 { - n += 1 + l + sovPacket(uint64(l)) - } - if len(m.Hops) > 0 { - for _, e := range m.Hops { - l = e.Size() - n += 1 + l + sovPacket(uint64(l)) - } - } return n } @@ -794,7 +638,7 @@ func (m *FungibleTokenPacketDataV2) Unmarshal(dAtA []byte) error { switch fieldNum { case 1: if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tokens", wireType) + return fmt.Errorf("proto: wrong wireType = %d for field Token", wireType) } var msglen int for shift := uint(0); ; shift += 7 { @@ -821,8 +665,7 @@ func (m *FungibleTokenPacketDataV2) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - m.Tokens = append(m.Tokens, Token{}) - if err := m.Tokens[len(m.Tokens)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + if err := m.Token.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { return err } iNdEx = postIndex @@ -922,155 +765,6 @@ func (m *FungibleTokenPacketDataV2) Unmarshal(dAtA []byte) error { } m.Memo = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 5: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Forwarding", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPacket - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthPacket - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthPacket - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if err := m.Forwarding.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipPacket(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthPacket - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *ForwardingPacketData) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPacket - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: ForwardingPacketData: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: ForwardingPacketData: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field DestinationMemo", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPacket - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthPacket - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthPacket - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.DestinationMemo = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Hops", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowPacket - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthPacket - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthPacket - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Hops = append(m.Hops, Hop{}) - if err := m.Hops[len(m.Hops)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipPacket(dAtA[iNdEx:]) diff --git a/modules/apps/transfer/types/packet_test.go b/modules/apps/transfer/types/packet_test.go index d6b1e179903..26b2354d652 100644 --- a/modules/apps/transfer/types/packet_test.go +++ b/modules/apps/transfer/types/packet_test.go @@ -2,7 +2,6 @@ package types_test import ( "encoding/json" - "errors" "fmt" "testing" @@ -178,305 +177,143 @@ func TestFungibleTokenPacketDataV2ValidateBasic(t *testing.T) { { "success: valid packet", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, "", - ibctesting.EmptyForwardingPacketData, ), nil, }, { "success: valid packet with memo", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, "memo", - ibctesting.EmptyForwardingPacketData, ), nil, }, { "success: valid packet with large amount", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: largeAmount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: largeAmount, }, sender, receiver, "memo", - ibctesting.EmptyForwardingPacketData, - ), - nil, - }, - { - "success: valid packet with forwarding path hops", - types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, - }, - sender, - receiver, - "", - types.NewForwardingPacketData("", validHop, validHop), - ), - nil, - }, - { - "success: valid packet with forwarding path hops with memo", - types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, - }, - sender, - receiver, - "", - types.NewForwardingPacketData("memo", validHop), ), nil, }, { "failure: invalid denom", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("", types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom("", types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, "", - ibctesting.EmptyForwardingPacketData, ), types.ErrInvalidDenomForTransfer, }, { "failure: invalid empty amount", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: "", - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: "", }, sender, receiver, "", - ibctesting.EmptyForwardingPacketData, - ), - types.ErrInvalidAmount, - }, - { - "failure: invalid empty token array", - types.NewFungibleTokenPacketDataV2( - []types.Token{}, - sender, - receiver, - "", - ibctesting.EmptyForwardingPacketData, ), types.ErrInvalidAmount, }, { "failure: invalid zero amount", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: "0", - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: "0", }, sender, receiver, "", - ibctesting.EmptyForwardingPacketData, ), types.ErrInvalidAmount, }, { "failure: invalid negative amount", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: "-100", - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: "-100", }, sender, receiver, "", - ibctesting.EmptyForwardingPacketData, ), types.ErrInvalidAmount, }, { "failure: invalid large amount", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: invalidLargeAmount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: invalidLargeAmount, }, sender, receiver, "memo", - ibctesting.EmptyForwardingPacketData, ), types.ErrInvalidAmount, }, { "failure: missing sender address", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, "", receiver, "memo", - ibctesting.EmptyForwardingPacketData, ), ibcerrors.ErrInvalidAddress, }, { "failure: missing recipient address", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, "", "", - ibctesting.EmptyForwardingPacketData, ), ibcerrors.ErrInvalidAddress, }, { "failure: memo field too large", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: largeAmount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: largeAmount, }, sender, receiver, ibctesting.GenerateString(types.MaximumMemoLength+1), - ibctesting.EmptyForwardingPacketData, - ), - types.ErrInvalidMemo, - }, - { - "failure: memo must be empty if forwarding path hops is not empty", - types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, - }, - sender, - receiver, - "memo", - types.NewForwardingPacketData("", validHop), - ), - types.ErrInvalidMemo, - }, - { - "failure: invalid forwarding path port ID", - types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, - }, - sender, - receiver, - "", - types.NewForwardingPacketData( - "", - types.NewHop(invalidPort, "channel-1"), - ), - ), - types.ErrInvalidForwarding, - }, - { - "failure: invalid forwarding path channel ID", - types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, - }, - sender, - receiver, - "", - types.NewForwardingPacketData( - "", - types.NewHop("transfer", invalidChannel), - ), - ), - types.ErrInvalidForwarding, - }, - { - "failure: invalid forwarding path too many hops", - types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, - }, - sender, - receiver, - "", - types.NewForwardingPacketData("", generateHops(types.MaximumNumberOfForwardingHops+1)...), - ), - types.ErrInvalidForwarding, - }, - { - "failure: invalid forwarding path too long memo", - types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, - }, - sender, - receiver, - "", - types.NewForwardingPacketData(ibctesting.GenerateString(types.MaximumMemoLength+1), validHop), ), types.ErrInvalidMemo, }, @@ -504,32 +341,26 @@ func TestGetPacketSender(t *testing.T) { { "non-empty sender field", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, "", - ibctesting.EmptyForwardingPacketData, ), sender, }, { "empty sender field", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, "", receiver, "abc", - ibctesting.EmptyForwardingPacketData, ), "", }, @@ -551,16 +382,13 @@ func TestPacketDataProvider(t *testing.T) { { "success: src_callback key in memo", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, fmt.Sprintf(`{"src_callback": {"address": "%s"}}`, receiver), - ibctesting.EmptyForwardingPacketData, ), map[string]interface{}{ @@ -570,16 +398,13 @@ func TestPacketDataProvider(t *testing.T) { { "success: src_callback key in memo with additional fields", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, fmt.Sprintf(`{"src_callback": {"address": "%s", "gas_limit": "200000"}}`, receiver), - ibctesting.EmptyForwardingPacketData, ), map[string]interface{}{ "address": receiver, @@ -589,64 +414,52 @@ func TestPacketDataProvider(t *testing.T) { { "success: src_callback has string value", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, `{"src_callback": "string"}`, - ibctesting.EmptyForwardingPacketData, ), "string", }, { "failure: src_callback key not found memo", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, fmt.Sprintf(`{"dest_callback": {"address": "%s", "min_gas": "200000"}}`, receiver), - ibctesting.EmptyForwardingPacketData, ), nil, }, { "failure: empty memo", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, "", - ibctesting.EmptyForwardingPacketData, ), nil, }, { "failure: non-json memo", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, "invalid", - ibctesting.EmptyForwardingPacketData, ), nil, }, @@ -669,32 +482,26 @@ func TestFungibleTokenPacketDataOmitEmpty(t *testing.T) { { "empty memo field, resulting marshalled bytes should not contain the memo field", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, "", - ibctesting.EmptyForwardingPacketData, ), false, }, { "non-empty memo field, resulting marshalled bytes should contain the memo field", types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: amount, - }, + types.Token{ + Denom: types.NewDenom(denom, types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: amount, }, sender, receiver, "abc", - ibctesting.EmptyForwardingPacketData, ), true, }, @@ -765,77 +572,18 @@ func TestUnmarshalPacketData(t *testing.T) { nil, }, { - "success: v2 with empty encoding (protobuf)", + "failure: v2 with empty encoding (protobuf)", func() { packetData := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0")), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}) + types.Token{ + Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0")), + Amount: "1000", + }, sender, receiver, "") packetDataBz = packetData.GetBytes() - version = types.V2 - }, - nil, - }, - { - "success: v2 with JSON encoding", - func() { - packetData := types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0")), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}) - - packetDataBz, _ = json.Marshal(packetData) - version = types.V2 - encoding = types.EncodingJSON + version = "ics20-2" }, - nil, - }, - { - "failure: v2 with ABI encoding (not supported)", - func() { - packetDataBz = []byte("should fail before this gets relevant") - version = types.V2 - encoding = types.EncodingABI - }, - errors.New("encoding application/x-solidity-abi is only supported for ICS20-V1"), - }, - { - "failure: invalid encoding", - func() { - encoding = "invalid" - }, - errors.New("invalid encoding provided"), - }, - { - "failure: invalid type for json", - func() { - packetDataBz = []byte("invalid") - encoding = types.EncodingJSON - }, - ibcerrors.ErrInvalidType, - }, - { - "failure: invalid type for protobuf", - func() { - packetDataBz = []byte("invalid") - encoding = types.EncodingProtobuf - }, - ibcerrors.ErrInvalidType, - }, - { - "failure: invalid type for abi", - func() { - packetDataBz = []byte("invalid") - encoding = types.EncodingABI - }, - ibcerrors.ErrInvalidType, + types.ErrInvalidVersion, }, { "invalid version", @@ -859,7 +607,7 @@ func TestUnmarshalPacketData(t *testing.T) { if tc.expError == nil { require.NoError(t, err) - require.NotEmpty(t, packetData.Tokens) + require.NotEmpty(t, packetData.Token) require.NotEmpty(t, packetData.Sender) require.NotEmpty(t, packetData.Receiver) require.IsType(t, types.FungibleTokenPacketDataV2{}, packetData) @@ -869,60 +617,6 @@ func TestUnmarshalPacketData(t *testing.T) { } } -// TestV2ForwardsCompatibilityFails asserts that new fields being added to a future proto definition of -// FungibleTokenPacketDataV2 fail to unmarshal with previous versions. In essence, permit backwards compatibility -// but restrict forward one. -func TestV2ForwardsCompatibilityFails(t *testing.T) { - var ( - packet types.FungibleTokenPacketDataV2 - packetDataBz []byte - ) - - testCases := []struct { - name string - malleate func() - expError error - }{ - { - "success", - func() {}, - nil, - }, - { - "failure: new field present in packet data", - func() { - // packet data containing extra field unknown to current proto file. - packetDataBz = append(packet.GetBytes(), []byte("22\tnew_value")...) - }, - ibcerrors.ErrInvalidType, - }, - } - - for _, tc := range testCases { - packet = types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0")), - Amount: "1000", - }, - }, "sender", "receiver", "", types.ForwardingPacketData{}, - ) - - packetDataBz = packet.GetBytes() - - tc.malleate() - - packetData, err := types.UnmarshalPacketData(packetDataBz, types.V2, types.EncodingProtobuf) - - if tc.expError == nil { - require.NoError(t, err) - require.NotEqual(t, types.FungibleTokenPacketDataV2{}, packetData) - } else { - require.ErrorIs(t, err, tc.expError) - } - } -} - func TestPacketV1ToPacketV2(t *testing.T) { const ( sender = "sender" @@ -939,84 +633,70 @@ func TestPacketV1ToPacketV2(t *testing.T) { "success", types.NewFungibleTokenPacketData("transfer/channel-0/atom", "1000", sender, receiver, ""), types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0")), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}), + types.Token{ + Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0")), + Amount: "1000", + }, sender, receiver, ""), nil, }, { "success with empty trace", types.NewFungibleTokenPacketData("atom", "1000", sender, receiver, ""), types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom"), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}), + types.Token{ + Denom: types.NewDenom("atom"), + Amount: "1000", + }, sender, receiver, ""), nil, }, { "success: base denom with '/'", types.NewFungibleTokenPacketData("transfer/channel-0/atom/withslash", "1000", sender, receiver, ""), types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom/withslash", types.NewHop("transfer", "channel-0")), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}), + types.Token{ + Denom: types.NewDenom("atom/withslash", types.NewHop("transfer", "channel-0")), + Amount: "1000", + }, sender, receiver, ""), nil, }, { "success: base denom with '/' at the end", types.NewFungibleTokenPacketData("transfer/channel-0/atom/", "1000", sender, receiver, ""), types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom/", types.NewHop("transfer", "channel-0")), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}), + types.Token{ + Denom: types.NewDenom("atom/", types.NewHop("transfer", "channel-0")), + Amount: "1000", + }, sender, receiver, ""), nil, }, { "success: longer trace base denom with '/'", types.NewFungibleTokenPacketData("transfer/channel-0/transfer/channel-1/atom/pool", "1000", sender, receiver, ""), types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom/pool", types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}), + types.Token{ + Denom: types.NewDenom("atom/pool", types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1")), + Amount: "1000", + }, sender, receiver, ""), nil, }, { "success: longer trace with non transfer port", types.NewFungibleTokenPacketData("transfer/channel-0/transfer/channel-1/transfer-custom/channel-2/atom", "1000", sender, receiver, ""), types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1"), types.NewHop("transfer-custom", "channel-2")), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}), + types.Token{ + Denom: types.NewDenom("atom", types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1"), types.NewHop("transfer-custom", "channel-2")), + Amount: "1000", + }, sender, receiver, ""), nil, }, { "success: base denom with slash, trace with non transfer port", types.NewFungibleTokenPacketData("transfer/channel-0/transfer/channel-1/transfer-custom/channel-2/atom/pool", "1000", sender, receiver, ""), types.NewFungibleTokenPacketDataV2( - []types.Token{ - { - Denom: types.NewDenom("atom/pool", types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1"), types.NewHop("transfer-custom", "channel-2")), - Amount: "1000", - }, - }, sender, receiver, "", types.ForwardingPacketData{}), + types.Token{ + Denom: types.NewDenom("atom/pool", types.NewHop("transfer", "channel-0"), types.NewHop("transfer", "channel-1"), types.NewHop("transfer-custom", "channel-2")), + Amount: "1000", + }, sender, receiver, ""), nil, }, { diff --git a/modules/apps/transfer/types/token.go b/modules/apps/transfer/types/token.go index d30a765f0f2..161ab6e607d 100644 --- a/modules/apps/transfer/types/token.go +++ b/modules/apps/transfer/types/token.go @@ -9,9 +9,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// Tokens is a slice of Tokens -type Tokens []Token - // maxUint256 is the maximum value for a 256 bit unsigned integer. var maxUint256 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1)) diff --git a/modules/apps/transfer/types/transfer.pb.go b/modules/apps/transfer/types/transfer.pb.go index 8f5ed10b56f..099d8101221 100644 --- a/modules/apps/transfer/types/transfer.pb.go +++ b/modules/apps/transfer/types/transfer.pb.go @@ -83,63 +83,6 @@ func (m *Params) GetReceiveEnabled() bool { return false } -// Forwarding defines a list of port ID, channel ID pairs determining the path -// through which a packet must be forwarded, and an unwind boolean indicating if -// the coin should be unwinded to its native chain before forwarding. -type Forwarding struct { - // optional unwinding for the token transferred - Unwind bool `protobuf:"varint,1,opt,name=unwind,proto3" json:"unwind,omitempty"` - // optional intermediate path through which packet will be forwarded - Hops []Hop `protobuf:"bytes,2,rep,name=hops,proto3" json:"hops"` -} - -func (m *Forwarding) Reset() { *m = Forwarding{} } -func (m *Forwarding) String() string { return proto.CompactTextString(m) } -func (*Forwarding) ProtoMessage() {} -func (*Forwarding) Descriptor() ([]byte, []int) { - return fileDescriptor_5041673e96e97901, []int{1} -} -func (m *Forwarding) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *Forwarding) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_Forwarding.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *Forwarding) XXX_Merge(src proto.Message) { - xxx_messageInfo_Forwarding.Merge(m, src) -} -func (m *Forwarding) XXX_Size() int { - return m.Size() -} -func (m *Forwarding) XXX_DiscardUnknown() { - xxx_messageInfo_Forwarding.DiscardUnknown(m) -} - -var xxx_messageInfo_Forwarding proto.InternalMessageInfo - -func (m *Forwarding) GetUnwind() bool { - if m != nil { - return m.Unwind - } - return false -} - -func (m *Forwarding) GetHops() []Hop { - if m != nil { - return m.Hops - } - return nil -} - // Hop defines a port ID, channel ID pair specifying where tokens must be forwarded // next in a multihop transfer. type Hop struct { @@ -150,7 +93,7 @@ type Hop struct { func (m *Hop) Reset() { *m = Hop{} } func (*Hop) ProtoMessage() {} func (*Hop) Descriptor() ([]byte, []int) { - return fileDescriptor_5041673e96e97901, []int{2} + return fileDescriptor_5041673e96e97901, []int{1} } func (m *Hop) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -195,7 +138,6 @@ func (m *Hop) GetChannelId() string { func init() { proto.RegisterType((*Params)(nil), "ibc.applications.transfer.v1.Params") - proto.RegisterType((*Forwarding)(nil), "ibc.applications.transfer.v1.Forwarding") proto.RegisterType((*Hop)(nil), "ibc.applications.transfer.v1.Hop") } @@ -204,28 +146,25 @@ func init() { } var fileDescriptor_5041673e96e97901 = []byte{ - // 332 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xcf, 0x4a, 0xc3, 0x40, - 0x10, 0x87, 0x93, 0xb6, 0x44, 0xbb, 0x15, 0x85, 0x45, 0xb4, 0x88, 0xa6, 0x7f, 0x2e, 0x16, 0xc4, - 0x2c, 0xd5, 0x83, 0xa8, 0xb7, 0x8a, 0xd2, 0xde, 0xb4, 0x78, 0xf2, 0x52, 0x36, 0x9b, 0x35, 0x5d, - 0x48, 0x76, 0x96, 0xdd, 0x34, 0xc5, 0xb7, 0xf0, 0xe8, 0xd1, 0xc7, 0xe9, 0xb1, 0x47, 0x4f, 0x22, - 0xed, 0x8b, 0x48, 0xd2, 0x58, 0x7a, 0xf2, 0x36, 0xf3, 0xcd, 0x37, 0xc3, 0xb2, 0x3f, 0x74, 0x26, - 0x7c, 0x46, 0xa8, 0x52, 0x91, 0x60, 0x34, 0x11, 0x20, 0x0d, 0x49, 0x34, 0x95, 0xe6, 0x95, 0x6b, - 0x92, 0x76, 0xd7, 0xb5, 0xa7, 0x34, 0x24, 0x80, 0x8f, 0x85, 0xcf, 0xbc, 0x4d, 0xd9, 0x5b, 0x0b, - 0x69, 0xf7, 0x68, 0x3f, 0x84, 0x10, 0x72, 0x91, 0x64, 0xd5, 0x6a, 0xa7, 0xfd, 0x8c, 0x9c, 0x47, - 0xaa, 0x69, 0x6c, 0x70, 0x0b, 0xed, 0x18, 0x2e, 0x83, 0x11, 0x97, 0xd4, 0x8f, 0x78, 0x50, 0xb7, - 0x9b, 0x76, 0x67, 0x7b, 0x58, 0xcb, 0xd8, 0xfd, 0x0a, 0xe1, 0x53, 0xb4, 0xa7, 0x39, 0xe3, 0x22, - 0xe5, 0x6b, 0xab, 0x94, 0x5b, 0xbb, 0x05, 0x2e, 0xc4, 0x36, 0x45, 0xe8, 0x01, 0xf4, 0x94, 0xea, - 0x40, 0xc8, 0x10, 0x1f, 0x20, 0x67, 0x22, 0xa7, 0x42, 0xfe, 0xdd, 0x2c, 0x3a, 0x7c, 0x8b, 0x2a, - 0x63, 0x50, 0xa6, 0x5e, 0x6a, 0x96, 0x3b, 0xb5, 0x8b, 0x96, 0xf7, 0xdf, 0xf3, 0xbd, 0x3e, 0xa8, - 0x5e, 0x65, 0xf6, 0xdd, 0xb0, 0x86, 0xf9, 0x52, 0xfb, 0x0e, 0x95, 0xfb, 0xa0, 0xf0, 0x21, 0xda, - 0x52, 0xa0, 0x93, 0x91, 0x58, 0x1d, 0xaf, 0x0e, 0x9d, 0xac, 0x1d, 0x04, 0xf8, 0x04, 0x21, 0x36, - 0xa6, 0x52, 0xf2, 0x28, 0x9b, 0x95, 0xf2, 0x59, 0xb5, 0x20, 0x83, 0xe0, 0xa6, 0xf2, 0xf1, 0xd9, - 0xb0, 0x7a, 0x4f, 0xb3, 0x85, 0x6b, 0xcf, 0x17, 0xae, 0xfd, 0xb3, 0x70, 0xed, 0xf7, 0xa5, 0x6b, - 0xcd, 0x97, 0xae, 0xf5, 0xb5, 0x74, 0xad, 0x97, 0xab, 0x50, 0x24, 0xe3, 0x89, 0xef, 0x31, 0x88, - 0x09, 0x03, 0x13, 0x83, 0x21, 0xc2, 0x67, 0xe7, 0x21, 0x90, 0xf4, 0x9a, 0xc4, 0x10, 0x4c, 0x22, - 0x6e, 0xb2, 0x60, 0x36, 0x02, 0x49, 0xde, 0x14, 0x37, 0xbe, 0x93, 0xff, 0xeb, 0xe5, 0x6f, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x58, 0xc2, 0xeb, 0x86, 0xba, 0x01, 0x00, 0x00, + // 277 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x4c, 0x90, 0xb1, 0x4a, 0xc4, 0x30, + 0x1c, 0xc6, 0xdb, 0x53, 0xaa, 0x17, 0x45, 0xa1, 0x08, 0x8a, 0x68, 0xd4, 0x5b, 0x14, 0xc4, 0x86, + 0xc3, 0x41, 0x74, 0x54, 0x04, 0x6f, 0xd3, 0xc3, 0xc9, 0xe5, 0x48, 0xd2, 0xd8, 0x0b, 0xb4, 0xf9, + 0x87, 0x24, 0x57, 0xf0, 0x2d, 0x1c, 0x1d, 0x7d, 0x1c, 0xc7, 0x1b, 0x1d, 0xa5, 0x7d, 0x11, 0x49, + 0x5b, 0xca, 0x6d, 0x5f, 0x7e, 0xdf, 0x2f, 0x81, 0x7c, 0xe8, 0x52, 0x32, 0x4e, 0xa8, 0xd6, 0xb9, + 0xe4, 0xd4, 0x49, 0x50, 0x96, 0x38, 0x43, 0x95, 0x7d, 0x17, 0x86, 0x94, 0xe3, 0x3e, 0x27, 0xda, + 0x80, 0x83, 0xf8, 0x48, 0x32, 0x9e, 0xac, 0xca, 0x49, 0x2f, 0x94, 0xe3, 0xc3, 0xbd, 0x0c, 0x32, + 0x68, 0x44, 0xe2, 0x53, 0x7b, 0x67, 0xf4, 0x8a, 0xa2, 0x67, 0x6a, 0x68, 0x61, 0xe3, 0x33, 0xb4, + 0x6d, 0x85, 0x4a, 0x67, 0x42, 0x51, 0x96, 0x8b, 0xf4, 0x20, 0x3c, 0x0d, 0x2f, 0x36, 0xa7, 0x5b, + 0x9e, 0x3d, 0xb6, 0x28, 0x3e, 0x47, 0xbb, 0x46, 0x70, 0x21, 0x4b, 0xd1, 0x5b, 0x83, 0xc6, 0xda, + 0xe9, 0x70, 0x27, 0x8e, 0x1e, 0xd0, 0xda, 0x13, 0xe8, 0x78, 0x1f, 0x6d, 0x68, 0x30, 0x6e, 0x26, + 0xdb, 0xd7, 0x86, 0xd3, 0xc8, 0x1f, 0x27, 0x69, 0x7c, 0x8c, 0x10, 0x9f, 0x53, 0xa5, 0x44, 0xee, + 0xbb, 0x41, 0xd3, 0x0d, 0x3b, 0x32, 0x49, 0xef, 0xd6, 0xbf, 0xbe, 0x4f, 0x82, 0xfb, 0x97, 0x9f, + 0x0a, 0x87, 0xcb, 0x0a, 0x87, 0x7f, 0x15, 0x0e, 0x3f, 0x6b, 0x1c, 0x2c, 0x6b, 0x1c, 0xfc, 0xd6, + 0x38, 0x78, 0xbb, 0xc9, 0xa4, 0x9b, 0x2f, 0x58, 0xc2, 0xa1, 0x20, 0x1c, 0x6c, 0x01, 0x96, 0x48, + 0xc6, 0xaf, 0x32, 0x20, 0xe5, 0x2d, 0x29, 0x20, 0x5d, 0xe4, 0xc2, 0xfa, 0xd5, 0x56, 0xd6, 0x72, + 0x1f, 0x5a, 0x58, 0x16, 0x35, 0x9f, 0xbe, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x29, 0x07, 0x1d, + 0x19, 0x57, 0x01, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -271,53 +210,6 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func (m *Forwarding) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *Forwarding) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *Forwarding) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Hops) > 0 { - for iNdEx := len(m.Hops) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Hops[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTransfer(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x12 - } - } - if m.Unwind { - i-- - if m.Unwind { - dAtA[i] = 1 - } else { - dAtA[i] = 0 - } - i-- - dAtA[i] = 0x8 - } - return len(dAtA) - i, nil -} - func (m *Hop) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -381,24 +273,6 @@ func (m *Params) Size() (n int) { return n } -func (m *Forwarding) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - if m.Unwind { - n += 2 - } - if len(m.Hops) > 0 { - for _, e := range m.Hops { - l = e.Size() - n += 1 + l + sovTransfer(uint64(l)) - } - } - return n -} - func (m *Hop) Size() (n int) { if m == nil { return 0 @@ -512,110 +386,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { } return nil } -func (m *Forwarding) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: Forwarding: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: Forwarding: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Unwind", wireType) - } - var v int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - v |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - m.Unwind = bool(v != 0) - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Hops", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTransfer - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTransfer - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTransfer - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Hops = append(m.Hops, Hop{}) - if err := m.Hops[len(m.Hops)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTransfer(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTransfer - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} func (m *Hop) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/modules/apps/transfer/types/transfer_authorization.go b/modules/apps/transfer/types/transfer_authorization.go index 81a19b0b384..3f332339349 100644 --- a/modules/apps/transfer/types/transfer_authorization.go +++ b/modules/apps/transfer/types/transfer_authorization.go @@ -47,10 +47,6 @@ func (a TransferAuthorization) Accept(goCtx context.Context, msg proto.Message) return authz.AcceptResponse{}, errorsmod.Wrap(ibcerrors.ErrNotFound, "requested port and channel allocation does not exist") } - if err := validateForwarding(msgTransfer.Forwarding, a.Allocations[index].AllowedForwarding); err != nil { - return authz.AcceptResponse{}, err - } - ctx := sdk.UnwrapSDKContext(goCtx) if !isAllowedAddress(ctx, msgTransfer.Receiver, a.Allocations[index].AllowList) { @@ -64,17 +60,13 @@ func (a TransferAuthorization) Accept(goCtx context.Context, msg proto.Message) // bool flag to see if we have updated any of the allocations allocationModified := false - // update spend limit for each token in the MsgTransfer - for _, coin := range msgTransfer.GetCoins() { - // If the spend limit is set to the MaxUint256 sentinel value, do not subtract the amount from the spend limit. - // if there is no unlimited spend, then we need to subtract the amount from the spend limit to get the limit left - if a.Allocations[index].SpendLimit.AmountOf(coin.Denom).Equal(UnboundedSpendLimit()) { - continue - } - - limitLeft, isNegative := a.Allocations[index].SpendLimit.SafeSub(coin) + // update spend limit the token token in the MsgTransfer + // If the spend limit is set to the MaxUint256 sentinel value, do not subtract the amount from the spend limit. + // if there is no unlimited spend, then we need to subtract the amount from the spend limit to get the limit left + if !a.Allocations[index].SpendLimit.AmountOf(msgTransfer.Token.Denom).Equal(UnboundedSpendLimit()) { + limitLeft, isNegative := a.Allocations[index].SpendLimit.SafeSub(msgTransfer.Token) if isNegative { - return authz.AcceptResponse{}, errorsmod.Wrapf(ibcerrors.ErrInsufficientFunds, "requested amount of token %s is more than spend limit", coin.Denom) + return authz.AcceptResponse{}, errorsmod.Wrapf(ibcerrors.ErrInsufficientFunds, "requested amount of token %s is more than spend limit", msgTransfer.Token.Denom) } allocationModified = true @@ -141,14 +133,6 @@ func (a TransferAuthorization) ValidateBasic() error { } found[allocation.AllowList[i]] = true } - - for i := 0; i < len(allocation.AllowedForwarding); i++ { - for _, hop := range allocation.AllowedForwarding[i].Hops { - if err := hop.Validate(); err != nil { - return errorsmod.Wrap(err, "invalid forwarding hop") - } - } - } } return nil @@ -172,42 +156,6 @@ func isAllowedAddress(ctx sdk.Context, receiver string, allowedAddrs []string) b return false } -// validateForwarding performs the validation of forwarding info. -func validateForwarding(forwarding *Forwarding, allowedForwarding []AllowedForwarding) error { - if forwarding == nil { - return nil - } - - if forwarding.GetUnwind() { - return errorsmod.Wrap(ErrInvalidForwarding, "not allowed automatic unwind") - } - - if !isAllowedForwarding(forwarding.GetHops(), allowedForwarding) { - return errorsmod.Wrapf(ErrInvalidForwarding, "not allowed hops %s", forwarding.Hops) - } - - return nil -} - -// isAllowedForwarding returns whether the provided slice of Hop matches one of the allowed ones. -func isAllowedForwarding(hops []Hop, allowed []AllowedForwarding) bool { - if len(hops) == 0 { - return true - } - - // We want to ensure that at least one of the Hops in "allowed" - // is equal to "hops". - // Note that we can't use slices.Contains() as that is a generic - // function that requires the type Hop to satisfy the "comparable" constraint. - for _, allowedHops := range allowed { - if slices.Equal(hops, allowedHops.Hops) { - return true - } - } - - return false -} - // validateMemo returns a nil error indicating if the memo is valid for transfer. func validateMemo(ctx sdk.Context, memo string, allowedMemos []string) error { // if the allow list is empty, then the memo must be an empty string diff --git a/modules/apps/transfer/types/transfer_authorization_test.go b/modules/apps/transfer/types/transfer_authorization_test.go index a02bc51a2f4..6985fa15247 100644 --- a/modules/apps/transfer/types/transfer_authorization_test.go +++ b/modules/apps/transfer/types/transfer_authorization_test.go @@ -21,8 +21,6 @@ const ( testMemo2 = `{"forward":{"channel":"channel-11","port":"transfer","receiver":"stars1twfv52yxcyykx2lcvgl42svw46hsm5dd4ww6xy","retries":2,"timeout":1712146014542131200}}` ) -var forwardingWithValidHop = []types.AllowedForwarding{{Hops: []types.Hop{validHop}}} - func (suite *TypesTestSuite) TestTransferAuthorizationAccept() { var ( msgTransfer *types.MsgTransfer @@ -103,22 +101,6 @@ func (suite *TypesTestSuite) TestTransferAuthorizationAccept() { suite.Require().Nil(res.Updated) }, }, - { - "success: empty AllowedPacketData and empty memo in forwarding path", - func() { - allowedList := []string{} - transferAuthz.Allocations[0].AllowedPacketData = allowedList - transferAuthz.Allocations[0].AllowedForwarding = forwardingWithValidHop - msgTransfer.Forwarding = types.NewForwarding(false, validHop) - }, - func(res authz.AcceptResponse, err error) { - suite.Require().NoError(err) - - suite.Require().True(res.Accept) - suite.Require().True(res.Delete) - suite.Require().Nil(res.Updated) - }, - }, { "success: AllowedPacketData allows any packet", func() { @@ -134,22 +116,6 @@ func (suite *TypesTestSuite) TestTransferAuthorizationAccept() { suite.Require().Nil(res.Updated) }, }, - { - "success: AllowedPacketData allows any packet in forwarding path", - func() { - allowedList := []string{"*"} - transferAuthz.Allocations[0].AllowedPacketData = allowedList - transferAuthz.Allocations[0].AllowedForwarding = forwardingWithValidHop - msgTransfer.Forwarding = types.NewForwarding(false, validHop) - }, - func(res authz.AcceptResponse, err error) { - suite.Require().NoError(err) - - suite.Require().True(res.Accept) - suite.Require().True(res.Delete) - suite.Require().Nil(res.Updated) - }, - }, { "success: transfer memo allowed", func() { @@ -243,242 +209,6 @@ func (suite *TypesTestSuite) TestTransferAuthorizationAccept() { suite.Require().Error(err) }, }, - { - "success: with multiple allocations and multidenom transfer", - func() { - coins := sdk.NewCoins( - ibctesting.TestCoin, - sdk.NewCoin("atom", sdkmath.NewInt(100)), - sdk.NewCoin("osmo", sdkmath.NewInt(100)), - ) - - transferAuthz.Allocations = append(transferAuthz.Allocations, types.Allocation{ - SourcePort: ibctesting.MockPort, - SourceChannel: "channel-9", - SpendLimit: coins, - }) - - msgTransfer = types.NewMsgTransfer( - ibctesting.MockPort, - "channel-9", - coins, - suite.chainA.SenderAccount.GetAddress().String(), - ibctesting.TestAccAddress, - suite.chainB.GetTimeoutHeight(), - 0, - "", - nil, - ) - }, - func(res authz.AcceptResponse, err error) { - suite.Require().NoError(err) - - suite.Require().True(res.Accept) - suite.Require().False(res.Delete) - - updatedAuthz, ok := res.Updated.(*types.TransferAuthorization) - suite.Require().True(ok) - - // assert spent spendlimits are removed from the list - suite.Require().Len(updatedAuthz.Allocations, 1) - }, - }, - { - "success: allowed forwarding hops", - func() { - msgTransfer.Forwarding = types.NewForwarding(false, types.NewHop(ibctesting.MockPort, "channel-1"), types.NewHop(ibctesting.MockPort, "channel-2")) - transferAuthz.Allocations[0].AllowedForwarding = []types.AllowedForwarding{ - { - Hops: []types.Hop{ - types.NewHop(ibctesting.MockPort, "channel-1"), - types.NewHop(ibctesting.MockPort, "channel-2"), - }, - }, - } - }, - func(res authz.AcceptResponse, err error) { - suite.Require().NoError(err) - suite.Require().True(res.Accept) - }, - }, - { - "success: Allocation specify hops but msgTransfer does not have hops", - func() { - transferAuthz.Allocations[0].AllowedForwarding = []types.AllowedForwarding{ - { - Hops: []types.Hop{ - types.NewHop(ibctesting.MockPort, "channel-1"), - types.NewHop(ibctesting.MockPort, "channel-2"), - }, - }, - } - }, - func(res authz.AcceptResponse, err error) { - suite.Require().NoError(err) - suite.Require().True(res.Accept) - }, - }, - { - "failure: multidenom transfer spend limit is exceeded", - func() { - coins := sdk.NewCoins( - ibctesting.TestCoin, - sdk.NewCoin("atom", sdkmath.NewInt(100)), - sdk.NewCoin("osmo", sdkmath.NewInt(100)), - ) - - transferAuthz.Allocations = append(transferAuthz.Allocations, types.Allocation{ - SourcePort: ibctesting.MockPort, - SourceChannel: "channel-9", - SpendLimit: coins, - }) - - // spending more than the spend limit - coins = coins.Add(sdk.NewCoin("atom", sdkmath.NewInt(1))) - - msgTransfer = types.NewMsgTransfer( - ibctesting.MockPort, - "channel-9", - coins, - suite.chainA.SenderAccount.GetAddress().String(), - ibctesting.TestAccAddress, - suite.chainB.GetTimeoutHeight(), - 0, - "", - nil, - ) - }, - func(res authz.AcceptResponse, err error) { - suite.Require().ErrorIs(err, ibcerrors.ErrInsufficientFunds) - suite.Require().False(res.Accept) - suite.Require().False(res.Delete) - suite.Require().Nil(res.Updated) - }, - }, - { - "failure: multidenom transfer denom not in allocation", - func() { - coins := sdk.NewCoins( - ibctesting.TestCoin, - sdk.NewCoin("atom", sdkmath.NewInt(100)), - sdk.NewCoin("osmo", sdkmath.NewInt(100)), - ) - - transferAuthz.Allocations = append(transferAuthz.Allocations, types.Allocation{ - SourcePort: ibctesting.MockPort, - SourceChannel: "channel-9", - SpendLimit: coins, - }) - - // spend a coin not in the allocation - coins = coins.Add(sdk.NewCoin("newdenom", sdkmath.NewInt(1))) - - msgTransfer = types.NewMsgTransfer( - ibctesting.MockPort, - "channel-9", - coins, - suite.chainA.SenderAccount.GetAddress().String(), - ibctesting.TestAccAddress, - suite.chainB.GetTimeoutHeight(), - 0, - "", - nil, - ) - }, - func(res authz.AcceptResponse, err error) { - suite.Require().ErrorIs(err, ibcerrors.ErrInsufficientFunds) - suite.Require().False(res.Accept) - suite.Require().False(res.Delete) - suite.Require().Nil(res.Updated) - }, - }, - { - "failure: allowed forwarding hops contains more hops", - func() { - msgTransfer.Forwarding = types.NewForwarding(false, - types.NewHop(ibctesting.MockPort, "channel-1"), - types.NewHop(ibctesting.MockPort, "channel-2"), - types.NewHop(ibctesting.MockPort, "channel-3"), - ) - transferAuthz.Allocations[0].AllowedForwarding = []types.AllowedForwarding{ - { - Hops: []types.Hop{ - types.NewHop(ibctesting.MockPort, "channel-1"), - types.NewHop(ibctesting.MockPort, "channel-2"), - }, - }, - } - }, - func(res authz.AcceptResponse, err error) { - suite.Require().Error(err) - suite.Require().False(res.Accept) - }, - }, - { - "failure: allowed forwarding hops contains one different hop", - func() { - msgTransfer.Forwarding = types.NewForwarding(false, - types.NewHop(ibctesting.MockPort, "channel-1"), - types.NewHop("3", "channel-3"), - ) - transferAuthz.Allocations[0].AllowedForwarding = []types.AllowedForwarding{ - { - Hops: []types.Hop{ - types.NewHop(ibctesting.MockPort, "channel-1"), - types.NewHop(ibctesting.MockPort, "channel-2"), - }, - }, - } - }, - func(res authz.AcceptResponse, err error) { - suite.Require().Error(err) - suite.Require().False(res.Accept) - }, - }, - { - "failure: allowed forwarding hops is empty but hops are present", - func() { - msgTransfer.Forwarding = types.NewForwarding(false, - types.NewHop(ibctesting.MockPort, "channel-1"), - ) - }, - func(res authz.AcceptResponse, err error) { - suite.Require().Error(err) - suite.Require().False(res.Accept) - }, - }, - { - "failure: order of hops is different", - func() { - msgTransfer.Forwarding = types.NewForwarding(false, - types.NewHop(ibctesting.MockPort, "channel-1"), - types.NewHop(ibctesting.MockPort, "channel-2"), - ) - transferAuthz.Allocations[0].AllowedForwarding = []types.AllowedForwarding{ - { - Hops: []types.Hop{ - types.NewHop(ibctesting.MockPort, "channel-2"), - types.NewHop(ibctesting.MockPort, "channel-1"), - }, - }, - } - }, - func(res authz.AcceptResponse, err error) { - suite.Require().Error(err) - suite.Require().False(res.Accept) - }, - }, - - { - "failure: unwind is not allowed", - func() { - msgTransfer.Forwarding = types.NewForwarding(true) - }, - func(res authz.AcceptResponse, err error) { - suite.Require().Error(err) - suite.Require().False(res.Accept) - }, - }, } for _, tc := range testCases { @@ -504,13 +234,12 @@ func (suite *TypesTestSuite) TestTransferAuthorizationAccept() { msgTransfer = types.NewMsgTransfer( path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, - sdk.NewCoins(ibctesting.TestCoin), + ibctesting.TestCoin, suite.chainA.SenderAccount.GetAddress().String(), ibctesting.TestAccAddress, suite.chainB.GetTimeoutHeight(), 0, "", - nil, ) tc.malleate() @@ -574,16 +303,6 @@ func (suite *TypesTestSuite) TestTransferAuthorizationValidateBasic() { }, nil, }, - { - "success: with allowed forwarding hops", - func() { - transferAuthz.Allocations[0].AllowedForwarding = []types.AllowedForwarding{ - {Hops: []types.Hop{validHop}}, - {Hops: []types.Hop{types.NewHop(types.PortID, "channel-1")}}, - } - }, - nil, - }, { "empty allocations", func() { @@ -647,26 +366,6 @@ func (suite *TypesTestSuite) TestTransferAuthorizationValidateBasic() { }, channeltypes.ErrInvalidChannel, }, - { - "forwarding hop with invalid port ID", - func() { - transferAuthz.Allocations[0].AllowedForwarding = []types.AllowedForwarding{ - {Hops: []types.Hop{validHop}}, - {Hops: []types.Hop{types.NewHop("invalid/port", ibctesting.FirstChannelID)}}, - } - }, - host.ErrInvalidID, - }, - { - "forwarding hop with invalid channel ID", - func() { - transferAuthz.Allocations[0].AllowedForwarding = []types.AllowedForwarding{ - {Hops: []types.Hop{validHop}}, - {Hops: []types.Hop{types.NewHop(types.PortID, "invalid/channel")}}, - } - }, - host.ErrInvalidID, - }, } for _, tc := range testCases { diff --git a/modules/apps/transfer/types/tx.pb.go b/modules/apps/transfer/types/tx.pb.go index f4dd672e72f..4dc838e8a6f 100644 --- a/modules/apps/transfer/types/tx.pb.go +++ b/modules/apps/transfer/types/tx.pb.go @@ -40,8 +40,8 @@ type MsgTransfer struct { SourcePort string `protobuf:"bytes,1,opt,name=source_port,json=sourcePort,proto3" json:"source_port,omitempty"` // the channel by which the packet will be sent SourceChannel string `protobuf:"bytes,2,opt,name=source_channel,json=sourceChannel,proto3" json:"source_channel,omitempty"` - // the token to be transferred. this field has been replaced by the tokens field. - Token types.Coin `protobuf:"bytes,3,opt,name=token,proto3" json:"token"` // Deprecated: Do not use. + // token to be transferred + Token types.Coin `protobuf:"bytes,3,opt,name=token,proto3" json:"token"` // the sender address Sender string `protobuf:"bytes,4,opt,name=sender,proto3" json:"sender,omitempty"` // the recipient address on the destination chain @@ -54,10 +54,6 @@ type MsgTransfer struct { TimeoutTimestamp uint64 `protobuf:"varint,7,opt,name=timeout_timestamp,json=timeoutTimestamp,proto3" json:"timeout_timestamp,omitempty"` // optional memo Memo string `protobuf:"bytes,8,opt,name=memo,proto3" json:"memo,omitempty"` - // tokens to be transferred - Tokens []types.Coin `protobuf:"bytes,9,rep,name=tokens,proto3" json:"tokens"` - // optional forwarding information - Forwarding *Forwarding `protobuf:"bytes,10,opt,name=forwarding,proto3" json:"forwarding,omitempty"` } func (m *MsgTransfer) Reset() { *m = MsgTransfer{} } @@ -225,49 +221,46 @@ func init() { } var fileDescriptor_7401ed9bed2f8e09 = []byte{ - // 659 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x54, 0x4f, 0x6f, 0xd3, 0x30, - 0x14, 0x6f, 0x58, 0x57, 0x36, 0x97, 0x6d, 0xcc, 0xa0, 0x2d, 0x8b, 0x50, 0x5a, 0x55, 0x4c, 0x2a, - 0x9d, 0x66, 0xab, 0x43, 0x68, 0x62, 0xe2, 0xd4, 0x49, 0x68, 0x07, 0x26, 0x8d, 0x68, 0x5c, 0xb8, - 0x4c, 0x49, 0xea, 0xa5, 0xd6, 0x1a, 0x3b, 0xd8, 0x6e, 0x81, 0x0b, 0x42, 0x48, 0x48, 0x88, 0x13, - 0x1f, 0x81, 0x23, 0xc7, 0x7d, 0x8c, 0x1d, 0x77, 0xe4, 0x84, 0xd0, 0x76, 0xd8, 0x85, 0x0f, 0x81, - 0xec, 0x38, 0x25, 0x70, 0x28, 0x70, 0x49, 0xfc, 0xde, 0xfb, 0xbd, 0x3f, 0xbf, 0x9f, 0x9f, 0x0c, - 0xd6, 0x69, 0x14, 0xe3, 0x30, 0xcb, 0x86, 0x34, 0x0e, 0x15, 0xe5, 0x4c, 0x62, 0x25, 0x42, 0x26, - 0x8f, 0x89, 0xc0, 0xe3, 0x2e, 0x56, 0xaf, 0x50, 0x26, 0xb8, 0xe2, 0xf0, 0x0e, 0x8d, 0x62, 0x54, - 0x86, 0xa1, 0x02, 0x86, 0xc6, 0x5d, 0x6f, 0x39, 0x4c, 0x29, 0xe3, 0xd8, 0x7c, 0xf3, 0x04, 0xef, - 0x76, 0xc2, 0x13, 0x6e, 0x8e, 0x58, 0x9f, 0xac, 0x77, 0x35, 0xe6, 0x32, 0xe5, 0x12, 0xa7, 0x32, - 0xd1, 0xe5, 0x53, 0x99, 0xd8, 0x80, 0x6f, 0x03, 0x51, 0x28, 0x09, 0x1e, 0x77, 0x23, 0xa2, 0xc2, - 0x2e, 0x8e, 0x39, 0x65, 0x36, 0xde, 0xd0, 0x63, 0xc6, 0x5c, 0x10, 0x1c, 0x0f, 0x29, 0x61, 0x4a, - 0x67, 0xe7, 0x27, 0x0b, 0xd8, 0x98, 0xce, 0xa3, 0x18, 0xd6, 0x80, 0x5b, 0xef, 0xab, 0xa0, 0xbe, - 0x2f, 0x93, 0x43, 0xeb, 0x85, 0x0d, 0x50, 0x97, 0x7c, 0x24, 0x62, 0x72, 0x94, 0x71, 0xa1, 0x5c, - 0xa7, 0xe9, 0xb4, 0xe7, 0x03, 0x90, 0xbb, 0x0e, 0xb8, 0x50, 0x70, 0x1d, 0x2c, 0x5a, 0x40, 0x3c, - 0x08, 0x19, 0x23, 0x43, 0xf7, 0x9a, 0xc1, 0x2c, 0xe4, 0xde, 0xdd, 0xdc, 0x09, 0x1f, 0x81, 0x59, - 0xc5, 0x4f, 0x08, 0x73, 0x67, 0x9a, 0x4e, 0xbb, 0xbe, 0xb5, 0x86, 0x72, 0x56, 0x48, 0xb3, 0x42, - 0x96, 0x15, 0xda, 0xe5, 0x94, 0xf5, 0xea, 0x67, 0xdf, 0x1a, 0x95, 0x2f, 0x57, 0xa7, 0x1d, 0xc7, - 0x75, 0x82, 0x3c, 0x09, 0xae, 0x80, 0x9a, 0x24, 0xac, 0x4f, 0x84, 0x5b, 0x35, 0xc5, 0xad, 0x05, - 0x3d, 0x30, 0x27, 0x48, 0x4c, 0xe8, 0x98, 0x08, 0x77, 0xd6, 0x44, 0x26, 0x36, 0x7c, 0x02, 0x16, - 0x15, 0x4d, 0x09, 0x1f, 0xa9, 0xa3, 0x01, 0xa1, 0xc9, 0x40, 0xb9, 0x35, 0xd3, 0xda, 0x43, 0xfa, - 0xc2, 0xb4, 0x60, 0xc8, 0xca, 0x34, 0xee, 0xa2, 0x3d, 0x83, 0xe8, 0xcd, 0x4f, 0x7a, 0x07, 0x0b, - 0x36, 0x39, 0x8f, 0xc0, 0x0d, 0xb0, 0x5c, 0x54, 0xd3, 0x7f, 0xa9, 0xc2, 0x34, 0x73, 0xaf, 0x37, - 0x9d, 0x76, 0x35, 0xb8, 0x69, 0x03, 0x87, 0x85, 0x1f, 0x42, 0x50, 0x4d, 0x49, 0xca, 0xdd, 0x39, - 0x33, 0x92, 0x39, 0xc3, 0x6d, 0x50, 0x33, 0x5c, 0xa4, 0x3b, 0xdf, 0x9c, 0x99, 0xae, 0x40, 0x55, - 0x4f, 0x11, 0x58, 0x38, 0xdc, 0x03, 0xe0, 0x98, 0x8b, 0x97, 0xa1, 0xe8, 0x53, 0x96, 0xb8, 0xc0, - 0x70, 0x68, 0xa3, 0x69, 0x4b, 0x87, 0x1e, 0x4f, 0xf0, 0x41, 0x29, 0x77, 0xa7, 0xf3, 0xe1, 0x73, - 0xa3, 0xf2, 0xee, 0xea, 0xb4, 0x63, 0xe5, 0xfb, 0x78, 0x75, 0xda, 0x59, 0xc9, 0xa7, 0xd8, 0x94, - 0xfd, 0x13, 0x5c, 0xba, 0xf7, 0xd6, 0x36, 0xb8, 0x55, 0x32, 0x03, 0x22, 0x33, 0xce, 0x24, 0xd1, - 0x82, 0x4b, 0xf2, 0x62, 0x44, 0x58, 0x4c, 0xcc, 0x2e, 0x54, 0x83, 0x89, 0xbd, 0x53, 0xd5, 0xe5, - 0x5b, 0x6f, 0xc0, 0xd2, 0xbe, 0x4c, 0x9e, 0x65, 0xfd, 0x50, 0x91, 0x83, 0x50, 0x84, 0xa9, 0x34, - 0xb7, 0x47, 0x13, 0x46, 0x84, 0x5d, 0x1f, 0x6b, 0xc1, 0x1e, 0xa8, 0x65, 0x06, 0x61, 0x56, 0xa6, - 0xbe, 0x75, 0x77, 0x3a, 0xab, 0xbc, 0x5a, 0xa1, 0x4e, 0x9e, 0xb9, 0xb3, 0xf4, 0x8b, 0x93, 0x29, - 0xda, 0x5a, 0x03, 0xab, 0x7f, 0xf4, 0x2f, 0x86, 0xdf, 0xfa, 0xe1, 0x80, 0x99, 0x7d, 0x99, 0xc0, - 0x01, 0x98, 0x9b, 0xec, 0xf7, 0xbd, 0xe9, 0x3d, 0x4b, 0x1a, 0x78, 0xdd, 0x7f, 0x86, 0x4e, 0xe4, - 0x52, 0xe0, 0xc6, 0x6f, 0x4a, 0x6c, 0xfe, 0xb5, 0x44, 0x19, 0xee, 0x3d, 0xf8, 0x2f, 0x78, 0xd1, - 0xd5, 0x9b, 0x7d, 0xab, 0x37, 0xb8, 0xf7, 0xf4, 0xec, 0xc2, 0x77, 0xce, 0x2f, 0x7c, 0xe7, 0xfb, - 0x85, 0xef, 0x7c, 0xba, 0xf4, 0x2b, 0xe7, 0x97, 0x7e, 0xe5, 0xeb, 0xa5, 0x5f, 0x79, 0xbe, 0x9d, - 0x50, 0x35, 0x18, 0x45, 0x28, 0xe6, 0x29, 0xb6, 0xaf, 0x0b, 0x8d, 0xe2, 0xcd, 0x84, 0xe3, 0xf1, - 0x43, 0x9c, 0xf2, 0xfe, 0x68, 0x48, 0xa4, 0x7e, 0x31, 0x4a, 0x2f, 0x85, 0x7a, 0x9d, 0x11, 0x19, - 0xd5, 0xcc, 0x23, 0x71, 0xff, 0x67, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbb, 0x3b, 0x79, 0x37, 0x1b, - 0x05, 0x00, 0x00, + // 613 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x53, 0xcf, 0x4f, 0x13, 0x4f, + 0x14, 0xef, 0x7e, 0x29, 0xfd, 0xc2, 0x54, 0x40, 0x56, 0x03, 0xcb, 0xc6, 0x6c, 0x49, 0x23, 0x09, + 0x96, 0x30, 0x93, 0x62, 0x0c, 0xb1, 0xc7, 0x72, 0xf1, 0x20, 0x09, 0x36, 0x78, 0xf1, 0x42, 0x76, + 0xa7, 0xcf, 0xed, 0x84, 0xee, 0xcc, 0x3a, 0x33, 0x6d, 0xf4, 0x62, 0x88, 0x27, 0xe3, 0xc9, 0x3f, + 0xc1, 0xa3, 0x47, 0xfe, 0x0c, 0x8e, 0x1c, 0x3d, 0x19, 0x03, 0x07, 0x2e, 0xfe, 0x11, 0x66, 0x66, + 0xa7, 0x75, 0xf5, 0x50, 0xf5, 0xb2, 0xfb, 0x7e, 0x7c, 0xde, 0xaf, 0xcf, 0x9b, 0x87, 0xb6, 0x58, + 0x42, 0x49, 0x9c, 0xe7, 0x43, 0x46, 0x63, 0xcd, 0x04, 0x57, 0x44, 0xcb, 0x98, 0xab, 0x97, 0x20, + 0xc9, 0xb8, 0x4d, 0xf4, 0x6b, 0x9c, 0x4b, 0xa1, 0x85, 0x7f, 0x8f, 0x25, 0x14, 0x97, 0x61, 0x78, + 0x02, 0xc3, 0xe3, 0x76, 0xb8, 0x1a, 0x67, 0x8c, 0x0b, 0x62, 0xbf, 0x45, 0x40, 0x78, 0x37, 0x15, + 0xa9, 0xb0, 0x22, 0x31, 0x92, 0xb3, 0xae, 0x53, 0xa1, 0x32, 0xa1, 0x48, 0xa6, 0x52, 0x93, 0x3e, + 0x53, 0xa9, 0x73, 0x44, 0xce, 0x91, 0xc4, 0x0a, 0xc8, 0xb8, 0x9d, 0x80, 0x8e, 0xdb, 0x84, 0x0a, + 0xc6, 0x9d, 0xbf, 0x61, 0xda, 0xa4, 0x42, 0x02, 0xa1, 0x43, 0x06, 0x5c, 0x9b, 0xe8, 0x42, 0x72, + 0x80, 0x9d, 0xd9, 0x73, 0x4c, 0x9a, 0xb5, 0xe0, 0xe6, 0xd9, 0x1c, 0xaa, 0x1f, 0xaa, 0xf4, 0xd8, + 0x59, 0xfd, 0x06, 0xaa, 0x2b, 0x31, 0x92, 0x14, 0x4e, 0x72, 0x21, 0x75, 0xe0, 0x6d, 0x7a, 0xdb, + 0x8b, 0x3d, 0x54, 0x98, 0x8e, 0x84, 0xd4, 0xfe, 0x16, 0x5a, 0x76, 0x00, 0x3a, 0x88, 0x39, 0x87, + 0x61, 0xf0, 0x9f, 0xc5, 0x2c, 0x15, 0xd6, 0x83, 0xc2, 0xe8, 0x77, 0xd0, 0xbc, 0x16, 0xa7, 0xc0, + 0x83, 0xb9, 0x4d, 0x6f, 0xbb, 0xbe, 0xb7, 0x81, 0x8b, 0xa9, 0xb0, 0x99, 0x0a, 0xbb, 0xa9, 0xf0, + 0x81, 0x60, 0xbc, 0xbb, 0x78, 0xf1, 0xb5, 0x51, 0xf9, 0x7c, 0x73, 0xde, 0xf2, 0x7a, 0x45, 0x88, + 0xbf, 0x86, 0x6a, 0x0a, 0x78, 0x1f, 0x64, 0x50, 0xb5, 0xa9, 0x9d, 0xe6, 0x87, 0x68, 0x41, 0x02, + 0x05, 0x36, 0x06, 0x19, 0xcc, 0x5b, 0xcf, 0x54, 0xf7, 0x9f, 0xa2, 0x65, 0xcd, 0x32, 0x10, 0x23, + 0x7d, 0x32, 0x00, 0x96, 0x0e, 0x74, 0x50, 0xb3, 0x85, 0x43, 0x6c, 0xd6, 0x65, 0xe8, 0xc2, 0x8e, + 0xa4, 0x71, 0x1b, 0x3f, 0xb1, 0x88, 0x72, 0xe5, 0x25, 0x17, 0x5c, 0x78, 0xfc, 0x1d, 0xb4, 0x3a, + 0xc9, 0x66, 0xfe, 0x4a, 0xc7, 0x59, 0x1e, 0xfc, 0xbf, 0xe9, 0x6d, 0x57, 0x7b, 0xb7, 0x9d, 0xe3, + 0x78, 0x62, 0xf7, 0x7d, 0x54, 0xcd, 0x20, 0x13, 0xc1, 0x82, 0x6d, 0xc9, 0xca, 0x9d, 0xd6, 0xfb, + 0x4f, 0x8d, 0xca, 0xbb, 0x9b, 0xf3, 0x96, 0xeb, 0xfd, 0xc3, 0xcd, 0x79, 0x6b, 0xad, 0xa0, 0x60, + 0x57, 0xf5, 0x4f, 0x49, 0x89, 0xf2, 0xe6, 0x3e, 0xba, 0x53, 0x52, 0x7b, 0xa0, 0x72, 0xc1, 0x15, + 0x98, 0x69, 0x15, 0xbc, 0x1a, 0x01, 0xa7, 0x60, 0xd7, 0x50, 0xed, 0x4d, 0xf5, 0x4e, 0xd5, 0xa4, + 0x6f, 0xbe, 0x45, 0x2b, 0x87, 0x2a, 0x7d, 0x9e, 0xf7, 0x63, 0x0d, 0x47, 0xb1, 0x8c, 0x33, 0x65, + 0xa9, 0x63, 0x29, 0x07, 0xe9, 0x36, 0xe7, 0x34, 0xbf, 0x8b, 0x6a, 0xb9, 0x45, 0xd8, 0x6d, 0xd5, + 0xf7, 0xee, 0xe3, 0x59, 0xaf, 0x18, 0x17, 0xd9, 0xba, 0x55, 0x43, 0x50, 0xcf, 0x45, 0x76, 0x56, + 0x7e, 0xce, 0x64, 0x93, 0x36, 0x37, 0xd0, 0xfa, 0x6f, 0xf5, 0x27, 0xcd, 0xef, 0x7d, 0xf7, 0xd0, + 0xdc, 0xa1, 0x4a, 0xfd, 0x01, 0x5a, 0x98, 0x3e, 0xad, 0x07, 0xb3, 0x6b, 0x96, 0x38, 0x08, 0xdb, + 0x7f, 0x0d, 0x9d, 0xd2, 0xa5, 0xd1, 0xad, 0x5f, 0x98, 0xd8, 0xfd, 0x63, 0x8a, 0x32, 0x3c, 0x7c, + 0xf4, 0x4f, 0xf0, 0x49, 0xd5, 0x70, 0xfe, 0xcc, 0x3c, 0x9f, 0xee, 0xb3, 0x8b, 0xab, 0xc8, 0xbb, + 0xbc, 0x8a, 0xbc, 0x6f, 0x57, 0x91, 0xf7, 0xf1, 0x3a, 0xaa, 0x5c, 0x5e, 0x47, 0x95, 0x2f, 0xd7, + 0x51, 0xe5, 0xc5, 0x7e, 0xca, 0xf4, 0x60, 0x94, 0x60, 0x2a, 0x32, 0xe2, 0x0e, 0x9b, 0x25, 0x74, + 0x37, 0x15, 0x64, 0xfc, 0x98, 0x64, 0xa2, 0x3f, 0x1a, 0x82, 0x32, 0xc7, 0x5a, 0x3a, 0x52, 0xfd, + 0x26, 0x07, 0x95, 0xd4, 0xec, 0x7d, 0x3e, 0xfc, 0x11, 0x00, 0x00, 0xff, 0xff, 0x24, 0xcd, 0x21, + 0x43, 0x96, 0x04, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -410,32 +403,6 @@ func (m *MsgTransfer) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if m.Forwarding != nil { - { - size, err := m.Forwarding.MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x52 - } - if len(m.Tokens) > 0 { - for iNdEx := len(m.Tokens) - 1; iNdEx >= 0; iNdEx-- { - { - size, err := m.Tokens[iNdEx].MarshalToSizedBuffer(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarintTx(dAtA, i, uint64(size)) - } - i-- - dAtA[i] = 0x4a - } - } if len(m.Memo) > 0 { i -= len(m.Memo) copy(dAtA[i:], m.Memo) @@ -634,16 +601,6 @@ func (m *MsgTransfer) Size() (n int) { if l > 0 { n += 1 + l + sovTx(uint64(l)) } - if len(m.Tokens) > 0 { - for _, e := range m.Tokens { - l = e.Size() - n += 1 + l + sovTx(uint64(l)) - } - } - if m.Forwarding != nil { - l = m.Forwarding.Size() - n += 1 + l + sovTx(uint64(l)) - } return n } @@ -963,76 +920,6 @@ func (m *MsgTransfer) Unmarshal(dAtA []byte) error { } m.Memo = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex - case 9: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Tokens", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Tokens = append(m.Tokens, types.Coin{}) - if err := m.Tokens[len(m.Tokens)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex - case 10: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Forwarding", wireType) - } - var msglen int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - msglen |= int(b&0x7F) << shift - if b < 0x80 { - break - } - } - if msglen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + msglen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - if m.Forwarding == nil { - m.Forwarding = &Forwarding{} - } - if err := m.Forwarding.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { - return err - } - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipTx(dAtA[iNdEx:]) diff --git a/modules/apps/transfer/v2/ibc_module.go b/modules/apps/transfer/v2/ibc_module.go index 3a68da435a1..777eade26df 100644 --- a/modules/apps/transfer/v2/ibc_module.go +++ b/modules/apps/transfer/v2/ibc_module.go @@ -63,19 +63,17 @@ func (im *IBCModule) OnSendPacket(goCtx context.Context, sourceChannel string, d // This prevents such denominations from being sent with IBCV v2 packets, however we can still support them in IBC v1 packets // If we enforce that IBC v2 packets are sent with ICS20 v2 and above versions that separate the trace from the base denomination // in the packet data, then we can remove this restriction. - for _, token := range data.Tokens { - if strings.Contains(token.Denom.Base, "/") { - return errorsmod.Wrapf(types.ErrInvalidDenomForTransfer, "base denomination %s cannot contain slashes for IBC v2 packet", token.Denom.Base) - } + if strings.Contains(data.Token.Denom.Base, "/") { + return errorsmod.Wrapf(types.ErrInvalidDenomForTransfer, "base denomination %s cannot contain slashes for IBC v2 packet", data.Token.Denom.Base) } - if err := im.keeper.SendTransfer(sdk.UnwrapSDKContext(goCtx), payload.SourcePort, sourceChannel, data.Tokens, signer); err != nil { + if err := im.keeper.SendTransfer(sdk.UnwrapSDKContext(goCtx), payload.SourcePort, sourceChannel, data.Token, signer); err != nil { return err } - events.EmitTransferEvent(goCtx, sender.String(), data.Receiver, data.Tokens, data.Memo, data.Forwarding.Hops) + events.EmitTransferEvent(goCtx, sender.String(), data.Receiver, data.Token, data.Memo) - telemetry.ReportTransfer(payload.SourcePort, sourceChannel, payload.DestinationPort, destinationChannel, data.Tokens) + telemetry.ReportTransfer(payload.SourcePort, sourceChannel, payload.DestinationPort, destinationChannel, data.Token) return nil } @@ -115,7 +113,7 @@ func (im *IBCModule) OnRecvPacket(ctx context.Context, sourceChannel string, des } } - if _, ackErr = im.keeper.OnRecvPacket( + if ackErr = im.keeper.OnRecvPacket( ctx, data, payload.SourcePort, @@ -131,24 +129,7 @@ func (im *IBCModule) OnRecvPacket(ctx context.Context, sourceChannel string, des im.keeper.Logger(ctx).Info("successfully handled ICS-20 packet", "sequence", sequence) - telemetry.ReportOnRecvPacket(payload.SourcePort, sourceChannel, payload.DestinationPort, destinationChannel, data.Tokens) - - if data.HasForwarding() { - // we are now sending from the forward escrow address to the final receiver address. - return channeltypesv2.RecvPacketResult{ - Status: channeltypesv2.PacketStatus_Failure, - } - // TODO: handle forwarding - // TODO: inside this version of the function, we should fetch the packet that was stored in IBC core in order to set it for forwarding. - // if err := k.forwardPacket(ctx, data, packet, receivedCoins); err != nil { - // return err - // } - - // NOTE: acknowledgement will be written asynchronously - // return types.RecvPacketResult{ - // Status: types.PacketStatus_Async, - // } - } + telemetry.ReportOnRecvPacket(payload.SourcePort, sourceChannel, payload.DestinationPort, destinationChannel, data.Token) // NOTE: acknowledgement will be written synchronously during IBC handler execution. return recvResult @@ -165,8 +146,6 @@ func (im *IBCModule) OnTimeoutPacket(ctx context.Context, sourceChannel string, return err } - // TODO: handle forwarding - events.EmitOnTimeoutEvent(ctx, data) return nil @@ -196,8 +175,6 @@ func (im *IBCModule) OnAcknowledgementPacket(ctx context.Context, sourceChannel return err } - // TODO: handle forwarding - events.EmitOnAcknowledgementPacketEvent(ctx, data, ack) return nil diff --git a/modules/apps/transfer/v2/ibc_module_test.go b/modules/apps/transfer/v2/ibc_module_test.go index bd5b02106dc..283acfced6e 100644 --- a/modules/apps/transfer/v2/ibc_module_test.go +++ b/modules/apps/transfer/v2/ibc_module_test.go @@ -61,26 +61,20 @@ func TestTransferTestSuite(t *testing.T) { func (suite *TransferTestSuite) TestOnSendPacket() { var payload channeltypesv2.Payload testCases := []struct { - name string - sourceDenomsToTransfer []string - malleate func() - expError error + name string + sourceDenomToTransfer string + malleate func() + expError error }{ { "transfer single denom", - []string{sdk.DefaultBondDenom}, - func() {}, - nil, - }, - { - "transfer multiple denoms", - []string{sdk.DefaultBondDenom, ibctesting.SecondaryDenom}, + sdk.DefaultBondDenom, func() {}, nil, }, { "transfer with invalid source port", - []string{sdk.DefaultBondDenom}, + sdk.DefaultBondDenom, func() { payload.SourcePort = invalidPortID }, @@ -88,7 +82,7 @@ func (suite *TransferTestSuite) TestOnSendPacket() { }, { "transfer with invalid destination port", - []string{sdk.DefaultBondDenom}, + sdk.DefaultBondDenom, func() { payload.DestinationPort = invalidPortID }, @@ -96,7 +90,7 @@ func (suite *TransferTestSuite) TestOnSendPacket() { }, { "transfer with slashes in base denom", - []string{"base/coin"}, + "base/coin", func() {}, types.ErrInvalidDenomForTransfer, }, @@ -106,38 +100,25 @@ func (suite *TransferTestSuite) TestOnSendPacket() { suite.Run(tc.name, func() { suite.SetupTest() // reset - originalBalances := sdk.NewCoins() - for _, denom := range tc.sourceDenomsToTransfer { - originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), denom) - originalBalances = originalBalances.Add(originalBalance) - } + originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), tc.sourceDenomToTransfer) amount, ok := sdkmath.NewIntFromString("9223372036854775808") // 2^63 (one above int64) suite.Require().True(ok) - originalCoins := sdk.NewCoins() - for _, denom := range tc.sourceDenomsToTransfer { - coinToSendToB := sdk.NewCoin(denom, amount) - originalCoins = originalCoins.Add(coinToSendToB) - } - - tokens := make([]types.Token, len(originalCoins)) + originalCoin := sdk.NewCoin(tc.sourceDenomToTransfer, amount) - for i, coin := range originalCoins { - var err error - tokens[i], err = suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(suite.chainA.GetContext(), coin) - suite.Require().NoError(err) - } + token, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(suite.chainA.GetContext(), originalCoin) + suite.Require().NoError(err) - transferData := types.NewFungibleTokenPacketDataV2( - tokens, + transferData := types.NewFungibleTokenPacketData( + token.Denom.Path(), + token.Amount, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), "", - types.ForwardingPacketData{}, ) bz := suite.chainA.Codec.MustMarshal(&transferData) payload = channeltypesv2.NewPayload( - types.PortID, types.PortID, types.V2, + types.PortID, types.PortID, types.V1, types.EncodingProtobuf, bz, ) @@ -147,7 +128,7 @@ func (suite *TransferTestSuite) TestOnSendPacket() { ctx := suite.chainA.GetContext() cbs := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.Router.Route(ibctesting.TransferPort) - err := cbs.OnSendPacket(ctx, suite.pathAToB.EndpointA.ClientID, suite.pathAToB.EndpointB.ClientID, 1, payload, suite.chainA.SenderAccount.GetAddress()) + err = cbs.OnSendPacket(ctx, suite.pathAToB.EndpointA.ClientID, suite.pathAToB.EndpointB.ClientID, 1, payload, suite.chainA.SenderAccount.GetAddress()) if tc.expError != nil { suite.Require().Contains(err.Error(), tc.expError.Error()) @@ -155,16 +136,13 @@ func (suite *TransferTestSuite) TestOnSendPacket() { suite.Require().NoError(err) escrowAddress := types.GetEscrowAddress(types.PortID, suite.pathAToB.EndpointA.ClientID) - for _, coin := range originalCoins { - // check that the balance for chainA is updated - chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), coin.Denom) - suite.Require().Equal(originalBalances.AmountOf(coin.Denom).Sub(amount).Int64(), chainABalance.Amount.Int64()) - - // check that module account escrow address has locked the tokens - chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, coin.Denom) - suite.Require().Equal(coin, chainAEscrowBalance) + // check that the balance for chainA is updated + chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), originalCoin.Denom) + suite.Require().Equal(originalBalance.Amount.Sub(amount).Int64(), chainABalance.Amount.Int64()) - } + // check that module account escrow address has locked the tokens + chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, originalCoin.Denom) + suite.Require().Equal(originalCoin, chainAEscrowBalance) } }) } @@ -173,26 +151,20 @@ func (suite *TransferTestSuite) TestOnSendPacket() { func (suite *TransferTestSuite) TestOnRecvPacket() { var payload channeltypesv2.Payload testCases := []struct { - name string - sourceDenomsToTransfer []string - malleate func() - expErr bool + name string + sourceDenomToTransfer string + malleate func() + expErr bool }{ { "transfer single denom", - []string{sdk.DefaultBondDenom}, - func() {}, - false, - }, - { - "transfer multiple denoms", - []string{sdk.DefaultBondDenom, ibctesting.SecondaryDenom}, + sdk.DefaultBondDenom, func() {}, false, }, { "transfer with invalid source port", - []string{sdk.DefaultBondDenom}, + sdk.DefaultBondDenom, func() { payload.SourcePort = invalidPortID }, @@ -200,7 +172,7 @@ func (suite *TransferTestSuite) TestOnRecvPacket() { }, { "transfer with invalid dest port", - []string{sdk.DefaultBondDenom}, + sdk.DefaultBondDenom, func() { payload.DestinationPort = invalidPortID }, @@ -212,40 +184,27 @@ func (suite *TransferTestSuite) TestOnRecvPacket() { suite.Run(tc.name, func() { suite.SetupTest() // reset - originalBalances := sdk.NewCoins() - for _, denom := range tc.sourceDenomsToTransfer { - originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), denom) - originalBalances = originalBalances.Add(originalBalance) - } + originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), tc.sourceDenomToTransfer) timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) amount, ok := sdkmath.NewIntFromString("9223372036854775808") // 2^63 (one above int64) suite.Require().True(ok) - originalCoins := sdk.NewCoins() - for _, denom := range tc.sourceDenomsToTransfer { - coinToSendToB := sdk.NewCoin(denom, amount) - originalCoins = originalCoins.Add(coinToSendToB) - } - - tokens := make([]types.Token, len(originalCoins)) + originalCoin := sdk.NewCoin(tc.sourceDenomToTransfer, amount) - for i, coin := range originalCoins { - var err error - tokens[i], err = suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(suite.chainA.GetContext(), coin) - suite.Require().NoError(err) - } + token, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(suite.chainA.GetContext(), originalCoin) + suite.Require().NoError(err) - transferData := types.NewFungibleTokenPacketDataV2( - tokens, + transferData := types.NewFungibleTokenPacketData( + token.Denom.Path(), + token.Amount, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), "", - types.ForwardingPacketData{}, ) bz := suite.chainA.Codec.MustMarshal(&transferData) payload = channeltypesv2.NewPayload( - types.PortID, types.PortID, types.V2, + types.PortID, types.PortID, types.V1, types.EncodingProtobuf, bz, ) msg := channeltypesv2.NewMsgSendPacket( @@ -255,7 +214,7 @@ func (suite *TransferTestSuite) TestOnRecvPacket() { payload, ) - _, err := suite.chainA.SendMsgs(msg) + _, err = suite.chainA.SendMsgs(msg) suite.Require().NoError(err) // message committed ctx := suite.chainB.GetContext() @@ -275,24 +234,21 @@ func (suite *TransferTestSuite) TestOnRecvPacket() { suite.Require().Equal(channeltypes.NewResultAcknowledgement([]byte{byte(1)}).Acknowledgement(), recvResult.Acknowledgement) escrowAddress := types.GetEscrowAddress(types.PortID, suite.pathAToB.EndpointA.ClientID) - for _, coin := range originalCoins { - // check that the balance for chainA is updated - chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), coin.Denom) - suite.Require().Equal(originalBalances.AmountOf(coin.Denom).Sub(amount).Int64(), chainABalance.Amount.Int64()) - - // check that module account escrow address has locked the tokens - chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, coin.Denom) - suite.Require().Equal(coin, chainAEscrowBalance) + // check that the balance for chainA is updated + chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), originalCoin.Denom) + suite.Require().Equal(originalBalance.Amount.Sub(amount).Int64(), chainABalance.Amount.Int64()) - traceAToB := types.NewHop(types.PortID, suite.pathAToB.EndpointB.ClientID) + // check that module account escrow address has locked the tokens + chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, originalCoin.Denom) + suite.Require().Equal(originalCoin, chainAEscrowBalance) - // check that voucher exists on chain B - chainBDenom := types.NewDenom(coin.Denom, traceAToB) - chainBBalance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), chainBDenom.IBCDenom()) - coinSentFromAToB := sdk.NewCoin(chainBDenom.IBCDenom(), amount) - suite.Require().Equal(coinSentFromAToB, chainBBalance) + traceAToB := types.NewHop(types.PortID, suite.pathAToB.EndpointB.ClientID) - } + // check that voucher exists on chain B + chainBDenom := types.NewDenom(originalCoin.Denom, traceAToB) + chainBBalance := suite.chainB.GetSimApp().BankKeeper.GetBalance(suite.chainB.GetContext(), suite.chainB.SenderAccount.GetAddress(), chainBDenom.IBCDenom()) + coinSentFromAToB := sdk.NewCoin(chainBDenom.IBCDenom(), amount) + suite.Require().Equal(coinSentFromAToB, chainBBalance) } else { suite.Require().Equal(channeltypesv2.PacketStatus_Failure, recvResult.Status) } @@ -302,16 +258,12 @@ func (suite *TransferTestSuite) TestOnRecvPacket() { func (suite *TransferTestSuite) TestOnAckPacket() { testCases := []struct { - name string - sourceDenomsToTransfer []string + name string + sourceDenomToTransfer string }{ { "transfer single denom", - []string{sdk.DefaultBondDenom}, - }, - { - "transfer multiple denoms", - []string{sdk.DefaultBondDenom, ibctesting.SecondaryDenom}, + sdk.DefaultBondDenom, }, } @@ -319,40 +271,27 @@ func (suite *TransferTestSuite) TestOnAckPacket() { suite.Run(tc.name, func() { suite.SetupTest() // reset - originalBalances := sdk.NewCoins() - for _, denom := range tc.sourceDenomsToTransfer { - originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), denom) - originalBalances = originalBalances.Add(originalBalance) - } + originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), tc.sourceDenomToTransfer) timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) amount, ok := sdkmath.NewIntFromString("9223372036854775808") // 2^63 (one above int64) suite.Require().True(ok) - originalCoins := sdk.NewCoins() - for _, denom := range tc.sourceDenomsToTransfer { - coinToSendToB := sdk.NewCoin(denom, amount) - originalCoins = originalCoins.Add(coinToSendToB) - } + originalCoin := sdk.NewCoin(tc.sourceDenomToTransfer, amount) - tokens := make([]types.Token, len(originalCoins)) - - for i, coin := range originalCoins { - var err error - tokens[i], err = suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(suite.chainA.GetContext(), coin) - suite.Require().NoError(err) - } + token, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(suite.chainA.GetContext(), originalCoin) + suite.Require().NoError(err) - transferData := types.NewFungibleTokenPacketDataV2( - tokens, + transferData := types.NewFungibleTokenPacketData( + token.Denom.Path(), + token.Amount, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), "", - types.ForwardingPacketData{}, ) bz := suite.chainA.Codec.MustMarshal(&transferData) payload := channeltypesv2.NewPayload( - types.PortID, types.PortID, types.V2, + types.PortID, types.PortID, types.V1, types.EncodingProtobuf, bz, ) msg := channeltypesv2.NewMsgSendPacket( @@ -362,7 +301,7 @@ func (suite *TransferTestSuite) TestOnAckPacket() { payload, ) - _, err := suite.chainA.SendMsgs(msg) + _, err = suite.chainA.SendMsgs(msg) suite.Require().NoError(err) // message committed ctx := suite.chainA.GetContext() @@ -378,15 +317,13 @@ func (suite *TransferTestSuite) TestOnAckPacket() { // on successful ack, the tokens sent in packets should still be in escrow escrowAddress := types.GetEscrowAddress(types.PortID, suite.pathAToB.EndpointA.ClientID) - for _, coin := range originalCoins { - // check that the balance for chainA is updated - chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), coin.Denom) - suite.Require().Equal(originalBalances.AmountOf(coin.Denom).Sub(amount).Int64(), chainABalance.Amount.Int64()) + // check that the balance for chainA is updated + chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), originalCoin.Denom) + suite.Require().Equal(originalBalance.Amount.Sub(amount).Int64(), chainABalance.Amount.Int64()) - // check that module account escrow address has locked the tokens - chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, coin.Denom) - suite.Require().Equal(coin, chainAEscrowBalance) - } + // check that module account escrow address has locked the tokens + chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, originalCoin.Denom) + suite.Require().Equal(originalCoin, chainAEscrowBalance) // create a custom error ack and replay the callback to ensure it fails with IBC v2 callbacks errAck := channeltypes.NewErrorAcknowledgement(types.ErrInvalidAmount) @@ -405,31 +342,25 @@ func (suite *TransferTestSuite) TestOnAckPacket() { suite.Require().NoError(err) // on error ack, the tokens sent in packets should be returned to sender - for _, coin := range originalCoins { - // check that the balance for chainA is refunded - chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), coin.Denom) - suite.Require().Equal(originalBalances.AmountOf(coin.Denom), chainABalance.Amount) - - // check that module account escrow address has no tokens - chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, coin.Denom) - suite.Require().Equal(sdk.NewCoin(coin.Denom, sdkmath.ZeroInt()), chainAEscrowBalance) - } + // check that the balance for chainA is refunded + chainABalance = suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), originalCoin.Denom) + suite.Require().Equal(originalBalance.Amount, chainABalance.Amount) + + // check that module account escrow address has no tokens + chainAEscrowBalance = suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, originalCoin.Denom) + suite.Require().Equal(sdk.NewCoin(originalCoin.Denom, sdkmath.ZeroInt()), chainAEscrowBalance) }) } } func (suite *TransferTestSuite) TestOnTimeoutPacket() { testCases := []struct { - name string - sourceDenomsToTransfer []string + name string + sourceDenomToTransfer string }{ { "transfer single denom", - []string{sdk.DefaultBondDenom}, - }, - { - "transfer multiple denoms", - []string{sdk.DefaultBondDenom, ibctesting.SecondaryDenom}, + sdk.DefaultBondDenom, }, } @@ -437,40 +368,27 @@ func (suite *TransferTestSuite) TestOnTimeoutPacket() { suite.Run(tc.name, func() { suite.SetupTest() // reset - originalBalances := sdk.NewCoins() - for _, denom := range tc.sourceDenomsToTransfer { - originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), denom) - originalBalances = originalBalances.Add(originalBalance) - } + originalBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), tc.sourceDenomToTransfer) timeoutTimestamp := uint64(suite.chainB.GetContext().BlockTime().Add(time.Hour).Unix()) amount, ok := sdkmath.NewIntFromString("9223372036854775808") // 2^63 (one above int64) suite.Require().True(ok) - originalCoins := sdk.NewCoins() - for _, denom := range tc.sourceDenomsToTransfer { - coinToSendToB := sdk.NewCoin(denom, amount) - originalCoins = originalCoins.Add(coinToSendToB) - } + originalCoin := sdk.NewCoin(tc.sourceDenomToTransfer, amount) - tokens := make([]types.Token, len(originalCoins)) - - for i, coin := range originalCoins { - var err error - tokens[i], err = suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(suite.chainA.GetContext(), coin) - suite.Require().NoError(err) - } + token, err := suite.chainA.GetSimApp().TransferKeeper.TokenFromCoin(suite.chainA.GetContext(), originalCoin) + suite.Require().NoError(err) - transferData := types.NewFungibleTokenPacketDataV2( - tokens, + transferData := types.NewFungibleTokenPacketData( + token.Denom.Path(), + token.Amount, suite.chainA.SenderAccount.GetAddress().String(), suite.chainB.SenderAccount.GetAddress().String(), "", - types.ForwardingPacketData{}, ) bz := suite.chainA.Codec.MustMarshal(&transferData) payload := channeltypesv2.NewPayload( - types.PortID, types.PortID, types.V2, + types.PortID, types.PortID, types.V1, types.EncodingProtobuf, bz, ) msg := channeltypesv2.NewMsgSendPacket( @@ -480,20 +398,18 @@ func (suite *TransferTestSuite) TestOnTimeoutPacket() { payload, ) - _, err := suite.chainA.SendMsgs(msg) + _, err = suite.chainA.SendMsgs(msg) suite.Require().NoError(err) // message committed // on successful send, the tokens sent in packets should be in escrow escrowAddress := types.GetEscrowAddress(types.PortID, suite.pathAToB.EndpointA.ClientID) - for _, coin := range originalCoins { - // check that the balance for chainA is updated - chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), coin.Denom) - suite.Require().Equal(originalBalances.AmountOf(coin.Denom).Sub(amount).Int64(), chainABalance.Amount.Int64()) + // check that the balance for chainA is updated + chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), originalCoin.Denom) + suite.Require().Equal(originalBalance.Amount.Sub(amount).Int64(), chainABalance.Amount.Int64()) - // check that module account escrow address has locked the tokens - chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, coin.Denom) - suite.Require().Equal(coin, chainAEscrowBalance) - } + // check that module account escrow address has locked the tokens + chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, originalCoin.Denom) + suite.Require().Equal(originalCoin, chainAEscrowBalance) ctx := suite.chainA.GetContext() cbs := suite.chainA.App.GetIBCKeeper().ChannelKeeperV2.Router.Route(ibctesting.TransferPort) @@ -505,15 +421,13 @@ func (suite *TransferTestSuite) TestOnTimeoutPacket() { suite.Require().NoError(err) // on timeout, the tokens sent in packets should be returned to sender - for _, coin := range originalCoins { - // check that the balance for chainA is refunded - chainABalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), coin.Denom) - suite.Require().Equal(originalBalances.AmountOf(coin.Denom), chainABalance.Amount) - - // check that module account escrow address has no tokens - chainAEscrowBalance := suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, coin.Denom) - suite.Require().Equal(sdk.NewCoin(coin.Denom, sdkmath.ZeroInt()), chainAEscrowBalance) - } + // check that the balance for chainA is refunded + chainABalance = suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), suite.chainA.SenderAccount.GetAddress(), originalCoin.Denom) + suite.Require().Equal(originalBalance.Amount, chainABalance.Amount) + + // check that module account escrow address has no tokens + chainAEscrowBalance = suite.chainA.GetSimApp().BankKeeper.GetBalance(suite.chainA.GetContext(), escrowAddress, originalCoin.Denom) + suite.Require().Equal(sdk.NewCoin(originalCoin.Denom, sdkmath.ZeroInt()), chainAEscrowBalance) }) } } diff --git a/proto/ibc/applications/transfer/v1/authz.proto b/proto/ibc/applications/transfer/v1/authz.proto index 9d0280888c0..3f53ebf91f8 100644 --- a/proto/ibc/applications/transfer/v1/authz.proto +++ b/proto/ibc/applications/transfer/v1/authz.proto @@ -23,15 +23,6 @@ message Allocation { // allow list of memo strings, an empty list prohibits all memo strings; // a list only with "*" permits any memo string repeated string allowed_packet_data = 5; - // Forwarding options that are allowed. - repeated AllowedForwarding allowed_forwarding = 6 [(gogoproto.nullable) = false]; -} - -// AllowedForwarding defines which options are allowed for forwarding. -message AllowedForwarding { - // a list of allowed source port ID/channel ID pairs through which the packet is allowed to be forwarded until final - // destination - repeated ibc.applications.transfer.v1.Hop hops = 1 [(gogoproto.nullable) = false]; } // TransferAuthorization allows the grantee to spend up to spend_limit coins from diff --git a/proto/ibc/applications/transfer/v1/transfer.proto b/proto/ibc/applications/transfer/v1/transfer.proto index 2c4ea710721..d391c7fba14 100644 --- a/proto/ibc/applications/transfer/v1/transfer.proto +++ b/proto/ibc/applications/transfer/v1/transfer.proto @@ -19,16 +19,6 @@ message Params { bool receive_enabled = 2; } -// Forwarding defines a list of port ID, channel ID pairs determining the path -// through which a packet must be forwarded, and an unwind boolean indicating if -// the coin should be unwinded to its native chain before forwarding. -message Forwarding { - // optional unwinding for the token transferred - bool unwind = 1; - // optional intermediate path through which packet will be forwarded - repeated Hop hops = 2 [(gogoproto.nullable) = false]; -} - // Hop defines a port ID, channel ID pair specifying where tokens must be forwarded // next in a multihop transfer. message Hop { diff --git a/proto/ibc/applications/transfer/v1/tx.proto b/proto/ibc/applications/transfer/v1/tx.proto index 6968968854b..537acbbedb7 100644 --- a/proto/ibc/applications/transfer/v1/tx.proto +++ b/proto/ibc/applications/transfer/v1/tx.proto @@ -35,8 +35,8 @@ message MsgTransfer { string source_port = 1; // the channel by which the packet will be sent string source_channel = 2; - // the token to be transferred. this field has been replaced by the tokens field. - cosmos.base.v1beta1.Coin token = 3 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true, deprecated = true]; + // token to be transferred + cosmos.base.v1beta1.Coin token = 3 [(gogoproto.nullable) = false, (amino.dont_omitempty) = true]; // the sender address string sender = 4; // the recipient address on the destination chain @@ -49,10 +49,6 @@ message MsgTransfer { uint64 timeout_timestamp = 7; // optional memo string memo = 8; - // tokens to be transferred - repeated cosmos.base.v1beta1.Coin tokens = 9 [(gogoproto.nullable) = false]; - // optional forwarding information - Forwarding forwarding = 10; } // MsgTransferResponse defines the Msg/Transfer response type. diff --git a/proto/ibc/applications/transfer/v2/genesis.proto b/proto/ibc/applications/transfer/v2/genesis.proto index 6b3545d2f39..c3fdee63c85 100644 --- a/proto/ibc/applications/transfer/v2/genesis.proto +++ b/proto/ibc/applications/transfer/v2/genesis.proto @@ -19,13 +19,4 @@ message GenesisState { // by the transfer module repeated cosmos.base.v1beta1.Coin total_escrowed = 4 [(gogoproto.castrepeated) = "github.com/cosmos/cosmos-sdk/types.Coins", (gogoproto.nullable) = false]; - // forwarded_packets contains the forwarded packets stored as part of the - // packet forwarding lifecycle - repeated ForwardedPacket forwarded_packets = 5 [(gogoproto.nullable) = false]; -} - -// ForwardedPacket defines the genesis type necessary to retrieve and store forwarded packets. -message ForwardedPacket { - ibc.core.channel.v1.PacketId forward_key = 1 [(gogoproto.nullable) = false]; - ibc.core.channel.v1.Packet packet = 2 [(gogoproto.nullable) = false]; } diff --git a/proto/ibc/applications/transfer/v2/packet.proto b/proto/ibc/applications/transfer/v2/packet.proto index 5b84afe9742..c27d7ec7ea7 100644 --- a/proto/ibc/applications/transfer/v2/packet.proto +++ b/proto/ibc/applications/transfer/v2/packet.proto @@ -29,23 +29,12 @@ message FungibleTokenPacketData { // https://github.com/cosmos/ibc/tree/master/spec/app/ics-020-fungible-token-transfer#data-structures message FungibleTokenPacketDataV2 { // the tokens to be transferred - repeated Token tokens = 1 [(gogoproto.nullable) = false]; + Token token = 1 [(gogoproto.nullable) = false]; // the sender address string sender = 2; // the recipient address on the destination chain string receiver = 3; // optional memo string memo = 4; - // optional forwarding information - ForwardingPacketData forwarding = 5 [(gogoproto.nullable) = false]; } -// ForwardingPacketData defines a list of port ID, channel ID pairs determining the path -// through which a packet must be forwarded, and the destination memo string to be used in the -// final destination of the tokens. -message ForwardingPacketData { - // optional memo consumed by final destination chain - string destination_memo = 1; - // optional intermediate path through which packet will be forwarded. - repeated ibc.applications.transfer.v1.Hop hops = 2 [(gogoproto.nullable) = false]; -} diff --git a/testing/path.go b/testing/path.go index 6aa159aae86..28c40b4e226 100644 --- a/testing/path.go +++ b/testing/path.go @@ -47,8 +47,8 @@ func NewTransferPath(chainA, chainB *TestChain) *Path { path := NewPath(chainA, chainB) path.EndpointA.ChannelConfig.PortID = TransferPort path.EndpointB.ChannelConfig.PortID = TransferPort - path.EndpointA.ChannelConfig.Version = transfertypes.V2 - path.EndpointB.ChannelConfig.Version = transfertypes.V2 + path.EndpointA.ChannelConfig.Version = transfertypes.V1 + path.EndpointB.ChannelConfig.Version = transfertypes.V1 return path } diff --git a/testing/solomachine.go b/testing/solomachine.go index f5af6866287..a5404fbcf4c 100644 --- a/testing/solomachine.go +++ b/testing/solomachine.go @@ -12,7 +12,6 @@ import ( "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types/multisig" - sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx/signing" transfertypes "github.com/cosmos/ibc-go/v9/modules/apps/transfer/types" @@ -301,7 +300,7 @@ func (solo *Solomachine) ConnOpenAck(chain *TestChain, clientID, connectionID st func (solo *Solomachine) ChanOpenInit(chain *TestChain, connectionID string) string { msgChanOpenInit := channeltypes.NewMsgChannelOpenInit( transfertypes.PortID, - transfertypes.V2, + transfertypes.V1, channeltypes.UNORDERED, []string{connectionID}, transfertypes.PortID, @@ -321,12 +320,12 @@ func (solo *Solomachine) ChanOpenInit(chain *TestChain, connectionID string) str // ChanOpenAck performs the channel open ack handshake step on the tendermint chain for the associated // solo machine client. func (solo *Solomachine) ChanOpenAck(chain *TestChain, channelID string) { - tryProof := solo.GenerateChanOpenTryProof(transfertypes.PortID, transfertypes.V2, channelID) + tryProof := solo.GenerateChanOpenTryProof(transfertypes.PortID, transfertypes.V1, channelID) msgChanOpenAck := channeltypes.NewMsgChannelOpenAck( transfertypes.PortID, channelID, channelIDSolomachine, - transfertypes.V2, + transfertypes.V1, tryProof, clienttypes.ZeroHeight(), chain.SenderAccount.GetAddress().String(), @@ -340,7 +339,7 @@ func (solo *Solomachine) ChanOpenAck(chain *TestChain, channelID string) { // ChanCloseConfirm performs the channel close confirm handshake step on the tendermint chain for the associated // solo machine client. func (solo *Solomachine) ChanCloseConfirm(chain *TestChain, portID, channelID string) { - initProof := solo.GenerateChanClosedProof(portID, transfertypes.V2, channelID) + initProof := solo.GenerateChanClosedProof(portID, transfertypes.V1, channelID) msgChanCloseConfirm := channeltypes.NewMsgChannelCloseConfirm( portID, channelID, @@ -361,13 +360,12 @@ func (solo *Solomachine) SendTransfer(chain *TestChain, portID, channelID string msgTransfer := transfertypes.NewMsgTransfer( portID, channelID, - sdk.NewCoins(TestCoin), + TestCoin, chain.SenderAccount.GetAddress().String(), chain.SenderAccount.GetAddress().String(), clienttypes.ZeroHeight(), uint64(chain.GetContext().BlockTime().Add(time.Hour).UnixNano()), "", - nil, ) for _, fn := range fns { @@ -432,7 +430,7 @@ func (solo *Solomachine) TimeoutPacket(chain *TestChain, packet channeltypes.Pac // TimeoutPacketOnClose creates a channel closed and unreceived packet proof and broadcasts a MsgTimeoutOnClose. func (solo *Solomachine) TimeoutPacketOnClose(chain *TestChain, packet channeltypes.Packet, channelID string) { - closedProof := solo.GenerateChanClosedProof(transfertypes.PortID, transfertypes.V2, channelID) + closedProof := solo.GenerateChanClosedProof(transfertypes.PortID, transfertypes.V1, channelID) unreceivedProof := solo.GenerateReceiptAbsenceProof(packet) msgTimeout := channeltypes.NewMsgTimeoutOnClose( packet, diff --git a/testing/values.go b/testing/values.go index 79c995b4974..736e547d913 100644 --- a/testing/values.go +++ b/testing/values.go @@ -74,8 +74,6 @@ var ( MockPacketData = mock.MockPacketData MockFailPacketData = mock.MockFailPacketData - EmptyForwardingPacketData = ibctransfertypes.ForwardingPacketData{} - prefix = commitmenttypes.NewMerklePrefix([]byte("ibc")) // unusedHash is a placeholder hash used for testing. unusedHash = tmhash.Sum([]byte{0x00})