diff --git a/modules/apps/29-fee/ibc_middleware.go b/modules/apps/29-fee/ibc_middleware.go index a1a046f4727..d2040f42d1b 100644 --- a/modules/apps/29-fee/ibc_middleware.go +++ b/modules/apps/29-fee/ibc_middleware.go @@ -404,7 +404,17 @@ func (im IBCMiddleware) OnChanUpgradeAck(ctx sdk.Context, portID, channelID, cou // OnChanUpgradeOpen implements the IBCModule interface func (im IBCMiddleware) OnChanUpgradeOpen(ctx sdk.Context, portID, channelID string, order channeltypes.Order, connectionHops []string, version string) { - // call underlying app's OnChanUpgradeOpen callback. + // discard the version metadata returned as upgrade fields have already been validated in previous handshake steps. + _, err := types.MetadataFromVersion(version) + if err != nil { + // set fee disabled and passthrough to the next middleware or application in callstack. + im.keeper.DeleteFeeEnabled(ctx, portID, channelID) + im.app.OnChanUpgradeOpen(ctx, portID, channelID, order, connectionHops, version) + return + } + + // set fee enabled and passthrough to the next middleware of application in callstack. + im.keeper.SetFeeEnabled(ctx, portID, channelID) im.app.OnChanUpgradeOpen(ctx, portID, channelID, order, connectionHops, version) } diff --git a/modules/apps/29-fee/ibc_middleware_test.go b/modules/apps/29-fee/ibc_middleware_test.go index 842ffa78c77..9bb2649d170 100644 --- a/modules/apps/29-fee/ibc_middleware_test.go +++ b/modules/apps/29-fee/ibc_middleware_test.go @@ -1331,6 +1331,94 @@ func (suite *FeeTestSuite) TestOnChanUpgradeAck() { } } +func (suite *FeeTestSuite) TestOnChanUpgradeOpen() { + var path *ibctesting.Path + + testCases := []struct { + name string + malleate func() + expFeeEnabled bool + }{ + { + "success: enable fees", + func() {}, + true, + }, + { + "success: disable fees", + func() { + // create a new path using a fee enabled channel and downgrade it to disable fees + path = ibctesting.NewPath(suite.chainA, suite.chainB) + + mockFeeVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: ibcmock.Version})) + path.EndpointA.ChannelConfig.PortID = ibctesting.MockFeePort + path.EndpointB.ChannelConfig.PortID = ibctesting.MockFeePort + path.EndpointA.ChannelConfig.Version = mockFeeVersion + path.EndpointB.ChannelConfig.Version = mockFeeVersion + + upgradeVersion := ibcmock.Version + path.EndpointA.ChannelConfig.ProposedUpgrade.Fields.Version = upgradeVersion + path.EndpointB.ChannelConfig.ProposedUpgrade.Fields.Version = upgradeVersion + + suite.coordinator.Setup(path) + }, + false, + }, + } + + for _, tc := range testCases { + tc := tc + suite.Run(tc.name, func() { + suite.SetupTest() + + path = ibctesting.NewPath(suite.chainA, suite.chainB) + + // configure the initial path to create an unincentivized mock channel + path.EndpointA.ChannelConfig.PortID = ibctesting.MockFeePort + path.EndpointB.ChannelConfig.PortID = ibctesting.MockFeePort + path.EndpointA.ChannelConfig.Version = ibcmock.Version + path.EndpointB.ChannelConfig.Version = ibcmock.Version + + suite.coordinator.Setup(path) + + // configure the channel upgrade version to enabled ics29 fee middleware + upgradeVersion := string(types.ModuleCdc.MustMarshalJSON(&types.Metadata{FeeVersion: types.Version, AppVersion: ibcmock.Version})) + path.EndpointA.ChannelConfig.ProposedUpgrade.Fields.Version = upgradeVersion + path.EndpointB.ChannelConfig.ProposedUpgrade.Fields.Version = upgradeVersion + + tc.malleate() + + err := path.EndpointA.ChanUpgradeInit() + suite.Require().NoError(err) + + err = path.EndpointB.ChanUpgradeTry() + suite.Require().NoError(err) + + err = path.EndpointA.ChanUpgradeAck() + suite.Require().NoError(err) + + err = path.EndpointB.ChanUpgradeConfirm() + suite.Require().NoError(err) + + module, _, err := suite.chainA.App.GetIBCKeeper().PortKeeper.LookupModuleByPort(suite.chainA.GetContext(), ibctesting.MockFeePort) + suite.Require().NoError(err) + + cbs, ok := suite.chainA.App.GetIBCKeeper().Router.GetRoute(module) + suite.Require().True(ok) + + upgrade := path.EndpointA.GetChannelUpgrade() + cbs.OnChanUpgradeOpen(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID, upgrade.Fields.Ordering, upgrade.Fields.ConnectionHops, upgrade.Fields.Version) + + isFeeEnabled := suite.chainA.GetSimApp().IBCFeeKeeper.IsFeeEnabled(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) + if tc.expFeeEnabled { + suite.Require().True(isFeeEnabled) + } else { + suite.Require().False(isFeeEnabled) + } + }) + } +} + func (suite *FeeTestSuite) TestGetAppVersion() { var ( portID string