diff --git a/modules/apps/27-interchain-accounts/controller/keeper/account.go b/modules/apps/27-interchain-accounts/controller/keeper/account.go index aacbe751c6b..143c3a6055e 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/account.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/account.go @@ -21,13 +21,20 @@ func (k Keeper) RegisterInterchainAccount(ctx sdk.Context, connectionID, owner s return err } - if k.portKeeper.IsBound(ctx, portID) { - return sdkerrors.Wrap(icatypes.ErrPortAlreadyBound, portID) + // if there is an active channel for this portID / connectionID return an error + activeChannelID, found := k.GetOpenActiveChannel(ctx, connectionID, portID) + if found { + return sdkerrors.Wrapf(icatypes.ErrActiveChannelAlreadySet, "existing active channel %s for portID %s on connection %s for owner %s", activeChannelID, portID, connectionID, owner) } - cap := k.BindPort(ctx, portID) - if err := k.ClaimCapability(ctx, cap, host.PortPath(portID)); err != nil { - return sdkerrors.Wrap(err, "unable to bind to newly generated portID") + switch { + case k.portKeeper.IsBound(ctx, portID) && !k.IsBound(ctx, portID): + return sdkerrors.Wrapf(icatypes.ErrPortAlreadyBound, "another module has claimed capability for and bound port with portID: %s", portID) + case !k.portKeeper.IsBound(ctx, portID): + cap := k.BindPort(ctx, portID) + if err := k.ClaimCapability(ctx, cap, host.PortPath(portID)); err != nil { + return sdkerrors.Wrapf(err, "unable to bind to newly generated portID: %s", portID) + } } connectionEnd, err := k.channelKeeper.GetConnection(ctx, connectionID) diff --git a/modules/apps/27-interchain-accounts/controller/keeper/account_test.go b/modules/apps/27-interchain-accounts/controller/keeper/account_test.go index 8086726bdc2..11334c332ea 100644 --- a/modules/apps/27-interchain-accounts/controller/keeper/account_test.go +++ b/modules/apps/27-interchain-accounts/controller/keeper/account_test.go @@ -3,6 +3,7 @@ package keeper_test import ( icatypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/types" channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types" + host "github.com/cosmos/ibc-go/v3/modules/core/24-host" ibctesting "github.com/cosmos/ibc-go/v3/testing" ) @@ -22,9 +23,11 @@ func (suite *KeeperTestSuite) TestRegisterInterchainAccount() { "success", func() {}, true, }, { - "port is already bound", + "port is already bound for owner but capability is claimed by another module", func() { - suite.chainA.GetSimApp().IBCKeeper.PortKeeper.BindPort(suite.chainA.GetContext(), TestPortID) + cap := suite.chainA.GetSimApp().IBCKeeper.PortKeeper.BindPort(suite.chainA.GetContext(), TestPortID) + err := suite.chainA.GetSimApp().TransferKeeper.ClaimCapability(suite.chainA.GetContext(), cap, host.PortPath(TestPortID)) + suite.Require().NoError(err) }, false, }, @@ -56,7 +59,6 @@ func (suite *KeeperTestSuite) TestRegisterInterchainAccount() { false, }, } - for _, tc := range testCases { tc := tc @@ -77,7 +79,6 @@ func (suite *KeeperTestSuite) TestRegisterInterchainAccount() { } else { suite.Require().Error(err) } - }) } } diff --git a/modules/apps/27-interchain-accounts/types/errors.go b/modules/apps/27-interchain-accounts/types/errors.go index 6ce9f2a9dea..7bb391dbe93 100644 --- a/modules/apps/27-interchain-accounts/types/errors.go +++ b/modules/apps/27-interchain-accounts/types/errors.go @@ -13,8 +13,8 @@ var ( ErrInvalidRoute = sdkerrors.Register(ModuleName, 7, "invalid route") ErrInterchainAccountNotFound = sdkerrors.Register(ModuleName, 8, "interchain account not found") ErrInterchainAccountAlreadySet = sdkerrors.Register(ModuleName, 9, "interchain account is already set") - ErrActiveChannelNotFound = sdkerrors.Register(ModuleName, 10, "no active channel for this owner") - ErrActiveChannelAlreadySet = sdkerrors.Register(ModuleName, 11, "active channel already set for this owner") + ErrActiveChannelAlreadySet = sdkerrors.Register(ModuleName, 10, "active channel already set for this owner") + ErrActiveChannelNotFound = sdkerrors.Register(ModuleName, 11, "no active channel for this owner") ErrInvalidVersion = sdkerrors.Register(ModuleName, 12, "invalid interchain accounts version") ErrInvalidAccountAddress = sdkerrors.Register(ModuleName, 13, "invalid account address") ErrUnsupported = sdkerrors.Register(ModuleName, 14, "interchain account does not support this action")