From 1562207a10b05321bcb733700ee5fd06ccf1b8e3 Mon Sep 17 00:00:00 2001 From: Sammy Date: Mon, 23 Sep 2024 16:18:06 -0400 Subject: [PATCH 01/11] create nexus Coin struct --- app/app.go | 2 +- x/nexus/types/coin.go | 196 ++++++++++ x/nexus/types/expected_keepers.go | 19 +- x/nexus/types/mock/expected_keepers.go | 493 +++++++++++++++++++++++++ x/nexus/types/types.go | 23 ++ 5 files changed, 731 insertions(+), 2 deletions(-) create mode 100644 x/nexus/types/coin.go diff --git a/app/app.go b/app/app.go index 1230681d4..d6d58cb6d 100644 --- a/app/app.go +++ b/app/app.go @@ -746,7 +746,7 @@ func InitModuleAccountPermissions() map[string][]string { axelarnetTypes.ModuleName: {authtypes.Minter, authtypes.Burner}, rewardTypes.ModuleName: {authtypes.Minter}, wasm.ModuleName: {authtypes.Burner}, - nexusTypes.ModuleName: nil, + nexusTypes.ModuleName: {authtypes.Minter, authtypes.Burner}, } } diff --git a/x/nexus/types/coin.go b/x/nexus/types/coin.go new file mode 100644 index 000000000..d60d4f560 --- /dev/null +++ b/x/nexus/types/coin.go @@ -0,0 +1,196 @@ +package types + +import ( + "fmt" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" + ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + + axelarnet "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" + "github.com/axelarnetwork/utils/funcs" +) + +// Coin provides functionality to lock and release coins +type Coin struct { + sdk.Coin + coinType CoinType + nexus Nexus + ibc IBCKeeper + bank BankKeeper +} + +// NewCoin creates a coin struct, assign a coin type and normalize the denom if it's a ICS20 token +func NewCoin(ctx sdk.Context, nexus Nexus, ibc IBCKeeper, bank BankKeeper, coin sdk.Coin) (Coin, error) { + coinType, err := getCoinType(ctx, nexus, coin.GetDenom()) + if err != nil { + return Coin{}, err + } + + // If coin type is ICS20, we need to normalize it to convert from 'ibc/{hash}' + // to native asset denom so that nexus could recognize it + if coinType == ICS20 { + denomTrace, err := ibc.ParseIBCDenom(ctx, coin.GetDenom()) + if err != nil { + return Coin{}, err + } + + coin = sdk.NewCoin(denomTrace.GetBaseDenom(), coin.Amount) + } + + c := Coin{ + Coin: coin, + coinType: coinType, + nexus: nexus, + ibc: ibc, + bank: bank, + } + if _, err := c.getOriginalCoin(ctx); err != nil { + return Coin{}, err + } + + return c, nil +} + +// GetOriginalCoin returns the original coin +func (c Coin) GetOriginalCoin(ctx sdk.Context) sdk.Coin { + // NOTE: must not fail since it's already checked in NewCoin + return funcs.Must(c.getOriginalCoin(ctx)) +} + +// Lock locks the given coin from the given address +func (c Coin) Lock(ctx sdk.Context, fromAddr sdk.AccAddress) error { + coin := c.GetOriginalCoin(ctx) + + switch c.coinType { + case ICS20, Native: + return lock(ctx, c.bank, fromAddr, coin) + case External: + return burn(ctx, c.bank, fromAddr, coin) + default: + return fmt.Errorf("unrecognized coin type %d", c.coinType) + } +} + +// Unlock unlocks the given coin to the given address +func (c Coin) Unlock(ctx sdk.Context, toAddr sdk.AccAddress) error { + coin := c.GetOriginalCoin(ctx) + + switch c.coinType { + case ICS20, Native: + return unlock(ctx, c.bank, toAddr, coin) + case External: + return mint(ctx, c.bank, toAddr, coin) + default: + return fmt.Errorf("unrecognized coin type %d", c.coinType) + } +} + +func (c Coin) getOriginalCoin(ctx sdk.Context) (sdk.Coin, error) { + switch c.coinType { + case ICS20: + return c.toICS20(ctx) + case Native, External: + return c.Coin, nil + default: + return sdk.Coin{}, fmt.Errorf("unrecognized coin type %d", c.coinType) + } +} + +func (c Coin) toICS20(ctx sdk.Context) (sdk.Coin, error) { + if c.coinType != ICS20 { + return sdk.Coin{}, fmt.Errorf("%s is not ICS20 token", c.GetDenom()) + } + + // check if the asset registered with a path + chain, ok := c.nexus.GetChainByNativeAsset(ctx, c.GetDenom()) + if !ok { + return sdk.Coin{}, fmt.Errorf("asset %s is not linked to a cosmos chain", c.GetDenom()) + } + + path, ok := c.ibc.GetIBCPath(ctx, chain.Name) + if !ok { + return sdk.Coin{}, fmt.Errorf("path not found for chain %s", chain.Name) + } + + trace := ibctypes.DenomTrace{ + Path: path, + BaseDenom: c.GetDenom(), + } + + return sdk.NewCoin(trace.IBCDenom(), c.Amount), nil +} + +func lock(ctx sdk.Context, bank BankKeeper, fromAddr sdk.AccAddress, coin sdk.Coin) error { + return bank.SendCoins(ctx, fromAddr, GetEscrowAddress(coin.GetDenom()), sdk.NewCoins(coin)) +} + +func unlock(ctx sdk.Context, bank BankKeeper, toAddr sdk.AccAddress, coin sdk.Coin) error { + return bank.SendCoins(ctx, GetEscrowAddress(coin.GetDenom()), toAddr, sdk.NewCoins(coin)) +} + +func burn(ctx sdk.Context, bank BankKeeper, fromAddr sdk.AccAddress, coin sdk.Coin) error { + coins := sdk.NewCoins(coin) + + if err := bank.SendCoinsFromAccountToModule(ctx, fromAddr, ModuleName, coins); err != nil { + return err + } + + // NOTE: should never fail since the coin is just transfered to the module + // account before the burn + funcs.MustNoErr(bank.BurnCoins(ctx, ModuleName, coins)) + + return nil +} + +func mint(ctx sdk.Context, bank BankKeeper, toAddr sdk.AccAddress, coin sdk.Coin) error { + coins := sdk.NewCoins(coin) + + if err := bank.MintCoins(ctx, ModuleName, coins); err != nil { + return err + } + + // NOTE: should never fail since the coin is just minted to the module + // account before the transfer + funcs.MustNoErr(bank.SendCoinsFromModuleToAccount(ctx, ModuleName, toAddr, coins)) + + return nil +} + +func getCoinType(ctx sdk.Context, nexus Nexus, denom string) (CoinType, error) { + switch { + // check if the format of token denomination is 'ibc/{hash}' + case isIBCDenom(denom): + return ICS20, nil + case isNativeAssetOnAxelarnet(ctx, nexus, denom): + return Native, nil + case nexus.IsAssetRegistered(ctx, axelarnet.Axelarnet, denom): + return External, nil + default: + return Unrecognized, fmt.Errorf("unrecognized coin %s", denom) + } +} + +// isIBCDenom validates that the given denomination is a valid ICS token representation (ibc/{hash}) +func isIBCDenom(denom string) bool { + if err := sdk.ValidateDenom(denom); err != nil { + return false + } + + denomSplit := strings.SplitN(denom, "/", 2) + if len(denomSplit) != 2 || denomSplit[0] != ibctypes.DenomPrefix { + return false + } + + if _, err := ibctypes.ParseHexHash(denomSplit[1]); err != nil { + return false + } + + return true +} + +func isNativeAssetOnAxelarnet(ctx sdk.Context, nexus Nexus, denom string) bool { + chain, ok := nexus.GetChainByNativeAsset(ctx, denom) + + return ok && chain.Name.Equals(axelarnet.Axelarnet.Name) +} diff --git a/x/nexus/types/expected_keepers.go b/x/nexus/types/expected_keepers.go index b29e3432f..34f623c58 100644 --- a/x/nexus/types/expected_keepers.go +++ b/x/nexus/types/expected_keepers.go @@ -6,6 +6,7 @@ import ( wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" sdk "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/tendermint/tendermint/libs/log" "github.com/axelarnetwork/axelar-core/utils" @@ -14,7 +15,7 @@ import ( snapshot "github.com/axelarnetwork/axelar-core/x/snapshot/exported" ) -//go:generate moq -out ./mock/expected_keepers.go -pkg mock . Nexus Snapshotter AxelarnetKeeper RewardKeeper SlashingKeeper WasmKeeper AccountKeeper StakingKeeper MsgIDGenerator +//go:generate moq -out ./mock/expected_keepers.go -pkg mock . Nexus Snapshotter AxelarnetKeeper RewardKeeper SlashingKeeper WasmKeeper AccountKeeper StakingKeeper MsgIDGenerator IBCKeeper BankKeeper // Nexus provides functionality to manage cross-chain transfers type Nexus interface { @@ -50,6 +51,7 @@ type Nexus interface { RouteMessage(ctx sdk.Context, id string, routingCtx ...exported.RoutingContext) error DequeueRouteMessage(ctx sdk.Context) (exported.GeneralMessage, bool) IsAssetRegistered(ctx sdk.Context, chain exported.Chain, denom string) bool + GetChainByNativeAsset(ctx sdk.Context, asset string) (chain exported.Chain, ok bool) } // MsgIDGenerator provides functionality to generate msg IDs @@ -96,3 +98,18 @@ type WasmKeeper interface { type AccountKeeper interface { GetModuleAddress(moduleName string) sdk.AccAddress } + +// IBCKeeper provides functionality to send IBC transfer +type IBCKeeper interface { + ParseIBCDenom(ctx sdk.Context, ibcDenom string) (ibctypes.DenomTrace, error) + GetIBCPath(ctx sdk.Context, chain exported.ChainName) (string, bool) +} + +// BankKeeper provides functionality to manage bank +type BankKeeper interface { + SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error + SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error + MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error +} diff --git a/x/nexus/types/mock/expected_keepers.go b/x/nexus/types/mock/expected_keepers.go index 16fed77aa..494771457 100644 --- a/x/nexus/types/mock/expected_keepers.go +++ b/x/nexus/types/mock/expected_keepers.go @@ -12,6 +12,7 @@ import ( snapshot "github.com/axelarnetwork/axelar-core/x/snapshot/exported" cosmossdktypes "github.com/cosmos/cosmos-sdk/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" + ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/tendermint/tendermint/libs/log" "sync" time "time" @@ -51,6 +52,9 @@ var _ nexustypes.Nexus = &NexusMock{} // GetChainFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) { // panic("mock out the GetChain method") // }, +// GetChainByNativeAssetFunc: func(ctx cosmossdktypes.Context, asset string) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) { +// panic("mock out the GetChainByNativeAsset method") +// }, // GetChainMaintainerStatesFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []github_com_axelarnetwork_axelar_core_x_nexus_exported.MaintainerState { // panic("mock out the GetChainMaintainerStates method") // }, @@ -145,6 +149,9 @@ type NexusMock struct { // GetChainFunc mocks the GetChain method. GetChainFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) + // GetChainByNativeAssetFunc mocks the GetChainByNativeAsset method. + GetChainByNativeAssetFunc func(ctx cosmossdktypes.Context, asset string) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) + // GetChainMaintainerStatesFunc mocks the GetChainMaintainerStates method. GetChainMaintainerStatesFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []github_com_axelarnetwork_axelar_core_x_nexus_exported.MaintainerState @@ -260,6 +267,13 @@ type NexusMock struct { // Chain is the chain argument value. Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName } + // GetChainByNativeAsset holds details about calls to the GetChainByNativeAsset method. + GetChainByNativeAsset []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Asset is the asset argument value. + Asset string + } // GetChainMaintainerStates holds details about calls to the GetChainMaintainerStates method. GetChainMaintainerStates []struct { // Ctx is the ctx argument value. @@ -430,6 +444,7 @@ type NexusMock struct { lockDequeueRouteMessage sync.RWMutex lockExportGenesis sync.RWMutex lockGetChain sync.RWMutex + lockGetChainByNativeAsset sync.RWMutex lockGetChainMaintainerStates sync.RWMutex lockGetChainMaintainers sync.RWMutex lockGetChains sync.RWMutex @@ -729,6 +744,42 @@ func (mock *NexusMock) GetChainCalls() []struct { return calls } +// GetChainByNativeAsset calls GetChainByNativeAssetFunc. +func (mock *NexusMock) GetChainByNativeAsset(ctx cosmossdktypes.Context, asset string) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) { + if mock.GetChainByNativeAssetFunc == nil { + panic("NexusMock.GetChainByNativeAssetFunc: method is nil but Nexus.GetChainByNativeAsset was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Asset string + }{ + Ctx: ctx, + Asset: asset, + } + mock.lockGetChainByNativeAsset.Lock() + mock.calls.GetChainByNativeAsset = append(mock.calls.GetChainByNativeAsset, callInfo) + mock.lockGetChainByNativeAsset.Unlock() + return mock.GetChainByNativeAssetFunc(ctx, asset) +} + +// GetChainByNativeAssetCalls gets all the calls that were made to GetChainByNativeAsset. +// Check the length with: +// +// len(mockedNexus.GetChainByNativeAssetCalls()) +func (mock *NexusMock) GetChainByNativeAssetCalls() []struct { + Ctx cosmossdktypes.Context + Asset string +} { + var calls []struct { + Ctx cosmossdktypes.Context + Asset string + } + mock.lockGetChainByNativeAsset.RLock() + calls = mock.calls.GetChainByNativeAsset + mock.lockGetChainByNativeAsset.RUnlock() + return calls +} + // GetChainMaintainerStates calls GetChainMaintainerStatesFunc. func (mock *NexusMock) GetChainMaintainerStates(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []github_com_axelarnetwork_axelar_core_x_nexus_exported.MaintainerState { if mock.GetChainMaintainerStatesFunc == nil { @@ -3038,3 +3089,445 @@ func (mock *MsgIDGeneratorMock) IncrIDCalls() []struct { mock.lockIncrID.RUnlock() return calls } + +// Ensure, that IBCKeeperMock does implement nexustypes.IBCKeeper. +// If this is not the case, regenerate this file with moq. +var _ nexustypes.IBCKeeper = &IBCKeeperMock{} + +// IBCKeeperMock is a mock implementation of nexustypes.IBCKeeper. +// +// func TestSomethingThatUsesIBCKeeper(t *testing.T) { +// +// // make and configure a mocked nexustypes.IBCKeeper +// mockedIBCKeeper := &IBCKeeperMock{ +// GetIBCPathFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (string, bool) { +// panic("mock out the GetIBCPath method") +// }, +// ParseIBCDenomFunc: func(ctx cosmossdktypes.Context, ibcDenom string) (ibctypes.DenomTrace, error) { +// panic("mock out the ParseIBCDenom method") +// }, +// } +// +// // use mockedIBCKeeper in code that requires nexustypes.IBCKeeper +// // and then make assertions. +// +// } +type IBCKeeperMock struct { + // GetIBCPathFunc mocks the GetIBCPath method. + GetIBCPathFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (string, bool) + + // ParseIBCDenomFunc mocks the ParseIBCDenom method. + ParseIBCDenomFunc func(ctx cosmossdktypes.Context, ibcDenom string) (ibctypes.DenomTrace, error) + + // calls tracks calls to the methods. + calls struct { + // GetIBCPath holds details about calls to the GetIBCPath method. + GetIBCPath []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + } + // ParseIBCDenom holds details about calls to the ParseIBCDenom method. + ParseIBCDenom []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // IbcDenom is the ibcDenom argument value. + IbcDenom string + } + } + lockGetIBCPath sync.RWMutex + lockParseIBCDenom sync.RWMutex +} + +// GetIBCPath calls GetIBCPathFunc. +func (mock *IBCKeeperMock) GetIBCPath(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (string, bool) { + if mock.GetIBCPathFunc == nil { + panic("IBCKeeperMock.GetIBCPathFunc: method is nil but IBCKeeper.GetIBCPath was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + }{ + Ctx: ctx, + Chain: chain, + } + mock.lockGetIBCPath.Lock() + mock.calls.GetIBCPath = append(mock.calls.GetIBCPath, callInfo) + mock.lockGetIBCPath.Unlock() + return mock.GetIBCPathFunc(ctx, chain) +} + +// GetIBCPathCalls gets all the calls that were made to GetIBCPath. +// Check the length with: +// +// len(mockedIBCKeeper.GetIBCPathCalls()) +func (mock *IBCKeeperMock) GetIBCPathCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + } + mock.lockGetIBCPath.RLock() + calls = mock.calls.GetIBCPath + mock.lockGetIBCPath.RUnlock() + return calls +} + +// ParseIBCDenom calls ParseIBCDenomFunc. +func (mock *IBCKeeperMock) ParseIBCDenom(ctx cosmossdktypes.Context, ibcDenom string) (ibctypes.DenomTrace, error) { + if mock.ParseIBCDenomFunc == nil { + panic("IBCKeeperMock.ParseIBCDenomFunc: method is nil but IBCKeeper.ParseIBCDenom was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + IbcDenom string + }{ + Ctx: ctx, + IbcDenom: ibcDenom, + } + mock.lockParseIBCDenom.Lock() + mock.calls.ParseIBCDenom = append(mock.calls.ParseIBCDenom, callInfo) + mock.lockParseIBCDenom.Unlock() + return mock.ParseIBCDenomFunc(ctx, ibcDenom) +} + +// ParseIBCDenomCalls gets all the calls that were made to ParseIBCDenom. +// Check the length with: +// +// len(mockedIBCKeeper.ParseIBCDenomCalls()) +func (mock *IBCKeeperMock) ParseIBCDenomCalls() []struct { + Ctx cosmossdktypes.Context + IbcDenom string +} { + var calls []struct { + Ctx cosmossdktypes.Context + IbcDenom string + } + mock.lockParseIBCDenom.RLock() + calls = mock.calls.ParseIBCDenom + mock.lockParseIBCDenom.RUnlock() + return calls +} + +// Ensure, that BankKeeperMock does implement nexustypes.BankKeeper. +// If this is not the case, regenerate this file with moq. +var _ nexustypes.BankKeeper = &BankKeeperMock{} + +// BankKeeperMock is a mock implementation of nexustypes.BankKeeper. +// +// func TestSomethingThatUsesBankKeeper(t *testing.T) { +// +// // make and configure a mocked nexustypes.BankKeeper +// mockedBankKeeper := &BankKeeperMock{ +// BurnCoinsFunc: func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error { +// panic("mock out the BurnCoins method") +// }, +// MintCoinsFunc: func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error { +// panic("mock out the MintCoins method") +// }, +// SendCoinsFunc: func(ctx cosmossdktypes.Context, fromAddr cosmossdktypes.AccAddress, toAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error { +// panic("mock out the SendCoins method") +// }, +// SendCoinsFromAccountToModuleFunc: func(ctx cosmossdktypes.Context, senderAddr cosmossdktypes.AccAddress, recipientModule string, amt cosmossdktypes.Coins) error { +// panic("mock out the SendCoinsFromAccountToModule method") +// }, +// SendCoinsFromModuleToAccountFunc: func(ctx cosmossdktypes.Context, senderModule string, recipientAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error { +// panic("mock out the SendCoinsFromModuleToAccount method") +// }, +// } +// +// // use mockedBankKeeper in code that requires nexustypes.BankKeeper +// // and then make assertions. +// +// } +type BankKeeperMock struct { + // BurnCoinsFunc mocks the BurnCoins method. + BurnCoinsFunc func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error + + // MintCoinsFunc mocks the MintCoins method. + MintCoinsFunc func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error + + // SendCoinsFunc mocks the SendCoins method. + SendCoinsFunc func(ctx cosmossdktypes.Context, fromAddr cosmossdktypes.AccAddress, toAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error + + // SendCoinsFromAccountToModuleFunc mocks the SendCoinsFromAccountToModule method. + SendCoinsFromAccountToModuleFunc func(ctx cosmossdktypes.Context, senderAddr cosmossdktypes.AccAddress, recipientModule string, amt cosmossdktypes.Coins) error + + // SendCoinsFromModuleToAccountFunc mocks the SendCoinsFromModuleToAccount method. + SendCoinsFromModuleToAccountFunc func(ctx cosmossdktypes.Context, senderModule string, recipientAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error + + // calls tracks calls to the methods. + calls struct { + // BurnCoins holds details about calls to the BurnCoins method. + BurnCoins []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // ModuleName is the moduleName argument value. + ModuleName string + // Amt is the amt argument value. + Amt cosmossdktypes.Coins + } + // MintCoins holds details about calls to the MintCoins method. + MintCoins []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // ModuleName is the moduleName argument value. + ModuleName string + // Amt is the amt argument value. + Amt cosmossdktypes.Coins + } + // SendCoins holds details about calls to the SendCoins method. + SendCoins []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // FromAddr is the fromAddr argument value. + FromAddr cosmossdktypes.AccAddress + // ToAddr is the toAddr argument value. + ToAddr cosmossdktypes.AccAddress + // Amt is the amt argument value. + Amt cosmossdktypes.Coins + } + // SendCoinsFromAccountToModule holds details about calls to the SendCoinsFromAccountToModule method. + SendCoinsFromAccountToModule []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // SenderAddr is the senderAddr argument value. + SenderAddr cosmossdktypes.AccAddress + // RecipientModule is the recipientModule argument value. + RecipientModule string + // Amt is the amt argument value. + Amt cosmossdktypes.Coins + } + // SendCoinsFromModuleToAccount holds details about calls to the SendCoinsFromModuleToAccount method. + SendCoinsFromModuleToAccount []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // SenderModule is the senderModule argument value. + SenderModule string + // RecipientAddr is the recipientAddr argument value. + RecipientAddr cosmossdktypes.AccAddress + // Amt is the amt argument value. + Amt cosmossdktypes.Coins + } + } + lockBurnCoins sync.RWMutex + lockMintCoins sync.RWMutex + lockSendCoins sync.RWMutex + lockSendCoinsFromAccountToModule sync.RWMutex + lockSendCoinsFromModuleToAccount sync.RWMutex +} + +// BurnCoins calls BurnCoinsFunc. +func (mock *BankKeeperMock) BurnCoins(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error { + if mock.BurnCoinsFunc == nil { + panic("BankKeeperMock.BurnCoinsFunc: method is nil but BankKeeper.BurnCoins was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + ModuleName string + Amt cosmossdktypes.Coins + }{ + Ctx: ctx, + ModuleName: moduleName, + Amt: amt, + } + mock.lockBurnCoins.Lock() + mock.calls.BurnCoins = append(mock.calls.BurnCoins, callInfo) + mock.lockBurnCoins.Unlock() + return mock.BurnCoinsFunc(ctx, moduleName, amt) +} + +// BurnCoinsCalls gets all the calls that were made to BurnCoins. +// Check the length with: +// +// len(mockedBankKeeper.BurnCoinsCalls()) +func (mock *BankKeeperMock) BurnCoinsCalls() []struct { + Ctx cosmossdktypes.Context + ModuleName string + Amt cosmossdktypes.Coins +} { + var calls []struct { + Ctx cosmossdktypes.Context + ModuleName string + Amt cosmossdktypes.Coins + } + mock.lockBurnCoins.RLock() + calls = mock.calls.BurnCoins + mock.lockBurnCoins.RUnlock() + return calls +} + +// MintCoins calls MintCoinsFunc. +func (mock *BankKeeperMock) MintCoins(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error { + if mock.MintCoinsFunc == nil { + panic("BankKeeperMock.MintCoinsFunc: method is nil but BankKeeper.MintCoins was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + ModuleName string + Amt cosmossdktypes.Coins + }{ + Ctx: ctx, + ModuleName: moduleName, + Amt: amt, + } + mock.lockMintCoins.Lock() + mock.calls.MintCoins = append(mock.calls.MintCoins, callInfo) + mock.lockMintCoins.Unlock() + return mock.MintCoinsFunc(ctx, moduleName, amt) +} + +// MintCoinsCalls gets all the calls that were made to MintCoins. +// Check the length with: +// +// len(mockedBankKeeper.MintCoinsCalls()) +func (mock *BankKeeperMock) MintCoinsCalls() []struct { + Ctx cosmossdktypes.Context + ModuleName string + Amt cosmossdktypes.Coins +} { + var calls []struct { + Ctx cosmossdktypes.Context + ModuleName string + Amt cosmossdktypes.Coins + } + mock.lockMintCoins.RLock() + calls = mock.calls.MintCoins + mock.lockMintCoins.RUnlock() + return calls +} + +// SendCoins calls SendCoinsFunc. +func (mock *BankKeeperMock) SendCoins(ctx cosmossdktypes.Context, fromAddr cosmossdktypes.AccAddress, toAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error { + if mock.SendCoinsFunc == nil { + panic("BankKeeperMock.SendCoinsFunc: method is nil but BankKeeper.SendCoins was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + FromAddr cosmossdktypes.AccAddress + ToAddr cosmossdktypes.AccAddress + Amt cosmossdktypes.Coins + }{ + Ctx: ctx, + FromAddr: fromAddr, + ToAddr: toAddr, + Amt: amt, + } + mock.lockSendCoins.Lock() + mock.calls.SendCoins = append(mock.calls.SendCoins, callInfo) + mock.lockSendCoins.Unlock() + return mock.SendCoinsFunc(ctx, fromAddr, toAddr, amt) +} + +// SendCoinsCalls gets all the calls that were made to SendCoins. +// Check the length with: +// +// len(mockedBankKeeper.SendCoinsCalls()) +func (mock *BankKeeperMock) SendCoinsCalls() []struct { + Ctx cosmossdktypes.Context + FromAddr cosmossdktypes.AccAddress + ToAddr cosmossdktypes.AccAddress + Amt cosmossdktypes.Coins +} { + var calls []struct { + Ctx cosmossdktypes.Context + FromAddr cosmossdktypes.AccAddress + ToAddr cosmossdktypes.AccAddress + Amt cosmossdktypes.Coins + } + mock.lockSendCoins.RLock() + calls = mock.calls.SendCoins + mock.lockSendCoins.RUnlock() + return calls +} + +// SendCoinsFromAccountToModule calls SendCoinsFromAccountToModuleFunc. +func (mock *BankKeeperMock) SendCoinsFromAccountToModule(ctx cosmossdktypes.Context, senderAddr cosmossdktypes.AccAddress, recipientModule string, amt cosmossdktypes.Coins) error { + if mock.SendCoinsFromAccountToModuleFunc == nil { + panic("BankKeeperMock.SendCoinsFromAccountToModuleFunc: method is nil but BankKeeper.SendCoinsFromAccountToModule was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + SenderAddr cosmossdktypes.AccAddress + RecipientModule string + Amt cosmossdktypes.Coins + }{ + Ctx: ctx, + SenderAddr: senderAddr, + RecipientModule: recipientModule, + Amt: amt, + } + mock.lockSendCoinsFromAccountToModule.Lock() + mock.calls.SendCoinsFromAccountToModule = append(mock.calls.SendCoinsFromAccountToModule, callInfo) + mock.lockSendCoinsFromAccountToModule.Unlock() + return mock.SendCoinsFromAccountToModuleFunc(ctx, senderAddr, recipientModule, amt) +} + +// SendCoinsFromAccountToModuleCalls gets all the calls that were made to SendCoinsFromAccountToModule. +// Check the length with: +// +// len(mockedBankKeeper.SendCoinsFromAccountToModuleCalls()) +func (mock *BankKeeperMock) SendCoinsFromAccountToModuleCalls() []struct { + Ctx cosmossdktypes.Context + SenderAddr cosmossdktypes.AccAddress + RecipientModule string + Amt cosmossdktypes.Coins +} { + var calls []struct { + Ctx cosmossdktypes.Context + SenderAddr cosmossdktypes.AccAddress + RecipientModule string + Amt cosmossdktypes.Coins + } + mock.lockSendCoinsFromAccountToModule.RLock() + calls = mock.calls.SendCoinsFromAccountToModule + mock.lockSendCoinsFromAccountToModule.RUnlock() + return calls +} + +// SendCoinsFromModuleToAccount calls SendCoinsFromModuleToAccountFunc. +func (mock *BankKeeperMock) SendCoinsFromModuleToAccount(ctx cosmossdktypes.Context, senderModule string, recipientAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error { + if mock.SendCoinsFromModuleToAccountFunc == nil { + panic("BankKeeperMock.SendCoinsFromModuleToAccountFunc: method is nil but BankKeeper.SendCoinsFromModuleToAccount was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientAddr cosmossdktypes.AccAddress + Amt cosmossdktypes.Coins + }{ + Ctx: ctx, + SenderModule: senderModule, + RecipientAddr: recipientAddr, + Amt: amt, + } + mock.lockSendCoinsFromModuleToAccount.Lock() + mock.calls.SendCoinsFromModuleToAccount = append(mock.calls.SendCoinsFromModuleToAccount, callInfo) + mock.lockSendCoinsFromModuleToAccount.Unlock() + return mock.SendCoinsFromModuleToAccountFunc(ctx, senderModule, recipientAddr, amt) +} + +// SendCoinsFromModuleToAccountCalls gets all the calls that were made to SendCoinsFromModuleToAccount. +// Check the length with: +// +// len(mockedBankKeeper.SendCoinsFromModuleToAccountCalls()) +func (mock *BankKeeperMock) SendCoinsFromModuleToAccountCalls() []struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientAddr cosmossdktypes.AccAddress + Amt cosmossdktypes.Coins +} { + var calls []struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientAddr cosmossdktypes.AccAddress + Amt cosmossdktypes.Coins + } + mock.lockSendCoinsFromModuleToAccount.RLock() + calls = mock.calls.SendCoinsFromModuleToAccount + mock.lockSendCoinsFromModuleToAccount.RUnlock() + return calls +} diff --git a/x/nexus/types/types.go b/x/nexus/types/types.go index 108571608..60d4ec6d3 100644 --- a/x/nexus/types/types.go +++ b/x/nexus/types/types.go @@ -1,9 +1,11 @@ package types import ( + "crypto/sha256" "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/axelarnetwork/axelar-core/utils" @@ -188,3 +190,24 @@ func NewTransferEpoch(chain exported.ChainName, asset string, epoch uint64, dire Direction: direction, } } + +// CoinType on can be ICS20 token, native asset, or wrapped asset from external chains +type CoinType int + +const ( + // Unrecognized means coin type is unrecognized + Unrecognized = iota + // Native means native token on Axelarnet + Native = 1 + // ICS20 means coin from IBC chains + ICS20 = 2 + // External means from external chains, such as EVM chains + External = 3 +) + +// GetEscrowAddress creates an address for the given denomination +func GetEscrowAddress(denom string) sdk.AccAddress { + hash := sha256.Sum256([]byte(denom)) + + return hash[:address.Len] +} From 501f5c3a6eacf28b2456833c124db4d4e9e9b4bc Mon Sep 17 00:00:00 2001 From: Sammy Date: Mon, 23 Sep 2024 18:29:34 -0400 Subject: [PATCH 02/11] pick up the new nexus Coin and remove axelarnet Coin --- app/app.go | 3 - x/axelarnet/handler.go | 4 +- x/axelarnet/keeper/coin.go | 185 ---- x/axelarnet/keeper/coin_test.go | 274 +++-- x/axelarnet/keeper/message_route.go | 13 +- x/axelarnet/keeper/msg_server.go | 111 +- x/axelarnet/message_handler.go | 23 +- x/axelarnet/module.go | 34 +- x/axelarnet/types/expected_keepers.go | 50 +- x/axelarnet/types/mock/expected_keepers.go | 1118 ++++++++++++++++++-- 10 files changed, 1299 insertions(+), 516 deletions(-) delete mode 100644 x/axelarnet/keeper/coin.go diff --git a/app/app.go b/app/app.go index d6d58cb6d..345a43817 100644 --- a/app/app.go +++ b/app/app.go @@ -310,7 +310,6 @@ func NewAxelarApp( *GetKeeper[axelarnetKeeper.IBCKeeper](keepers), GetKeeper[nexusKeeper.Keeper](keepers), axelarbankkeeper.NewBankKeeper(GetKeeper[bankkeeper.BaseKeeper](keepers)), - GetKeeper[authkeeper.AccountKeeper](keepers), logger, ), ) @@ -446,12 +445,10 @@ func initMessageRouter(keepers *KeeperCache) nexusTypes.MessageRouter { messageRouter := nexusTypes.NewMessageRouter(). AddRoute(evmTypes.ModuleName, evmKeeper.NewMessageRoute()). AddRoute(axelarnetTypes.ModuleName, axelarnetKeeper.NewMessageRoute( - *GetKeeper[axelarnetKeeper.Keeper](keepers), GetKeeper[axelarnetKeeper.IBCKeeper](keepers), GetKeeper[feegrantkeeper.Keeper](keepers), axelarbankkeeper.NewBankKeeper(GetKeeper[bankkeeper.BaseKeeper](keepers)), GetKeeper[nexusKeeper.Keeper](keepers), - GetKeeper[authkeeper.AccountKeeper](keepers), GetKeeper[stakingkeeper.Keeper](keepers), )) diff --git a/x/axelarnet/handler.go b/x/axelarnet/handler.go index 2f9703862..16cc0f5cb 100644 --- a/x/axelarnet/handler.go +++ b/x/axelarnet/handler.go @@ -20,8 +20,8 @@ import ( ) // NewHandler returns the handler of the Cosmos module -func NewHandler(k keeper.Keeper, n types.Nexus, b types.BankKeeper, a types.AccountKeeper, ibcK keeper.IBCKeeper) sdk.Handler { - server := keeper.NewMsgServerImpl(k, n, b, a, ibcK) +func NewHandler(k keeper.Keeper, n types.Nexus, b types.BankKeeper, ibcK keeper.IBCKeeper) sdk.Handler { + server := keeper.NewMsgServerImpl(k, n, b, ibcK) h := func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { diff --git a/x/axelarnet/keeper/coin.go b/x/axelarnet/keeper/coin.go deleted file mode 100644 index 3c163cadf..000000000 --- a/x/axelarnet/keeper/coin.go +++ /dev/null @@ -1,185 +0,0 @@ -package keeper - -import ( - "fmt" - "strings" - - sdk "github.com/cosmos/cosmos-sdk/types" - ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" - - "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" - "github.com/axelarnetwork/axelar-core/x/axelarnet/types" - "github.com/axelarnetwork/utils/funcs" -) - -// Coin provides functionality to lock and release coins -type Coin struct { - sdk.Coin - ctx sdk.Context - ibcK IBCKeeper - nexusK types.Nexus - coinType types.CoinType -} - -// NewCoin creates a coin struct, assign a coin type and normalize the denom if it's a ICS20 token -func NewCoin(ctx sdk.Context, ibcK IBCKeeper, nexusK types.Nexus, c sdk.Coin) (Coin, error) { - ct, err := getCoinType(ctx, nexusK, c.Denom) - if err != nil { - return Coin{}, err - } - - c2 := Coin{ - Coin: c, - ctx: ctx, - ibcK: ibcK, - nexusK: nexusK, - coinType: ct, - } - err = c2.normalizeDenom() - - return c2, err -} - -// Lock locks coin from deposit address to escrow address -func (c Coin) Lock(bankK types.BankKeeper, depositAddr sdk.AccAddress) error { - switch c.coinType { - case types.ICS20: - // convert to IBC denom - ics20, err := c.toICS20() - if err != nil { - return err - } - - if bankK.SpendableBalance(c.ctx, depositAddr, ics20.GetDenom()).IsLT(ics20) { - return fmt.Errorf("coin %s to lock is greater than account balance", ics20) - } - - // lock tokens in escrow address - escrowAddress := types.GetEscrowAddress(ics20.GetDenom()) - if err := bankK.SendCoins( - c.ctx, depositAddr, escrowAddress, sdk.NewCoins(ics20), - ); err != nil { - return err - } - case types.Native: - // lock tokens in escrow address - escrowAddress := types.GetEscrowAddress(c.GetDenom()) - if err := bankK.SendCoins( - c.ctx, depositAddr, escrowAddress, sdk.NewCoins(c.Coin), - ); err != nil { - return err - } - case types.External: - // transfer coins from linked address to module account and burn them - if err := bankK.SendCoinsFromAccountToModule( - c.ctx, depositAddr, types.ModuleName, sdk.NewCoins(c.Coin), - ); err != nil { - return err - } - - // NOTE: should not happen as the module account was - // retrieved on the step above, and it has enough balance - // to burn. - funcs.MustNoErr(bankK.BurnCoins(c.ctx, types.ModuleName, sdk.NewCoins(c.Coin))) - default: - return fmt.Errorf("unrecognized coin type %d", c.coinType) - } - - return nil -} - -// GetOriginalDenom returns the coin's original denom -func (c Coin) GetOriginalDenom() (string, error) { - if c.coinType != types.ICS20 { - return c.GetDenom(), nil - } - - // convert back to IBC denom 'ibc/{hash}' - coin, err := c.toICS20() - if err != nil { - return "", err - } - - return coin.GetDenom(), err -} - -// normalizeDenom converts from 'ibc/{hash}' to native asset that recognized by nexus module, -// returns error if trace is not found in IBC transfer store -func (c *Coin) normalizeDenom() error { - if !isIBCDenom(c.GetDenom()) || c.coinType != types.ICS20 { - return nil - } - - // get base denomination and tracing path - denomTrace, err := c.ibcK.ParseIBCDenom(c.ctx, c.Denom) - if err != nil { - return err - } - - // convert denomination from 'ibc/{hash}' to native asset that recognized by nexus module - c.Coin = sdk.NewCoin(denomTrace.GetBaseDenom(), c.Amount) - - return nil -} - -// toICS20 creates an ICS20 token from base denom, returns error if the asset is not registered on Axelarnet -func (c Coin) toICS20() (sdk.Coin, error) { - if c.coinType != types.ICS20 { - return sdk.Coin{}, fmt.Errorf("%s is not ICS20 token", c.GetDenom()) - } - - // check if the asset registered with a path - chain, ok := c.nexusK.GetChainByNativeAsset(c.ctx, c.GetDenom()) - if !ok { - return sdk.Coin{}, fmt.Errorf("asset %s is not linked to a cosmos chain", c.GetDenom()) - } - - path, ok := c.ibcK.GetIBCPath(c.ctx, chain.Name) - if !ok { - return sdk.Coin{}, fmt.Errorf("path not found for chain %s", chain.Name) - } - - trace := ibctypes.DenomTrace{ - Path: path, - BaseDenom: c.GetDenom(), - } - - return sdk.NewCoin(trace.IBCDenom(), c.Amount), nil -} - -func getCoinType(ctx sdk.Context, nexusK types.Nexus, denom string) (types.CoinType, error) { - switch { - // check if the format of token denomination is 'ibc/{hash}' - case isIBCDenom(denom): - return types.ICS20, nil - case isNativeAssetOnAxelarnet(ctx, nexusK, denom): - return types.Native, nil - case nexusK.IsAssetRegistered(ctx, exported.Axelarnet, denom): - return types.External, nil - default: - return types.Unrecognized, fmt.Errorf("unrecognized coin %s", denom) - } -} - -// isIBCDenom validates that the given denomination is a valid ICS token representation (ibc/{hash}) -func isIBCDenom(denom string) bool { - if err := sdk.ValidateDenom(denom); err != nil { - return false - } - - denomSplit := strings.SplitN(denom, "/", 2) - if len(denomSplit) != 2 || denomSplit[0] != ibctypes.DenomPrefix { - return false - } - - if _, err := ibctypes.ParseHexHash(denomSplit[1]); err != nil { - return false - } - - return true -} - -func isNativeAssetOnAxelarnet(ctx sdk.Context, n types.Nexus, denom string) bool { - chain, ok := n.GetChainByNativeAsset(ctx, denom) - return ok && chain.Name.Equals(exported.Axelarnet.Name) -} diff --git a/x/axelarnet/keeper/coin_test.go b/x/axelarnet/keeper/coin_test.go index abfa8fc24..f407035b3 100644 --- a/x/axelarnet/keeper/coin_test.go +++ b/x/axelarnet/keeper/coin_test.go @@ -1,149 +1,147 @@ package keeper_test -import ( - "testing" +// import ( +// "testing" +// sdk "github.com/cosmos/cosmos-sdk/types" +// ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" +// "github.com/stretchr/testify/assert" +// tmbytes "github.com/tendermint/tendermint/libs/bytes" +// "github.com/axelarnetwork/axelar-core/testutils/rand" +// "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" +// "github.com/axelarnetwork/axelar-core/x/axelarnet/keeper" +// "github.com/axelarnetwork/axelar-core/x/axelarnet/types" +// "github.com/axelarnetwork/axelar-core/x/axelarnet/types/mock" +// "github.com/axelarnetwork/axelar-core/x/axelarnet/types/testutils" +// nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" +// nexustestutils "github.com/axelarnetwork/axelar-core/x/nexus/exported/testutils" +// "github.com/axelarnetwork/utils/funcs" +// . "github.com/axelarnetwork/utils/test" +// ) - sdk "github.com/cosmos/cosmos-sdk/types" - ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" - "github.com/stretchr/testify/assert" - tmbytes "github.com/tendermint/tendermint/libs/bytes" +// func TestCoin(t *testing.T) { +// var ( +// ctx sdk.Context +// nexusK *mock.NexusMock +// bankK *mock.BankKeeperMock +// transferK *mock.IBCTransferKeeperMock +// ibcK keeper.IBCKeeper +// chain nexus.Chain +// coin keeper.Coin +// trace ibctypes.DenomTrace +// ) - "github.com/axelarnetwork/axelar-core/testutils/rand" - "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" - "github.com/axelarnetwork/axelar-core/x/axelarnet/keeper" - "github.com/axelarnetwork/axelar-core/x/axelarnet/types" - "github.com/axelarnetwork/axelar-core/x/axelarnet/types/mock" - "github.com/axelarnetwork/axelar-core/x/axelarnet/types/testutils" - nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" - nexustestutils "github.com/axelarnetwork/axelar-core/x/nexus/exported/testutils" - "github.com/axelarnetwork/utils/funcs" - . "github.com/axelarnetwork/utils/test" -) +// givenAKeeper := Given("a keeper", func() { +// ctx2, k, _, _ := setup() +// ctx = ctx2 +// nexusK = &mock.NexusMock{} +// bankK = &mock.BankKeeperMock{} +// transferK = &mock.IBCTransferKeeperMock{} +// ibcK = keeper.NewIBCKeeper(k, transferK) +// bankK.SendCoinsFromAccountToModuleFunc = func(sdk.Context, sdk.AccAddress, string, sdk.Coins) error { +// return nil +// } +// bankK.BurnCoinsFunc = func(sdk.Context, string, sdk.Coins) error { +// return nil +// } +// bankK.SendCoinsFunc = func(sdk.Context, sdk.AccAddress, sdk.AccAddress, sdk.Coins) error { +// return nil +// } +// bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { +// return coin.Coin +// } +// }) -func TestCoin(t *testing.T) { - var ( - ctx sdk.Context - nexusK *mock.NexusMock - bankK *mock.BankKeeperMock - transferK *mock.IBCTransferKeeperMock - ibcK keeper.IBCKeeper - chain nexus.Chain - coin keeper.Coin - trace ibctypes.DenomTrace - ) +// whenCoinIsNative := When("coin is native", func() { +// nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { +// return exported.Axelarnet, true +// } +// coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(exported.NativeAsset, sdk.NewInt(rand.PosI64())))) +// }) - givenAKeeper := Given("a keeper", func() { - ctx2, k, _, _ := setup() - ctx = ctx2 - nexusK = &mock.NexusMock{} - bankK = &mock.BankKeeperMock{} - transferK = &mock.IBCTransferKeeperMock{} - ibcK = keeper.NewIBCKeeper(k, transferK) - bankK.SendCoinsFromAccountToModuleFunc = func(sdk.Context, sdk.AccAddress, string, sdk.Coins) error { - return nil - } - bankK.BurnCoinsFunc = func(sdk.Context, string, sdk.Coins) error { - return nil - } - bankK.SendCoinsFunc = func(sdk.Context, sdk.AccAddress, sdk.AccAddress, sdk.Coins) error { - return nil - } - bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { - return coin.Coin - } - }) +// whenCoinIsExternal := When("coin is external", func() { +// nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { +// return nexustestutils.RandomChain(), true +// } +// nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { +// return true +// } +// coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(rand.Denom(5, 10), sdk.NewInt(rand.PosI64())))) +// }) - whenCoinIsNative := When("coin is native", func() { - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return exported.Axelarnet, true - } - coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(exported.NativeAsset, sdk.NewInt(rand.PosI64())))) - }) +// whenCoinIsICS20 := When("coin is from ICS20", func() { +// // setup +// path := testutils.RandomIBCPath() +// chain = nexustestutils.RandomChain() +// trace = ibctypes.DenomTrace{ +// Path: path, +// BaseDenom: rand.Denom(5, 10), +// } +// transferK.GetDenomTraceFunc = func(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (ibctypes.DenomTrace, bool) { +// return trace, true +// } - whenCoinIsExternal := When("coin is external", func() { - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return nexustestutils.RandomChain(), true - } - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { - return true - } - coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(rand.Denom(5, 10), sdk.NewInt(rand.PosI64())))) - }) +// funcs.MustNoErr(ibcK.SetCosmosChain(ctx, types.CosmosChain{ +// Name: chain.Name, +// AddrPrefix: rand.StrBetween(1, 10), +// IBCPath: path, +// })) - whenCoinIsICS20 := When("coin is from ICS20", func() { - // setup - path := testutils.RandomIBCPath() - chain = nexustestutils.RandomChain() - trace = ibctypes.DenomTrace{ - Path: path, - BaseDenom: rand.Denom(5, 10), - } - transferK.GetDenomTraceFunc = func(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (ibctypes.DenomTrace, bool) { - return trace, true - } +// coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(trace.IBCDenom(), sdk.NewInt(rand.PosI64())))) - funcs.MustNoErr(ibcK.SetCosmosChain(ctx, types.CosmosChain{ - Name: chain.Name, - AddrPrefix: rand.StrBetween(1, 10), - IBCPath: path, - })) +// nexusK.GetChainFunc = func(sdk.Context, nexus.ChainName) (nexus.Chain, bool) { +// return chain, true +// } +// nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { +// return chain, true +// } +// }) - coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(trace.IBCDenom(), sdk.NewInt(rand.PosI64())))) - - nexusK.GetChainFunc = func(sdk.Context, nexus.ChainName) (nexus.Chain, bool) { - return chain, true - } - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return chain, true - } - }) - - givenAKeeper. - Branch( - whenCoinIsNative. - Then("should Lock native coin in escrow account", func(t *testing.T) { - err := coin.Lock(bankK, rand.AccAddr()) - assert.NoError(t, err) - assert.Len(t, bankK.SendCoinsCalls(), 1) - }), - whenCoinIsExternal. - Then("should burn external token", func(t *testing.T) { - err := coin.Lock(bankK, rand.AccAddr()) - assert.NoError(t, err) - assert.Len(t, bankK.SendCoinsFromAccountToModuleCalls(), 1) - assert.Len(t, bankK.BurnCoinsCalls(), 1) - }), - whenCoinIsICS20. - When("coin is greater than bank balance", func() { - bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { - return sdk.NewCoin(trace.IBCDenom(), coin.Amount.Sub(sdk.OneInt())) - } - }). - Then("should return error", func(t *testing.T) { - err := coin.Lock(bankK, rand.AccAddr()) - assert.ErrorContains(t, err, "is greater than account balance") - }), - whenCoinIsICS20. - When("coin equals to bank balance", func() { - bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { - return sdk.NewCoin(trace.IBCDenom(), coin.Amount) - } - }). - Then("should Lock ICS20 coin in escrow account", func(t *testing.T) { - err := coin.Lock(bankK, rand.AccAddr()) - assert.NoError(t, err) - assert.Len(t, bankK.SendCoinsCalls(), 1) - }), - whenCoinIsICS20. - When("coin is less than bank balance", func() { - bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { - return sdk.NewCoin(trace.IBCDenom(), coin.Amount.Add(sdk.OneInt())) - } - }). - Then("should Lock ICS20 coin in escrow account", func(t *testing.T) { - err := coin.Lock(bankK, rand.AccAddr()) - assert.NoError(t, err) - assert.Len(t, bankK.SendCoinsCalls(), 1) - }), - ).Run(t) -} +// givenAKeeper. +// Branch( +// whenCoinIsNative. +// Then("should Lock native coin in escrow account", func(t *testing.T) { +// err := coin.Lock(bankK, rand.AccAddr()) +// assert.NoError(t, err) +// assert.Len(t, bankK.SendCoinsCalls(), 1) +// }), +// whenCoinIsExternal. +// Then("should burn external token", func(t *testing.T) { +// err := coin.Lock(bankK, rand.AccAddr()) +// assert.NoError(t, err) +// assert.Len(t, bankK.SendCoinsFromAccountToModuleCalls(), 1) +// assert.Len(t, bankK.BurnCoinsCalls(), 1) +// }), +// whenCoinIsICS20. +// When("coin is greater than bank balance", func() { +// bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { +// return sdk.NewCoin(trace.IBCDenom(), coin.Amount.Sub(sdk.OneInt())) +// } +// }). +// Then("should return error", func(t *testing.T) { +// err := coin.Lock(bankK, rand.AccAddr()) +// assert.ErrorContains(t, err, "is greater than account balance") +// }), +// whenCoinIsICS20. +// When("coin equals to bank balance", func() { +// bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { +// return sdk.NewCoin(trace.IBCDenom(), coin.Amount) +// } +// }). +// Then("should Lock ICS20 coin in escrow account", func(t *testing.T) { +// err := coin.Lock(bankK, rand.AccAddr()) +// assert.NoError(t, err) +// assert.Len(t, bankK.SendCoinsCalls(), 1) +// }), +// whenCoinIsICS20. +// When("coin is less than bank balance", func() { +// bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { +// return sdk.NewCoin(trace.IBCDenom(), coin.Amount.Add(sdk.OneInt())) +// } +// }). +// Then("should Lock ICS20 coin in escrow account", func(t *testing.T) { +// err := coin.Lock(bankK, rand.AccAddr()) +// assert.NoError(t, err) +// assert.Len(t, bankK.SendCoinsCalls(), 1) +// }), +// ).Run(t) +// } diff --git a/x/axelarnet/keeper/message_route.go b/x/axelarnet/keeper/message_route.go index 8018cb18f..fc496ad73 100644 --- a/x/axelarnet/keeper/message_route.go +++ b/x/axelarnet/keeper/message_route.go @@ -9,6 +9,7 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/types" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" ) // for IBC execution @@ -16,12 +17,10 @@ const gasCost = storetypes.Gas(1000000) // NewMessageRoute creates a new message route func NewMessageRoute( - keeper Keeper, ibcK types.IBCKeeper, feegrantK types.FeegrantKeeper, bankK types.BankKeeper, nexusK types.Nexus, - accountK types.AccountKeeper, stakingK types.StakingKeeper, ) nexus.MessageRoute { return func(ctx sdk.Context, routingCtx nexus.RoutingContext, msg nexus.GeneralMessage) error { @@ -34,7 +33,7 @@ func NewMessageRoute( return sdkerrors.Wrap(err, "invalid payload") } - asset, err := escrowAssetToMessageSender(ctx, keeper, feegrantK, bankK, nexusK, accountK, stakingK, routingCtx, msg) + asset, err := escrowAssetToMessageSender(ctx, feegrantK, bankK, nexusK, ibcK, stakingK, routingCtx, msg) if err != nil { return err } @@ -49,11 +48,10 @@ func NewMessageRoute( // escrowAssetToMessageSender sends the asset to general msg sender account func escrowAssetToMessageSender( ctx sdk.Context, - keeper Keeper, feegrantK types.FeegrantKeeper, bankK types.BankKeeper, nexusK types.Nexus, - accountK types.AccountKeeper, + ibcK types.IBCKeeper, stakingK types.StakingKeeper, routingCtx nexus.RoutingContext, msg nexus.GeneralMessage, @@ -80,13 +78,12 @@ func escrowAssetToMessageSender( return asset, bankK.SendCoins(ctx, sender, types.AxelarGMPAccount, sdk.NewCoins(asset)) case nexus.TypeGeneralMessageWithToken: - // general message with token, get token from corresponding account - asset, sender, err := prepareTransfer(ctx, keeper, nexusK, bankK, accountK, *msg.Asset) + coin, err := nexustypes.NewCoin(ctx, nexusK, ibcK, bankK, *msg.Asset) if err != nil { return sdk.Coin{}, err } - return asset, bankK.SendCoins(ctx, sender, types.AxelarGMPAccount, sdk.NewCoins(asset)) + return coin.GetOriginalCoin(ctx), coin.Unlock(ctx, types.AxelarGMPAccount) default: return sdk.Coin{}, fmt.Errorf("unrecognized message type") } diff --git a/x/axelarnet/keeper/msg_server.go b/x/axelarnet/keeper/msg_server.go index 99bb342b0..3b0fa43da 100644 --- a/x/axelarnet/keeper/msg_server.go +++ b/x/axelarnet/keeper/msg_server.go @@ -9,7 +9,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/cosmos/cosmos-sdk/types/query" - ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" "github.com/ethereum/go-ethereum/crypto" "github.com/axelarnetwork/axelar-core/utils" @@ -17,6 +16,7 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" "github.com/axelarnetwork/axelar-core/x/axelarnet/types" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" tss "github.com/axelarnetwork/axelar-core/x/tss/exported" "github.com/axelarnetwork/utils/funcs" ) @@ -25,20 +25,18 @@ var _ types.MsgServiceServer = msgServer{} type msgServer struct { Keeper - nexus types.Nexus - bank types.BankKeeper - account types.AccountKeeper - ibcK IBCKeeper + nexus types.Nexus + bank types.BankKeeper + ibcK IBCKeeper } // NewMsgServerImpl returns an implementation of the axelarnet MsgServiceServer interface for the provided Keeper. -func NewMsgServerImpl(k Keeper, n types.Nexus, b types.BankKeeper, a types.AccountKeeper, ibcK IBCKeeper) types.MsgServiceServer { +func NewMsgServerImpl(k Keeper, n types.Nexus, b types.BankKeeper, ibcK IBCKeeper) types.MsgServiceServer { return msgServer{ - Keeper: k, - nexus: n, - bank: b, - account: a, - ibcK: ibcK, + Keeper: k, + nexus: n, + bank: b, + ibcK: ibcK, } } @@ -82,7 +80,7 @@ func (s msgServer) CallContract(c context.Context, req *types.CallContractReques }) if req.Fee != nil { - token, err := NewCoin(ctx, s.ibcK, s.nexus, req.Fee.Amount) + normalizedCoin, err := nexustypes.NewCoin(ctx, s.nexus, s.ibcK, s.bank, req.Fee.Amount) if err != nil { return nil, sdkerrors.Wrap(err, "unrecognized fee denom") } @@ -96,7 +94,7 @@ func (s msgServer) CallContract(c context.Context, req *types.CallContractReques MessageID: msgID, Recipient: req.Fee.Recipient, Fee: req.Fee.Amount, - Asset: token.GetDenom(), + Asset: normalizedCoin.GetDenom(), } if req.Fee.RefundRecipient != nil { feePaidEvent.RefundRecipient = req.Fee.RefundRecipient.String() @@ -188,12 +186,12 @@ func (s msgServer) ConfirmDeposit(c context.Context, req *types.ConfirmDepositRe return nil, fmt.Errorf("recipient chain '%s' is not activated", recipient.Chain.Name) } - normalizedCoin, err := NewCoin(ctx, s.ibcK, s.nexus, coin) + normalizedCoin, err := nexustypes.NewCoin(ctx, s.nexus, s.ibcK, s.bank, coin) if err != nil { return nil, err } - if err := normalizedCoin.Lock(s.bank, req.DepositAddress); err != nil { + if err := normalizedCoin.Lock(ctx, req.DepositAddress); err != nil { return nil, err } @@ -263,7 +261,7 @@ func (s msgServer) ExecutePendingTransfers(c context.Context, _ *types.ExecutePe continue } - if err = transfer(ctx, s.Keeper, s.nexus, s.bank, s.account, recipient, pendingTransfer.Asset); err != nil { + if err = transfer(ctx, s.Keeper, s.nexus, s.bank, s.ibcK, recipient, pendingTransfer.Asset); err != nil { s.Logger(ctx).Error("failed to transfer asset to axelarnet", "err", err) continue } @@ -282,7 +280,7 @@ func (s msgServer) ExecutePendingTransfers(c context.Context, _ *types.ExecutePe // release transfer fees if collector, ok := s.GetFeeCollector(ctx); ok { for _, fee := range s.nexus.GetTransferFees(ctx) { - if err := transfer(ctx, s.Keeper, s.nexus, s.bank, s.account, collector, fee); err != nil { + if err := transfer(ctx, s.Keeper, s.nexus, s.bank, s.ibcK, collector, fee); err != nil { s.Logger(ctx).Error("failed to collect fees", "err", err) continue } @@ -406,13 +404,18 @@ func (s msgServer) RouteIBCTransfers(c context.Context, _ *types.RouteIBCTransfe return nil, err } for _, p := range pendingTransfers { - token, sender, err := prepareTransfer(ctx, s.Keeper, s.nexus, s.bank, s.account, p.Asset) + coin, err := nexustypes.NewCoin(ctx, s.nexus, s.ibcK, s.bank, p.Asset) if err != nil { - s.Logger(ctx).Error(fmt.Sprintf("failed to prepare transfer %s: %s", p.String(), err)) + s.Logger(ctx).Error(fmt.Sprintf("failed to route IBC transfer %s: %s", p.String(), err)) continue } - funcs.MustNoErr(s.EnqueueIBCTransfer(ctx, types.NewIBCTransfer(sender, p.Recipient.Address, token, portID, channelID, p.ID))) + if err := coin.Unlock(ctx, types.AxelarGMPAccount); err != nil { + s.Logger(ctx).Error(fmt.Sprintf("failed to route IBC transfer %s: %s", p.String(), err)) + continue + } + + funcs.MustNoErr(s.EnqueueIBCTransfer(ctx, types.NewIBCTransfer(types.AxelarGMPAccount, p.Recipient.Address, coin.GetOriginalCoin(ctx), portID, channelID, p.ID))) s.nexus.ArchivePendingTransfer(ctx, p) } } @@ -496,71 +499,17 @@ func (s msgServer) RouteMessage(c context.Context, req *types.RouteMessageReques return &types.RouteMessageResponse{}, nil } -// toICS20 converts a cross chain transfer to ICS20 token -func toICS20(ctx sdk.Context, k Keeper, n types.Nexus, coin sdk.Coin) sdk.Coin { - // if chain or path not found, it will create coin with base denom - chain, _ := n.GetChainByNativeAsset(ctx, coin.GetDenom()) - path, _ := k.GetIBCPath(ctx, chain.Name) - - prefixedDenom := types.NewIBCPath(path, coin.Denom) - // construct the denomination trace from the full raw denomination - denomTrace := ibctransfertypes.ParseDenomTrace(prefixedDenom) - return sdk.NewCoin(denomTrace.IBCDenom(), coin.Amount) -} - -// isFromExternalCosmosChain returns true if the asset origins from cosmos chains -func isFromExternalCosmosChain(ctx sdk.Context, k Keeper, n types.Nexus, coin sdk.Coin) bool { - chain, ok := n.GetChainByNativeAsset(ctx, coin.GetDenom()) - if !ok { - return false - } - - if _, ok = k.GetCosmosChainByName(ctx, chain.Name); !ok { - return false - } - - _, ok = k.GetIBCPath(ctx, chain.Name) - return ok -} - -func transfer(ctx sdk.Context, k Keeper, n types.Nexus, b types.BankKeeper, a types.AccountKeeper, recipient sdk.AccAddress, coin sdk.Coin) error { - coin, escrowAddress, err := prepareTransfer(ctx, k, n, b, a, coin) +func transfer(ctx sdk.Context, k Keeper, n types.Nexus, b types.BankKeeper, ibc types.IBCKeeper, recipient sdk.AccAddress, coin sdk.Coin) error { + c, err := nexustypes.NewCoin(ctx, n, ibc, b, coin) if err != nil { - return fmt.Errorf("failed to prepare transfer %s: %s", coin, err) + return err } - if err = b.SendCoins( - ctx, escrowAddress, recipient, sdk.NewCoins(coin), - ); err != nil { - return fmt.Errorf("failed to send %s from %s to %s: %s", coin, escrowAddress, recipient, err) + if err := c.Unlock(ctx, recipient); err != nil { + return err } - k.Logger(ctx).Debug(fmt.Sprintf("successfully sent %s from %s to %s", coin, escrowAddress, recipient)) - - return nil -} -func prepareTransfer(ctx sdk.Context, k Keeper, n types.Nexus, b types.BankKeeper, a types.AccountKeeper, coin sdk.Coin) (sdk.Coin, sdk.AccAddress, error) { - var sender sdk.AccAddress - // pending transfer can be either of cosmos chains assets, Axelarnet native asset, assets from supported chain - switch { - // asset origins from cosmos chains, it will be converted to ICS20 token - case isFromExternalCosmosChain(ctx, k, n, coin): - coin = toICS20(ctx, k, n, coin) - sender = types.GetEscrowAddress(coin.GetDenom()) - case isNativeAssetOnAxelarnet(ctx, n, coin.Denom): - sender = types.GetEscrowAddress(coin.Denom) - case n.IsAssetRegistered(ctx, exported.Axelarnet, coin.Denom): - if err := b.MintCoins( - ctx, types.ModuleName, sdk.NewCoins(coin), - ); err != nil { - return sdk.Coin{}, nil, err - } + k.Logger(ctx).Debug(fmt.Sprintf("successfully sent %s to %s", coin, recipient)) - sender = a.GetModuleAddress(types.ModuleName) - default: - // should not reach here - panic(fmt.Sprintf("unrecognized %s token", coin.Denom)) - } - - return coin, sender, nil + return nil } diff --git a/x/axelarnet/message_handler.go b/x/axelarnet/message_handler.go index 8c92bde01..7050aed99 100644 --- a/x/axelarnet/message_handler.go +++ b/x/axelarnet/message_handler.go @@ -19,6 +19,7 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/keeper" "github.com/axelarnetwork/axelar-core/x/axelarnet/types" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" tss "github.com/axelarnetwork/axelar-core/x/tss/exported" "github.com/axelarnetwork/utils/funcs" ) @@ -127,7 +128,7 @@ func OnRecvMessage(ctx sdk.Context, k keeper.Keeper, ibcK keeper.IBCKeeper, n ty } // extract token from packet - token, err := extractTokenFromPacketData(ctx, ibcK, n, packet) + token, err := extractTokenFromPacketData(ctx, ibcK, n, b, packet) if err != nil { return channeltypes.NewErrorAcknowledgement(err) } @@ -184,7 +185,7 @@ func OnRecvMessage(ctx sdk.Context, k keeper.Keeper, ibcK keeper.IBCKeeper, n ty return ack } -func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcPath string, msg Message, token keeper.Coin) error { +func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcPath string, msg Message, token nexustypes.Coin) error { // validate source chain srcChainName, srcChainFound := ibcK.GetChainNameByIBCPath(ctx, ibcPath) if !srcChainFound { @@ -243,7 +244,7 @@ func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcP } } -func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token keeper.Coin) error { +func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexustypes.Coin) error { id, txID, nonce := n.GenerateMessageID(ctx) // ignore token for call contract @@ -284,7 +285,7 @@ func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAdd return n.SetNewMessage(ctx, m) } -func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token keeper.Coin) error { +func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexustypes.Coin) error { id, txID, nonce := n.GenerateMessageID(ctx) token, err := deductFee(ctx, b, msg.Fee, token, id) @@ -292,7 +293,7 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, return err } - if err = token.Lock(b, types.AxelarGMPAccount); err != nil { + if err = token.Lock(ctx, types.AxelarGMPAccount); err != nil { return err } @@ -322,11 +323,11 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, return n.SetNewMessage(ctx, m) } -func handleTokenSent(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token keeper.Coin) error { +func handleTokenSent(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexustypes.Coin) error { destChain := funcs.MustOk(n.GetChain(ctx, nexus.ChainName(msg.DestinationChain))) crossChainAddr := nexus.CrossChainAddress{Chain: destChain, Address: msg.DestinationAddress} - if err := token.Lock(b, types.AxelarGMPAccount); err != nil { + if err := token.Lock(ctx, types.AxelarGMPAccount); err != nil { return err } @@ -350,7 +351,7 @@ func handleTokenSent(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceA // extractTokenFromPacketData get normalized token from ICS20 packet // panic if unable to unmarshal packet data -func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, packet ibcexported.PacketI) (keeper.Coin, error) { +func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, b types.BankKeeper, packet ibcexported.PacketI) (nexustypes.Coin, error) { data := funcs.Must(types.ToICS20Packet(packet)) // parse the transfer amount @@ -388,17 +389,17 @@ func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types. denom = denomTrace.IBCDenom() } - return keeper.NewCoin(ctx, ibcK, n, sdk.NewCoin(denom, amount)) + return nexustypes.NewCoin(ctx, n, ibcK, b, sdk.NewCoin(denom, amount)) } // deductFee pays the fee and returns the updated transfer amount with the fee deducted -func deductFee(ctx sdk.Context, b types.BankKeeper, fee *Fee, token keeper.Coin, msgID string) (keeper.Coin, error) { +func deductFee(ctx sdk.Context, b types.BankKeeper, fee *Fee, token nexustypes.Coin, msgID string) (nexustypes.Coin, error) { if fee == nil { return token, nil } feeAmount := funcs.MustOk(sdk.NewIntFromString(fee.Amount)) - coin := sdk.NewCoin(funcs.Must(token.GetOriginalDenom()), feeAmount) + coin := sdk.NewCoin(token.GetOriginalCoin(ctx).Denom, feeAmount) recipient := funcs.Must(sdk.AccAddressFromBech32(fee.Recipient)) feePaidEvent := types.FeePaid{ diff --git a/x/axelarnet/module.go b/x/axelarnet/module.go index 0690fb8ea..3202c1917 100644 --- a/x/axelarnet/module.go +++ b/x/axelarnet/module.go @@ -29,6 +29,7 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/keeper" "github.com/axelarnetwork/axelar-core/x/axelarnet/types" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" "github.com/axelarnetwork/utils/funcs" ) @@ -96,16 +97,15 @@ func (AppModuleBasic) GetQueryCmd() *cobra.Command { // AppModule implements module.AppModule type AppModule struct { AppModuleBasic - logger log.Logger - ibcK keeper.IBCKeeper - keeper keeper.Keeper - nexus types.Nexus - bank types.BankKeeper - account types.AccountKeeper + logger log.Logger + ibcK keeper.IBCKeeper + keeper keeper.Keeper + nexus types.Nexus + bank types.BankKeeper } // NewAppModule creates a new AppModule object -func NewAppModule(ibcK keeper.IBCKeeper, nexus types.Nexus, bank types.BankKeeper, account types.AccountKeeper, logger log.Logger) AppModule { +func NewAppModule(ibcK keeper.IBCKeeper, nexus types.Nexus, bank types.BankKeeper, logger log.Logger) AppModule { return AppModule{ AppModuleBasic: AppModuleBasic{}, logger: logger, @@ -113,7 +113,6 @@ func NewAppModule(ibcK keeper.IBCKeeper, nexus types.Nexus, bank types.BankKeepe keeper: ibcK.Keeper, nexus: nexus, bank: bank, - account: account, } } @@ -141,7 +140,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw // Route returns the module's route func (am AppModule) Route() sdk.Route { - return sdk.NewRoute(types.RouterKey, NewHandler(am.keeper, am.nexus, am.bank, am.account, am.ibcK)) + return sdk.NewRoute(types.RouterKey, NewHandler(am.keeper, am.nexus, am.bank, am.ibcK)) } // QuerierRoute returns this module's query route @@ -157,7 +156,7 @@ func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { // RegisterServices registers a GRPC query service to respond to the // module-specific GRPC queries. func (am AppModule) RegisterServices(cfg module.Configurator) { - msgServer := keeper.NewMsgServerImpl(am.keeper, am.nexus, am.bank, am.account, am.ibcK) + msgServer := keeper.NewMsgServerImpl(am.keeper, am.nexus, am.bank, am.ibcK) types.RegisterMsgServiceServer(grpc.ServerWithSDKErrors{Server: cfg.MsgServer(), Err: types.ErrAxelarnet, Logger: am.keeper.Logger}, msgServer) types.RegisterQueryServiceServer(cfg.QueryServer(), keeper.NewGRPCQuerier(am.keeper, am.nexus)) @@ -344,6 +343,17 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed cross chain transfer transferID, ok := getSeqIDMapping(ctx, m.keeper, port, channel, sequence) if ok { + transfer := funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)) + coin, err := nexustypes.NewCoin(ctx, m.nexus, m.ibcK, m.bank, transfer.Token) + if err != nil { + return err + } + + err = coin.Lock(ctx, types.AxelarGMPAccount) + if err != nil { + return err + } + events.Emit(ctx, &types.IBCTransferFailed{ ID: transferID, @@ -360,12 +370,12 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed general message messageID, ok := getSeqMessageIDMapping(ctx, m.keeper, port, channel, sequence) if ok { - coin, err := keeper.NewCoin(ctx, m.ibcK, m.nexus, extractTokenFromAckOrTimeoutPacket(packet)) + coin, err := nexustypes.NewCoin(ctx, m.nexus, m.ibcK, m.bank, extractTokenFromAckOrTimeoutPacket(packet)) if err != nil { return err } - err = coin.Lock(m.bank, types.AxelarGMPAccount) + err = coin.Lock(ctx, types.AxelarGMPAccount) if err != nil { return err } diff --git a/x/axelarnet/types/expected_keepers.go b/x/axelarnet/types/expected_keepers.go index 509939888..8d3fcf469 100644 --- a/x/axelarnet/types/expected_keepers.go +++ b/x/axelarnet/types/expected_keepers.go @@ -6,7 +6,6 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" - "github.com/cosmos/cosmos-sdk/x/auth/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" @@ -18,6 +17,7 @@ import ( "github.com/axelarnetwork/axelar-core/utils" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" ) //go:generate moq -out ./mock/expected_keepers.go -pkg mock . BaseKeeper Nexus BankKeeper IBCTransferKeeper ChannelKeeper AccountKeeper PortKeeper GovKeeper StakingKeeper FeegrantKeeper IBCKeeper @@ -41,29 +41,51 @@ type BaseKeeper interface { // Nexus provides functionality to manage cross-chain transfers type Nexus interface { + Logger(ctx sdk.Context) log.Logger + + InitGenesis(ctx sdk.Context, genState *nexustypes.GenesisState) + ExportGenesis(ctx sdk.Context) *nexustypes.GenesisState + + SetParams(ctx sdk.Context, p nexustypes.Params) + GetParams(ctx sdk.Context) nexustypes.Params + + ActivateWasmConnection(ctx sdk.Context) + DeactivateWasmConnection(ctx sdk.Context) + IsWasmConnectionActivated(ctx sdk.Context) bool + IsChainActivated(ctx sdk.Context, chain nexus.Chain) bool + ActivateChain(ctx sdk.Context, chain nexus.Chain) + GetChains(ctx sdk.Context) []nexus.Chain + GetChain(ctx sdk.Context, chain nexus.ChainName) (nexus.Chain, bool) + IsChainMaintainer(ctx sdk.Context, chain nexus.Chain, maintainer sdk.ValAddress) bool + AddChainMaintainer(ctx sdk.Context, chain nexus.Chain, validator sdk.ValAddress) error + RemoveChainMaintainer(ctx sdk.Context, chain nexus.Chain, validator sdk.ValAddress) error + GetChainMaintainers(ctx sdk.Context, chain nexus.Chain) []sdk.ValAddress + GetChainMaintainerStates(ctx sdk.Context, chain nexus.Chain) []nexus.MaintainerState + LinkAddresses(ctx sdk.Context, sender nexus.CrossChainAddress, recipient nexus.CrossChainAddress) error + DeactivateChain(ctx sdk.Context, chain nexus.Chain) + RegisterFee(ctx sdk.Context, chain nexus.Chain, feeInfo nexus.FeeInfo) error + GetFeeInfo(ctx sdk.Context, chain nexus.Chain, asset string) nexus.FeeInfo + SetRateLimit(ctx sdk.Context, chainName nexus.ChainName, limit sdk.Coin, window time.Duration) error + RateLimitTransfer(ctx sdk.Context, chain nexus.ChainName, asset sdk.Coin, direction nexus.TransferDirection) error + SetNewMessage(ctx sdk.Context, msg nexus.GeneralMessage) error + GetMessage(ctx sdk.Context, id string) (nexus.GeneralMessage, bool) + SetMessageExecuted(ctx sdk.Context, id string) error + RouteMessage(ctx sdk.Context, id string, routingCtx ...nexus.RoutingContext) error + DequeueRouteMessage(ctx sdk.Context) (nexus.GeneralMessage, bool) + IsAssetRegistered(ctx sdk.Context, chain nexus.Chain, denom string) bool + GetChainByNativeAsset(ctx sdk.Context, asset string) (chain nexus.Chain, ok bool) EnqueueForTransfer(ctx sdk.Context, sender nexus.CrossChainAddress, amount sdk.Coin) (nexus.TransferID, error) EnqueueTransfer(ctx sdk.Context, senderChain nexus.Chain, recipient nexus.CrossChainAddress, asset sdk.Coin) (nexus.TransferID, error) GetTransfersForChainPaginated(ctx sdk.Context, chain nexus.Chain, state nexus.TransferState, pageRequest *query.PageRequest) ([]nexus.CrossChainTransfer, *query.PageResponse, error) ArchivePendingTransfer(ctx sdk.Context, transfer nexus.CrossChainTransfer) - GetChain(ctx sdk.Context, chain nexus.ChainName) (nexus.Chain, bool) - LinkAddresses(ctx sdk.Context, sender nexus.CrossChainAddress, recipient nexus.CrossChainAddress) error - IsAssetRegistered(ctx sdk.Context, chain nexus.Chain, denom string) bool RegisterAsset(ctx sdk.Context, chain nexus.Chain, asset nexus.Asset, limit sdk.Uint, window time.Duration) error GetRecipient(ctx sdk.Context, sender nexus.CrossChainAddress) (nexus.CrossChainAddress, bool) SetChain(ctx sdk.Context, chain nexus.Chain) GetTransferFees(ctx sdk.Context) sdk.Coins SubTransferFee(ctx sdk.Context, coin sdk.Coin) - ActivateChain(ctx sdk.Context, chain nexus.Chain) - GetChainByNativeAsset(ctx sdk.Context, asset string) (nexus.Chain, bool) - IsChainActivated(ctx sdk.Context, chain nexus.Chain) bool - RateLimitTransfer(ctx sdk.Context, chain nexus.ChainName, asset sdk.Coin, direction nexus.TransferDirection) error - GetMessage(ctx sdk.Context, id string) (m nexus.GeneralMessage, found bool) - SetNewMessage(ctx sdk.Context, m nexus.GeneralMessage) error - SetMessageExecuted(ctx sdk.Context, id string) error SetMessageFailed(ctx sdk.Context, id string) error GenerateMessageID(ctx sdk.Context) (string, []byte, uint64) ValidateAddress(ctx sdk.Context, address nexus.CrossChainAddress) error - RouteMessage(ctx sdk.Context, id string, routingCtx ...nexus.RoutingContext) error } // BankKeeper defines the expected interface contract the vesting module requires @@ -107,8 +129,6 @@ type ChannelKeeper interface { // creating a x/bank keeper. type AccountKeeper interface { GetModuleAddress(moduleName string) sdk.AccAddress - - GetModuleAccount(ctx sdk.Context, moduleName string) types.ModuleAccountI // used in module_test } // CosmosChainGetter exposes GetCosmosChainByName @@ -137,4 +157,6 @@ type FeegrantKeeper interface { // IBCKeeper defines the expected IBC keeper type IBCKeeper interface { SendMessage(c context.Context, recipient nexus.CrossChainAddress, asset sdk.Coin, payload string, id string) error + ParseIBCDenom(ctx sdk.Context, ibcDenom string) (ibctypes.DenomTrace, error) + GetIBCPath(ctx sdk.Context, chain nexus.ChainName) (string, bool) } diff --git a/x/axelarnet/types/mock/expected_keepers.go b/x/axelarnet/types/mock/expected_keepers.go index c47a2c5f9..21acd9ecc 100644 --- a/x/axelarnet/types/mock/expected_keepers.go +++ b/x/axelarnet/types/mock/expected_keepers.go @@ -8,9 +8,9 @@ import ( utils "github.com/axelarnetwork/axelar-core/utils" axelarnettypes "github.com/axelarnetwork/axelar-core/x/axelarnet/types" github_com_axelarnetwork_axelar_core_x_nexus_exported "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" cosmossdktypes "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" - "github.com/cosmos/cosmos-sdk/x/auth/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" gov "github.com/cosmos/cosmos-sdk/x/gov/types" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" @@ -666,15 +666,33 @@ var _ axelarnettypes.Nexus = &NexusMock{} // ActivateChainFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) { // panic("mock out the ActivateChain method") // }, +// ActivateWasmConnectionFunc: func(ctx cosmossdktypes.Context) { +// panic("mock out the ActivateWasmConnection method") +// }, +// AddChainMaintainerFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, validator cosmossdktypes.ValAddress) error { +// panic("mock out the AddChainMaintainer method") +// }, // ArchivePendingTransferFunc: func(ctx cosmossdktypes.Context, transfer github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainTransfer) { // panic("mock out the ArchivePendingTransfer method") // }, +// DeactivateChainFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) { +// panic("mock out the DeactivateChain method") +// }, +// DeactivateWasmConnectionFunc: func(ctx cosmossdktypes.Context) { +// panic("mock out the DeactivateWasmConnection method") +// }, +// DequeueRouteMessageFunc: func(ctx cosmossdktypes.Context) (github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage, bool) { +// panic("mock out the DequeueRouteMessage method") +// }, // EnqueueForTransferFunc: func(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, amount cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferID, error) { // panic("mock out the EnqueueForTransfer method") // }, // EnqueueTransferFunc: func(ctx cosmossdktypes.Context, senderChain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, recipient github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, asset cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferID, error) { // panic("mock out the EnqueueTransfer method") // }, +// ExportGenesisFunc: func(ctx cosmossdktypes.Context) *nexustypes.GenesisState { +// panic("mock out the ExportGenesis method") +// }, // GenerateMessageIDFunc: func(ctx cosmossdktypes.Context) (string, []byte, uint64) { // panic("mock out the GenerateMessageID method") // }, @@ -684,9 +702,24 @@ var _ axelarnettypes.Nexus = &NexusMock{} // GetChainByNativeAssetFunc: func(ctx cosmossdktypes.Context, asset string) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) { // panic("mock out the GetChainByNativeAsset method") // }, +// GetChainMaintainerStatesFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []github_com_axelarnetwork_axelar_core_x_nexus_exported.MaintainerState { +// panic("mock out the GetChainMaintainerStates method") +// }, +// GetChainMaintainersFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []cosmossdktypes.ValAddress { +// panic("mock out the GetChainMaintainers method") +// }, +// GetChainsFunc: func(ctx cosmossdktypes.Context) []github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain { +// panic("mock out the GetChains method") +// }, +// GetFeeInfoFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, asset string) github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo { +// panic("mock out the GetFeeInfo method") +// }, // GetMessageFunc: func(ctx cosmossdktypes.Context, id string) (github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage, bool) { // panic("mock out the GetMessage method") // }, +// GetParamsFunc: func(ctx cosmossdktypes.Context) nexustypes.Params { +// panic("mock out the GetParams method") +// }, // GetRecipientFunc: func(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress) (github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, bool) { // panic("mock out the GetRecipient method") // }, @@ -696,21 +729,39 @@ var _ axelarnettypes.Nexus = &NexusMock{} // GetTransfersForChainPaginatedFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, state github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferState, pageRequest *query.PageRequest) ([]github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainTransfer, *query.PageResponse, error) { // panic("mock out the GetTransfersForChainPaginated method") // }, +// InitGenesisFunc: func(ctx cosmossdktypes.Context, genState *nexustypes.GenesisState) { +// panic("mock out the InitGenesis method") +// }, // IsAssetRegisteredFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, denom string) bool { // panic("mock out the IsAssetRegistered method") // }, // IsChainActivatedFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) bool { // panic("mock out the IsChainActivated method") // }, +// IsChainMaintainerFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, maintainer cosmossdktypes.ValAddress) bool { +// panic("mock out the IsChainMaintainer method") +// }, +// IsWasmConnectionActivatedFunc: func(ctx cosmossdktypes.Context) bool { +// panic("mock out the IsWasmConnectionActivated method") +// }, // LinkAddressesFunc: func(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, recipient github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress) error { // panic("mock out the LinkAddresses method") // }, +// LoggerFunc: func(ctx cosmossdktypes.Context) log.Logger { +// panic("mock out the Logger method") +// }, // RateLimitTransferFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, asset cosmossdktypes.Coin, direction github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferDirection) error { // panic("mock out the RateLimitTransfer method") // }, // RegisterAssetFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, asset github_com_axelarnetwork_axelar_core_x_nexus_exported.Asset, limit cosmossdktypes.Uint, window time.Duration) error { // panic("mock out the RegisterAsset method") // }, +// RegisterFeeFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, feeInfo github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo) error { +// panic("mock out the RegisterFee method") +// }, +// RemoveChainMaintainerFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, validator cosmossdktypes.ValAddress) error { +// panic("mock out the RemoveChainMaintainer method") +// }, // RouteMessageFunc: func(ctx cosmossdktypes.Context, id string, routingCtx ...github_com_axelarnetwork_axelar_core_x_nexus_exported.RoutingContext) error { // panic("mock out the RouteMessage method") // }, @@ -723,9 +774,15 @@ var _ axelarnettypes.Nexus = &NexusMock{} // SetMessageFailedFunc: func(ctx cosmossdktypes.Context, id string) error { // panic("mock out the SetMessageFailed method") // }, -// SetNewMessageFunc: func(ctx cosmossdktypes.Context, m github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage) error { +// SetNewMessageFunc: func(ctx cosmossdktypes.Context, msg github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage) error { // panic("mock out the SetNewMessage method") // }, +// SetParamsFunc: func(ctx cosmossdktypes.Context, p nexustypes.Params) { +// panic("mock out the SetParams method") +// }, +// SetRateLimitFunc: func(ctx cosmossdktypes.Context, chainName github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, limit cosmossdktypes.Coin, window time.Duration) error { +// panic("mock out the SetRateLimit method") +// }, // SubTransferFeeFunc: func(ctx cosmossdktypes.Context, coin cosmossdktypes.Coin) { // panic("mock out the SubTransferFee method") // }, @@ -742,15 +799,33 @@ type NexusMock struct { // ActivateChainFunc mocks the ActivateChain method. ActivateChainFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) + // ActivateWasmConnectionFunc mocks the ActivateWasmConnection method. + ActivateWasmConnectionFunc func(ctx cosmossdktypes.Context) + + // AddChainMaintainerFunc mocks the AddChainMaintainer method. + AddChainMaintainerFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, validator cosmossdktypes.ValAddress) error + // ArchivePendingTransferFunc mocks the ArchivePendingTransfer method. ArchivePendingTransferFunc func(ctx cosmossdktypes.Context, transfer github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainTransfer) + // DeactivateChainFunc mocks the DeactivateChain method. + DeactivateChainFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) + + // DeactivateWasmConnectionFunc mocks the DeactivateWasmConnection method. + DeactivateWasmConnectionFunc func(ctx cosmossdktypes.Context) + + // DequeueRouteMessageFunc mocks the DequeueRouteMessage method. + DequeueRouteMessageFunc func(ctx cosmossdktypes.Context) (github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage, bool) + // EnqueueForTransferFunc mocks the EnqueueForTransfer method. EnqueueForTransferFunc func(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, amount cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferID, error) // EnqueueTransferFunc mocks the EnqueueTransfer method. EnqueueTransferFunc func(ctx cosmossdktypes.Context, senderChain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, recipient github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, asset cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferID, error) + // ExportGenesisFunc mocks the ExportGenesis method. + ExportGenesisFunc func(ctx cosmossdktypes.Context) *nexustypes.GenesisState + // GenerateMessageIDFunc mocks the GenerateMessageID method. GenerateMessageIDFunc func(ctx cosmossdktypes.Context) (string, []byte, uint64) @@ -760,9 +835,24 @@ type NexusMock struct { // GetChainByNativeAssetFunc mocks the GetChainByNativeAsset method. GetChainByNativeAssetFunc func(ctx cosmossdktypes.Context, asset string) (github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, bool) + // GetChainMaintainerStatesFunc mocks the GetChainMaintainerStates method. + GetChainMaintainerStatesFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []github_com_axelarnetwork_axelar_core_x_nexus_exported.MaintainerState + + // GetChainMaintainersFunc mocks the GetChainMaintainers method. + GetChainMaintainersFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []cosmossdktypes.ValAddress + + // GetChainsFunc mocks the GetChains method. + GetChainsFunc func(ctx cosmossdktypes.Context) []github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + + // GetFeeInfoFunc mocks the GetFeeInfo method. + GetFeeInfoFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, asset string) github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo + // GetMessageFunc mocks the GetMessage method. GetMessageFunc func(ctx cosmossdktypes.Context, id string) (github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage, bool) + // GetParamsFunc mocks the GetParams method. + GetParamsFunc func(ctx cosmossdktypes.Context) nexustypes.Params + // GetRecipientFunc mocks the GetRecipient method. GetRecipientFunc func(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress) (github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, bool) @@ -772,21 +862,39 @@ type NexusMock struct { // GetTransfersForChainPaginatedFunc mocks the GetTransfersForChainPaginated method. GetTransfersForChainPaginatedFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, state github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferState, pageRequest *query.PageRequest) ([]github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainTransfer, *query.PageResponse, error) + // InitGenesisFunc mocks the InitGenesis method. + InitGenesisFunc func(ctx cosmossdktypes.Context, genState *nexustypes.GenesisState) + // IsAssetRegisteredFunc mocks the IsAssetRegistered method. IsAssetRegisteredFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, denom string) bool // IsChainActivatedFunc mocks the IsChainActivated method. IsChainActivatedFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) bool + // IsChainMaintainerFunc mocks the IsChainMaintainer method. + IsChainMaintainerFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, maintainer cosmossdktypes.ValAddress) bool + + // IsWasmConnectionActivatedFunc mocks the IsWasmConnectionActivated method. + IsWasmConnectionActivatedFunc func(ctx cosmossdktypes.Context) bool + // LinkAddressesFunc mocks the LinkAddresses method. LinkAddressesFunc func(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, recipient github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress) error + // LoggerFunc mocks the Logger method. + LoggerFunc func(ctx cosmossdktypes.Context) log.Logger + // RateLimitTransferFunc mocks the RateLimitTransfer method. RateLimitTransferFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, asset cosmossdktypes.Coin, direction github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferDirection) error // RegisterAssetFunc mocks the RegisterAsset method. RegisterAssetFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, asset github_com_axelarnetwork_axelar_core_x_nexus_exported.Asset, limit cosmossdktypes.Uint, window time.Duration) error + // RegisterFeeFunc mocks the RegisterFee method. + RegisterFeeFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, feeInfo github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo) error + + // RemoveChainMaintainerFunc mocks the RemoveChainMaintainer method. + RemoveChainMaintainerFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, validator cosmossdktypes.ValAddress) error + // RouteMessageFunc mocks the RouteMessage method. RouteMessageFunc func(ctx cosmossdktypes.Context, id string, routingCtx ...github_com_axelarnetwork_axelar_core_x_nexus_exported.RoutingContext) error @@ -800,7 +908,13 @@ type NexusMock struct { SetMessageFailedFunc func(ctx cosmossdktypes.Context, id string) error // SetNewMessageFunc mocks the SetNewMessage method. - SetNewMessageFunc func(ctx cosmossdktypes.Context, m github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage) error + SetNewMessageFunc func(ctx cosmossdktypes.Context, msg github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage) error + + // SetParamsFunc mocks the SetParams method. + SetParamsFunc func(ctx cosmossdktypes.Context, p nexustypes.Params) + + // SetRateLimitFunc mocks the SetRateLimit method. + SetRateLimitFunc func(ctx cosmossdktypes.Context, chainName github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, limit cosmossdktypes.Coin, window time.Duration) error // SubTransferFeeFunc mocks the SubTransferFee method. SubTransferFeeFunc func(ctx cosmossdktypes.Context, coin cosmossdktypes.Coin) @@ -817,6 +931,20 @@ type NexusMock struct { // Chain is the chain argument value. Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain } + // ActivateWasmConnection holds details about calls to the ActivateWasmConnection method. + ActivateWasmConnection []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } + // AddChainMaintainer holds details about calls to the AddChainMaintainer method. + AddChainMaintainer []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + // Validator is the validator argument value. + Validator cosmossdktypes.ValAddress + } // ArchivePendingTransfer holds details about calls to the ArchivePendingTransfer method. ArchivePendingTransfer []struct { // Ctx is the ctx argument value. @@ -824,6 +952,23 @@ type NexusMock struct { // Transfer is the transfer argument value. Transfer github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainTransfer } + // DeactivateChain holds details about calls to the DeactivateChain method. + DeactivateChain []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + } + // DeactivateWasmConnection holds details about calls to the DeactivateWasmConnection method. + DeactivateWasmConnection []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } + // DequeueRouteMessage holds details about calls to the DequeueRouteMessage method. + DequeueRouteMessage []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } // EnqueueForTransfer holds details about calls to the EnqueueForTransfer method. EnqueueForTransfer []struct { // Ctx is the ctx argument value. @@ -844,6 +989,11 @@ type NexusMock struct { // Asset is the asset argument value. Asset cosmossdktypes.Coin } + // ExportGenesis holds details about calls to the ExportGenesis method. + ExportGenesis []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } // GenerateMessageID holds details about calls to the GenerateMessageID method. GenerateMessageID []struct { // Ctx is the ctx argument value. @@ -863,6 +1013,34 @@ type NexusMock struct { // Asset is the asset argument value. Asset string } + // GetChainMaintainerStates holds details about calls to the GetChainMaintainerStates method. + GetChainMaintainerStates []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + } + // GetChainMaintainers holds details about calls to the GetChainMaintainers method. + GetChainMaintainers []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + } + // GetChains holds details about calls to the GetChains method. + GetChains []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } + // GetFeeInfo holds details about calls to the GetFeeInfo method. + GetFeeInfo []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + // Asset is the asset argument value. + Asset string + } // GetMessage holds details about calls to the GetMessage method. GetMessage []struct { // Ctx is the ctx argument value. @@ -870,6 +1048,11 @@ type NexusMock struct { // ID is the id argument value. ID string } + // GetParams holds details about calls to the GetParams method. + GetParams []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } // GetRecipient holds details about calls to the GetRecipient method. GetRecipient []struct { // Ctx is the ctx argument value. @@ -893,6 +1076,13 @@ type NexusMock struct { // PageRequest is the pageRequest argument value. PageRequest *query.PageRequest } + // InitGenesis holds details about calls to the InitGenesis method. + InitGenesis []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // GenState is the genState argument value. + GenState *nexustypes.GenesisState + } // IsAssetRegistered holds details about calls to the IsAssetRegistered method. IsAssetRegistered []struct { // Ctx is the ctx argument value. @@ -909,6 +1099,20 @@ type NexusMock struct { // Chain is the chain argument value. Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain } + // IsChainMaintainer holds details about calls to the IsChainMaintainer method. + IsChainMaintainer []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + // Maintainer is the maintainer argument value. + Maintainer cosmossdktypes.ValAddress + } + // IsWasmConnectionActivated holds details about calls to the IsWasmConnectionActivated method. + IsWasmConnectionActivated []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } // LinkAddresses holds details about calls to the LinkAddresses method. LinkAddresses []struct { // Ctx is the ctx argument value. @@ -918,6 +1122,11 @@ type NexusMock struct { // Recipient is the recipient argument value. Recipient github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress } + // Logger holds details about calls to the Logger method. + Logger []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + } // RateLimitTransfer holds details about calls to the RateLimitTransfer method. RateLimitTransfer []struct { // Ctx is the ctx argument value. @@ -942,6 +1151,24 @@ type NexusMock struct { // Window is the window argument value. Window time.Duration } + // RegisterFee holds details about calls to the RegisterFee method. + RegisterFee []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + // FeeInfo is the feeInfo argument value. + FeeInfo github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo + } + // RemoveChainMaintainer holds details about calls to the RemoveChainMaintainer method. + RemoveChainMaintainer []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + // Validator is the validator argument value. + Validator cosmossdktypes.ValAddress + } // RouteMessage holds details about calls to the RouteMessage method. RouteMessage []struct { // Ctx is the ctx argument value. @@ -976,8 +1203,26 @@ type NexusMock struct { SetNewMessage []struct { // Ctx is the ctx argument value. Ctx cosmossdktypes.Context - // M is the m argument value. - M github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage + // Msg is the msg argument value. + Msg github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage + } + // SetParams holds details about calls to the SetParams method. + SetParams []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // P is the p argument value. + P nexustypes.Params + } + // SetRateLimit holds details about calls to the SetRateLimit method. + SetRateLimit []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // ChainName is the chainName argument value. + ChainName github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + // Limit is the limit argument value. + Limit cosmossdktypes.Coin + // Window is the window argument value. + Window time.Duration } // SubTransferFee holds details about calls to the SubTransferFee method. SubTransferFee []struct { @@ -995,26 +1240,45 @@ type NexusMock struct { } } lockActivateChain sync.RWMutex + lockActivateWasmConnection sync.RWMutex + lockAddChainMaintainer sync.RWMutex lockArchivePendingTransfer sync.RWMutex + lockDeactivateChain sync.RWMutex + lockDeactivateWasmConnection sync.RWMutex + lockDequeueRouteMessage sync.RWMutex lockEnqueueForTransfer sync.RWMutex lockEnqueueTransfer sync.RWMutex + lockExportGenesis sync.RWMutex lockGenerateMessageID sync.RWMutex lockGetChain sync.RWMutex lockGetChainByNativeAsset sync.RWMutex + lockGetChainMaintainerStates sync.RWMutex + lockGetChainMaintainers sync.RWMutex + lockGetChains sync.RWMutex + lockGetFeeInfo sync.RWMutex lockGetMessage sync.RWMutex + lockGetParams sync.RWMutex lockGetRecipient sync.RWMutex lockGetTransferFees sync.RWMutex lockGetTransfersForChainPaginated sync.RWMutex + lockInitGenesis sync.RWMutex lockIsAssetRegistered sync.RWMutex lockIsChainActivated sync.RWMutex + lockIsChainMaintainer sync.RWMutex + lockIsWasmConnectionActivated sync.RWMutex lockLinkAddresses sync.RWMutex + lockLogger sync.RWMutex lockRateLimitTransfer sync.RWMutex lockRegisterAsset sync.RWMutex + lockRegisterFee sync.RWMutex + lockRemoveChainMaintainer sync.RWMutex lockRouteMessage sync.RWMutex lockSetChain sync.RWMutex lockSetMessageExecuted sync.RWMutex lockSetMessageFailed sync.RWMutex lockSetNewMessage sync.RWMutex + lockSetParams sync.RWMutex + lockSetRateLimit sync.RWMutex lockSubTransferFee sync.RWMutex lockValidateAddress sync.RWMutex } @@ -1055,6 +1319,78 @@ func (mock *NexusMock) ActivateChainCalls() []struct { return calls } +// ActivateWasmConnection calls ActivateWasmConnectionFunc. +func (mock *NexusMock) ActivateWasmConnection(ctx cosmossdktypes.Context) { + if mock.ActivateWasmConnectionFunc == nil { + panic("NexusMock.ActivateWasmConnectionFunc: method is nil but Nexus.ActivateWasmConnection was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockActivateWasmConnection.Lock() + mock.calls.ActivateWasmConnection = append(mock.calls.ActivateWasmConnection, callInfo) + mock.lockActivateWasmConnection.Unlock() + mock.ActivateWasmConnectionFunc(ctx) +} + +// ActivateWasmConnectionCalls gets all the calls that were made to ActivateWasmConnection. +// Check the length with: +// +// len(mockedNexus.ActivateWasmConnectionCalls()) +func (mock *NexusMock) ActivateWasmConnectionCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockActivateWasmConnection.RLock() + calls = mock.calls.ActivateWasmConnection + mock.lockActivateWasmConnection.RUnlock() + return calls +} + +// AddChainMaintainer calls AddChainMaintainerFunc. +func (mock *NexusMock) AddChainMaintainer(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, validator cosmossdktypes.ValAddress) error { + if mock.AddChainMaintainerFunc == nil { + panic("NexusMock.AddChainMaintainerFunc: method is nil but Nexus.AddChainMaintainer was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Validator cosmossdktypes.ValAddress + }{ + Ctx: ctx, + Chain: chain, + Validator: validator, + } + mock.lockAddChainMaintainer.Lock() + mock.calls.AddChainMaintainer = append(mock.calls.AddChainMaintainer, callInfo) + mock.lockAddChainMaintainer.Unlock() + return mock.AddChainMaintainerFunc(ctx, chain, validator) +} + +// AddChainMaintainerCalls gets all the calls that were made to AddChainMaintainer. +// Check the length with: +// +// len(mockedNexus.AddChainMaintainerCalls()) +func (mock *NexusMock) AddChainMaintainerCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Validator cosmossdktypes.ValAddress +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Validator cosmossdktypes.ValAddress + } + mock.lockAddChainMaintainer.RLock() + calls = mock.calls.AddChainMaintainer + mock.lockAddChainMaintainer.RUnlock() + return calls +} + // ArchivePendingTransfer calls ArchivePendingTransferFunc. func (mock *NexusMock) ArchivePendingTransfer(ctx cosmossdktypes.Context, transfer github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainTransfer) { if mock.ArchivePendingTransferFunc == nil { @@ -1091,6 +1427,106 @@ func (mock *NexusMock) ArchivePendingTransferCalls() []struct { return calls } +// DeactivateChain calls DeactivateChainFunc. +func (mock *NexusMock) DeactivateChain(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) { + if mock.DeactivateChainFunc == nil { + panic("NexusMock.DeactivateChainFunc: method is nil but Nexus.DeactivateChain was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + }{ + Ctx: ctx, + Chain: chain, + } + mock.lockDeactivateChain.Lock() + mock.calls.DeactivateChain = append(mock.calls.DeactivateChain, callInfo) + mock.lockDeactivateChain.Unlock() + mock.DeactivateChainFunc(ctx, chain) +} + +// DeactivateChainCalls gets all the calls that were made to DeactivateChain. +// Check the length with: +// +// len(mockedNexus.DeactivateChainCalls()) +func (mock *NexusMock) DeactivateChainCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + } + mock.lockDeactivateChain.RLock() + calls = mock.calls.DeactivateChain + mock.lockDeactivateChain.RUnlock() + return calls +} + +// DeactivateWasmConnection calls DeactivateWasmConnectionFunc. +func (mock *NexusMock) DeactivateWasmConnection(ctx cosmossdktypes.Context) { + if mock.DeactivateWasmConnectionFunc == nil { + panic("NexusMock.DeactivateWasmConnectionFunc: method is nil but Nexus.DeactivateWasmConnection was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockDeactivateWasmConnection.Lock() + mock.calls.DeactivateWasmConnection = append(mock.calls.DeactivateWasmConnection, callInfo) + mock.lockDeactivateWasmConnection.Unlock() + mock.DeactivateWasmConnectionFunc(ctx) +} + +// DeactivateWasmConnectionCalls gets all the calls that were made to DeactivateWasmConnection. +// Check the length with: +// +// len(mockedNexus.DeactivateWasmConnectionCalls()) +func (mock *NexusMock) DeactivateWasmConnectionCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockDeactivateWasmConnection.RLock() + calls = mock.calls.DeactivateWasmConnection + mock.lockDeactivateWasmConnection.RUnlock() + return calls +} + +// DequeueRouteMessage calls DequeueRouteMessageFunc. +func (mock *NexusMock) DequeueRouteMessage(ctx cosmossdktypes.Context) (github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage, bool) { + if mock.DequeueRouteMessageFunc == nil { + panic("NexusMock.DequeueRouteMessageFunc: method is nil but Nexus.DequeueRouteMessage was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockDequeueRouteMessage.Lock() + mock.calls.DequeueRouteMessage = append(mock.calls.DequeueRouteMessage, callInfo) + mock.lockDequeueRouteMessage.Unlock() + return mock.DequeueRouteMessageFunc(ctx) +} + +// DequeueRouteMessageCalls gets all the calls that were made to DequeueRouteMessage. +// Check the length with: +// +// len(mockedNexus.DequeueRouteMessageCalls()) +func (mock *NexusMock) DequeueRouteMessageCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockDequeueRouteMessage.RLock() + calls = mock.calls.DequeueRouteMessage + mock.lockDequeueRouteMessage.RUnlock() + return calls +} + // EnqueueForTransfer calls EnqueueForTransferFunc. func (mock *NexusMock) EnqueueForTransfer(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, amount cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferID, error) { if mock.EnqueueForTransferFunc == nil { @@ -1175,6 +1611,38 @@ func (mock *NexusMock) EnqueueTransferCalls() []struct { return calls } +// ExportGenesis calls ExportGenesisFunc. +func (mock *NexusMock) ExportGenesis(ctx cosmossdktypes.Context) *nexustypes.GenesisState { + if mock.ExportGenesisFunc == nil { + panic("NexusMock.ExportGenesisFunc: method is nil but Nexus.ExportGenesis was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockExportGenesis.Lock() + mock.calls.ExportGenesis = append(mock.calls.ExportGenesis, callInfo) + mock.lockExportGenesis.Unlock() + return mock.ExportGenesisFunc(ctx) +} + +// ExportGenesisCalls gets all the calls that were made to ExportGenesis. +// Check the length with: +// +// len(mockedNexus.ExportGenesisCalls()) +func (mock *NexusMock) ExportGenesisCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockExportGenesis.RLock() + calls = mock.calls.ExportGenesis + mock.lockExportGenesis.RUnlock() + return calls +} + // GenerateMessageID calls GenerateMessageIDFunc. func (mock *NexusMock) GenerateMessageID(ctx cosmossdktypes.Context) (string, []byte, uint64) { if mock.GenerateMessageIDFunc == nil { @@ -1279,6 +1747,150 @@ func (mock *NexusMock) GetChainByNativeAssetCalls() []struct { return calls } +// GetChainMaintainerStates calls GetChainMaintainerStatesFunc. +func (mock *NexusMock) GetChainMaintainerStates(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []github_com_axelarnetwork_axelar_core_x_nexus_exported.MaintainerState { + if mock.GetChainMaintainerStatesFunc == nil { + panic("NexusMock.GetChainMaintainerStatesFunc: method is nil but Nexus.GetChainMaintainerStates was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + }{ + Ctx: ctx, + Chain: chain, + } + mock.lockGetChainMaintainerStates.Lock() + mock.calls.GetChainMaintainerStates = append(mock.calls.GetChainMaintainerStates, callInfo) + mock.lockGetChainMaintainerStates.Unlock() + return mock.GetChainMaintainerStatesFunc(ctx, chain) +} + +// GetChainMaintainerStatesCalls gets all the calls that were made to GetChainMaintainerStates. +// Check the length with: +// +// len(mockedNexus.GetChainMaintainerStatesCalls()) +func (mock *NexusMock) GetChainMaintainerStatesCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + } + mock.lockGetChainMaintainerStates.RLock() + calls = mock.calls.GetChainMaintainerStates + mock.lockGetChainMaintainerStates.RUnlock() + return calls +} + +// GetChainMaintainers calls GetChainMaintainersFunc. +func (mock *NexusMock) GetChainMaintainers(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain) []cosmossdktypes.ValAddress { + if mock.GetChainMaintainersFunc == nil { + panic("NexusMock.GetChainMaintainersFunc: method is nil but Nexus.GetChainMaintainers was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + }{ + Ctx: ctx, + Chain: chain, + } + mock.lockGetChainMaintainers.Lock() + mock.calls.GetChainMaintainers = append(mock.calls.GetChainMaintainers, callInfo) + mock.lockGetChainMaintainers.Unlock() + return mock.GetChainMaintainersFunc(ctx, chain) +} + +// GetChainMaintainersCalls gets all the calls that were made to GetChainMaintainers. +// Check the length with: +// +// len(mockedNexus.GetChainMaintainersCalls()) +func (mock *NexusMock) GetChainMaintainersCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + } + mock.lockGetChainMaintainers.RLock() + calls = mock.calls.GetChainMaintainers + mock.lockGetChainMaintainers.RUnlock() + return calls +} + +// GetChains calls GetChainsFunc. +func (mock *NexusMock) GetChains(ctx cosmossdktypes.Context) []github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain { + if mock.GetChainsFunc == nil { + panic("NexusMock.GetChainsFunc: method is nil but Nexus.GetChains was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockGetChains.Lock() + mock.calls.GetChains = append(mock.calls.GetChains, callInfo) + mock.lockGetChains.Unlock() + return mock.GetChainsFunc(ctx) +} + +// GetChainsCalls gets all the calls that were made to GetChains. +// Check the length with: +// +// len(mockedNexus.GetChainsCalls()) +func (mock *NexusMock) GetChainsCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockGetChains.RLock() + calls = mock.calls.GetChains + mock.lockGetChains.RUnlock() + return calls +} + +// GetFeeInfo calls GetFeeInfoFunc. +func (mock *NexusMock) GetFeeInfo(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, asset string) github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo { + if mock.GetFeeInfoFunc == nil { + panic("NexusMock.GetFeeInfoFunc: method is nil but Nexus.GetFeeInfo was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Asset string + }{ + Ctx: ctx, + Chain: chain, + Asset: asset, + } + mock.lockGetFeeInfo.Lock() + mock.calls.GetFeeInfo = append(mock.calls.GetFeeInfo, callInfo) + mock.lockGetFeeInfo.Unlock() + return mock.GetFeeInfoFunc(ctx, chain, asset) +} + +// GetFeeInfoCalls gets all the calls that were made to GetFeeInfo. +// Check the length with: +// +// len(mockedNexus.GetFeeInfoCalls()) +func (mock *NexusMock) GetFeeInfoCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Asset string +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Asset string + } + mock.lockGetFeeInfo.RLock() + calls = mock.calls.GetFeeInfo + mock.lockGetFeeInfo.RUnlock() + return calls +} + // GetMessage calls GetMessageFunc. func (mock *NexusMock) GetMessage(ctx cosmossdktypes.Context, id string) (github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage, bool) { if mock.GetMessageFunc == nil { @@ -1315,6 +1927,38 @@ func (mock *NexusMock) GetMessageCalls() []struct { return calls } +// GetParams calls GetParamsFunc. +func (mock *NexusMock) GetParams(ctx cosmossdktypes.Context) nexustypes.Params { + if mock.GetParamsFunc == nil { + panic("NexusMock.GetParamsFunc: method is nil but Nexus.GetParams was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockGetParams.Lock() + mock.calls.GetParams = append(mock.calls.GetParams, callInfo) + mock.lockGetParams.Unlock() + return mock.GetParamsFunc(ctx) +} + +// GetParamsCalls gets all the calls that were made to GetParams. +// Check the length with: +// +// len(mockedNexus.GetParamsCalls()) +func (mock *NexusMock) GetParamsCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockGetParams.RLock() + calls = mock.calls.GetParams + mock.lockGetParams.RUnlock() + return calls +} + // GetRecipient calls GetRecipientFunc. func (mock *NexusMock) GetRecipient(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress) (github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, bool) { if mock.GetRecipientFunc == nil { @@ -1427,6 +2071,42 @@ func (mock *NexusMock) GetTransfersForChainPaginatedCalls() []struct { return calls } +// InitGenesis calls InitGenesisFunc. +func (mock *NexusMock) InitGenesis(ctx cosmossdktypes.Context, genState *nexustypes.GenesisState) { + if mock.InitGenesisFunc == nil { + panic("NexusMock.InitGenesisFunc: method is nil but Nexus.InitGenesis was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + GenState *nexustypes.GenesisState + }{ + Ctx: ctx, + GenState: genState, + } + mock.lockInitGenesis.Lock() + mock.calls.InitGenesis = append(mock.calls.InitGenesis, callInfo) + mock.lockInitGenesis.Unlock() + mock.InitGenesisFunc(ctx, genState) +} + +// InitGenesisCalls gets all the calls that were made to InitGenesis. +// Check the length with: +// +// len(mockedNexus.InitGenesisCalls()) +func (mock *NexusMock) InitGenesisCalls() []struct { + Ctx cosmossdktypes.Context + GenState *nexustypes.GenesisState +} { + var calls []struct { + Ctx cosmossdktypes.Context + GenState *nexustypes.GenesisState + } + mock.lockInitGenesis.RLock() + calls = mock.calls.InitGenesis + mock.lockInitGenesis.RUnlock() + return calls +} + // IsAssetRegistered calls IsAssetRegisteredFunc. func (mock *NexusMock) IsAssetRegistered(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, denom string) bool { if mock.IsAssetRegisteredFunc == nil { @@ -1503,6 +2183,78 @@ func (mock *NexusMock) IsChainActivatedCalls() []struct { return calls } +// IsChainMaintainer calls IsChainMaintainerFunc. +func (mock *NexusMock) IsChainMaintainer(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, maintainer cosmossdktypes.ValAddress) bool { + if mock.IsChainMaintainerFunc == nil { + panic("NexusMock.IsChainMaintainerFunc: method is nil but Nexus.IsChainMaintainer was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Maintainer cosmossdktypes.ValAddress + }{ + Ctx: ctx, + Chain: chain, + Maintainer: maintainer, + } + mock.lockIsChainMaintainer.Lock() + mock.calls.IsChainMaintainer = append(mock.calls.IsChainMaintainer, callInfo) + mock.lockIsChainMaintainer.Unlock() + return mock.IsChainMaintainerFunc(ctx, chain, maintainer) +} + +// IsChainMaintainerCalls gets all the calls that were made to IsChainMaintainer. +// Check the length with: +// +// len(mockedNexus.IsChainMaintainerCalls()) +func (mock *NexusMock) IsChainMaintainerCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Maintainer cosmossdktypes.ValAddress +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Maintainer cosmossdktypes.ValAddress + } + mock.lockIsChainMaintainer.RLock() + calls = mock.calls.IsChainMaintainer + mock.lockIsChainMaintainer.RUnlock() + return calls +} + +// IsWasmConnectionActivated calls IsWasmConnectionActivatedFunc. +func (mock *NexusMock) IsWasmConnectionActivated(ctx cosmossdktypes.Context) bool { + if mock.IsWasmConnectionActivatedFunc == nil { + panic("NexusMock.IsWasmConnectionActivatedFunc: method is nil but Nexus.IsWasmConnectionActivated was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockIsWasmConnectionActivated.Lock() + mock.calls.IsWasmConnectionActivated = append(mock.calls.IsWasmConnectionActivated, callInfo) + mock.lockIsWasmConnectionActivated.Unlock() + return mock.IsWasmConnectionActivatedFunc(ctx) +} + +// IsWasmConnectionActivatedCalls gets all the calls that were made to IsWasmConnectionActivated. +// Check the length with: +// +// len(mockedNexus.IsWasmConnectionActivatedCalls()) +func (mock *NexusMock) IsWasmConnectionActivatedCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockIsWasmConnectionActivated.RLock() + calls = mock.calls.IsWasmConnectionActivated + mock.lockIsWasmConnectionActivated.RUnlock() + return calls +} + // LinkAddresses calls LinkAddressesFunc. func (mock *NexusMock) LinkAddresses(ctx cosmossdktypes.Context, sender github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, recipient github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress) error { if mock.LinkAddressesFunc == nil { @@ -1543,6 +2295,38 @@ func (mock *NexusMock) LinkAddressesCalls() []struct { return calls } +// Logger calls LoggerFunc. +func (mock *NexusMock) Logger(ctx cosmossdktypes.Context) log.Logger { + if mock.LoggerFunc == nil { + panic("NexusMock.LoggerFunc: method is nil but Nexus.Logger was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + }{ + Ctx: ctx, + } + mock.lockLogger.Lock() + mock.calls.Logger = append(mock.calls.Logger, callInfo) + mock.lockLogger.Unlock() + return mock.LoggerFunc(ctx) +} + +// LoggerCalls gets all the calls that were made to Logger. +// Check the length with: +// +// len(mockedNexus.LoggerCalls()) +func (mock *NexusMock) LoggerCalls() []struct { + Ctx cosmossdktypes.Context +} { + var calls []struct { + Ctx cosmossdktypes.Context + } + mock.lockLogger.RLock() + calls = mock.calls.Logger + mock.lockLogger.RUnlock() + return calls +} + // RateLimitTransfer calls RateLimitTransferFunc. func (mock *NexusMock) RateLimitTransfer(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, asset cosmossdktypes.Coin, direction github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferDirection) error { if mock.RateLimitTransferFunc == nil { @@ -1635,6 +2419,86 @@ func (mock *NexusMock) RegisterAssetCalls() []struct { return calls } +// RegisterFee calls RegisterFeeFunc. +func (mock *NexusMock) RegisterFee(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, feeInfo github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo) error { + if mock.RegisterFeeFunc == nil { + panic("NexusMock.RegisterFeeFunc: method is nil but Nexus.RegisterFee was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + FeeInfo github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo + }{ + Ctx: ctx, + Chain: chain, + FeeInfo: feeInfo, + } + mock.lockRegisterFee.Lock() + mock.calls.RegisterFee = append(mock.calls.RegisterFee, callInfo) + mock.lockRegisterFee.Unlock() + return mock.RegisterFeeFunc(ctx, chain, feeInfo) +} + +// RegisterFeeCalls gets all the calls that were made to RegisterFee. +// Check the length with: +// +// len(mockedNexus.RegisterFeeCalls()) +func (mock *NexusMock) RegisterFeeCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + FeeInfo github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + FeeInfo github_com_axelarnetwork_axelar_core_x_nexus_exported.FeeInfo + } + mock.lockRegisterFee.RLock() + calls = mock.calls.RegisterFee + mock.lockRegisterFee.RUnlock() + return calls +} + +// RemoveChainMaintainer calls RemoveChainMaintainerFunc. +func (mock *NexusMock) RemoveChainMaintainer(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain, validator cosmossdktypes.ValAddress) error { + if mock.RemoveChainMaintainerFunc == nil { + panic("NexusMock.RemoveChainMaintainerFunc: method is nil but Nexus.RemoveChainMaintainer was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Validator cosmossdktypes.ValAddress + }{ + Ctx: ctx, + Chain: chain, + Validator: validator, + } + mock.lockRemoveChainMaintainer.Lock() + mock.calls.RemoveChainMaintainer = append(mock.calls.RemoveChainMaintainer, callInfo) + mock.lockRemoveChainMaintainer.Unlock() + return mock.RemoveChainMaintainerFunc(ctx, chain, validator) +} + +// RemoveChainMaintainerCalls gets all the calls that were made to RemoveChainMaintainer. +// Check the length with: +// +// len(mockedNexus.RemoveChainMaintainerCalls()) +func (mock *NexusMock) RemoveChainMaintainerCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Validator cosmossdktypes.ValAddress +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.Chain + Validator cosmossdktypes.ValAddress + } + mock.lockRemoveChainMaintainer.RLock() + calls = mock.calls.RemoveChainMaintainer + mock.lockRemoveChainMaintainer.RUnlock() + return calls +} + // RouteMessage calls RouteMessageFunc. func (mock *NexusMock) RouteMessage(ctx cosmossdktypes.Context, id string, routingCtx ...github_com_axelarnetwork_axelar_core_x_nexus_exported.RoutingContext) error { if mock.RouteMessageFunc == nil { @@ -1784,21 +2648,21 @@ func (mock *NexusMock) SetMessageFailedCalls() []struct { } // SetNewMessage calls SetNewMessageFunc. -func (mock *NexusMock) SetNewMessage(ctx cosmossdktypes.Context, m github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage) error { +func (mock *NexusMock) SetNewMessage(ctx cosmossdktypes.Context, msg github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage) error { if mock.SetNewMessageFunc == nil { panic("NexusMock.SetNewMessageFunc: method is nil but Nexus.SetNewMessage was just called") } callInfo := struct { Ctx cosmossdktypes.Context - M github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage + Msg github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage }{ Ctx: ctx, - M: m, + Msg: msg, } mock.lockSetNewMessage.Lock() mock.calls.SetNewMessage = append(mock.calls.SetNewMessage, callInfo) mock.lockSetNewMessage.Unlock() - return mock.SetNewMessageFunc(ctx, m) + return mock.SetNewMessageFunc(ctx, msg) } // SetNewMessageCalls gets all the calls that were made to SetNewMessage. @@ -1807,11 +2671,11 @@ func (mock *NexusMock) SetNewMessage(ctx cosmossdktypes.Context, m github_com_ax // len(mockedNexus.SetNewMessageCalls()) func (mock *NexusMock) SetNewMessageCalls() []struct { Ctx cosmossdktypes.Context - M github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage + Msg github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage } { var calls []struct { Ctx cosmossdktypes.Context - M github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage + Msg github_com_axelarnetwork_axelar_core_x_nexus_exported.GeneralMessage } mock.lockSetNewMessage.RLock() calls = mock.calls.SetNewMessage @@ -1819,6 +2683,86 @@ func (mock *NexusMock) SetNewMessageCalls() []struct { return calls } +// SetParams calls SetParamsFunc. +func (mock *NexusMock) SetParams(ctx cosmossdktypes.Context, p nexustypes.Params) { + if mock.SetParamsFunc == nil { + panic("NexusMock.SetParamsFunc: method is nil but Nexus.SetParams was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + P nexustypes.Params + }{ + Ctx: ctx, + P: p, + } + mock.lockSetParams.Lock() + mock.calls.SetParams = append(mock.calls.SetParams, callInfo) + mock.lockSetParams.Unlock() + mock.SetParamsFunc(ctx, p) +} + +// SetParamsCalls gets all the calls that were made to SetParams. +// Check the length with: +// +// len(mockedNexus.SetParamsCalls()) +func (mock *NexusMock) SetParamsCalls() []struct { + Ctx cosmossdktypes.Context + P nexustypes.Params +} { + var calls []struct { + Ctx cosmossdktypes.Context + P nexustypes.Params + } + mock.lockSetParams.RLock() + calls = mock.calls.SetParams + mock.lockSetParams.RUnlock() + return calls +} + +// SetRateLimit calls SetRateLimitFunc. +func (mock *NexusMock) SetRateLimit(ctx cosmossdktypes.Context, chainName github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, limit cosmossdktypes.Coin, window time.Duration) error { + if mock.SetRateLimitFunc == nil { + panic("NexusMock.SetRateLimitFunc: method is nil but Nexus.SetRateLimit was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + ChainName github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + Limit cosmossdktypes.Coin + Window time.Duration + }{ + Ctx: ctx, + ChainName: chainName, + Limit: limit, + Window: window, + } + mock.lockSetRateLimit.Lock() + mock.calls.SetRateLimit = append(mock.calls.SetRateLimit, callInfo) + mock.lockSetRateLimit.Unlock() + return mock.SetRateLimitFunc(ctx, chainName, limit, window) +} + +// SetRateLimitCalls gets all the calls that were made to SetRateLimit. +// Check the length with: +// +// len(mockedNexus.SetRateLimitCalls()) +func (mock *NexusMock) SetRateLimitCalls() []struct { + Ctx cosmossdktypes.Context + ChainName github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + Limit cosmossdktypes.Coin + Window time.Duration +} { + var calls []struct { + Ctx cosmossdktypes.Context + ChainName github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + Limit cosmossdktypes.Coin + Window time.Duration + } + mock.lockSetRateLimit.RLock() + calls = mock.calls.SetRateLimit + mock.lockSetRateLimit.RUnlock() + return calls +} + // SubTransferFee calls SubTransferFeeFunc. func (mock *NexusMock) SubTransferFee(ctx cosmossdktypes.Context, coin cosmossdktypes.Coin) { if mock.SubTransferFeeFunc == nil { @@ -2993,9 +3937,6 @@ var _ axelarnettypes.AccountKeeper = &AccountKeeperMock{} // // // make and configure a mocked axelarnettypes.AccountKeeper // mockedAccountKeeper := &AccountKeeperMock{ -// GetModuleAccountFunc: func(ctx cosmossdktypes.Context, moduleName string) types.ModuleAccountI { -// panic("mock out the GetModuleAccount method") -// }, // GetModuleAddressFunc: func(moduleName string) cosmossdktypes.AccAddress { // panic("mock out the GetModuleAddress method") // }, @@ -3006,67 +3947,20 @@ var _ axelarnettypes.AccountKeeper = &AccountKeeperMock{} // // } type AccountKeeperMock struct { - // GetModuleAccountFunc mocks the GetModuleAccount method. - GetModuleAccountFunc func(ctx cosmossdktypes.Context, moduleName string) types.ModuleAccountI - // GetModuleAddressFunc mocks the GetModuleAddress method. GetModuleAddressFunc func(moduleName string) cosmossdktypes.AccAddress // calls tracks calls to the methods. calls struct { - // GetModuleAccount holds details about calls to the GetModuleAccount method. - GetModuleAccount []struct { - // Ctx is the ctx argument value. - Ctx cosmossdktypes.Context - // ModuleName is the moduleName argument value. - ModuleName string - } // GetModuleAddress holds details about calls to the GetModuleAddress method. GetModuleAddress []struct { // ModuleName is the moduleName argument value. ModuleName string } } - lockGetModuleAccount sync.RWMutex lockGetModuleAddress sync.RWMutex } -// GetModuleAccount calls GetModuleAccountFunc. -func (mock *AccountKeeperMock) GetModuleAccount(ctx cosmossdktypes.Context, moduleName string) types.ModuleAccountI { - if mock.GetModuleAccountFunc == nil { - panic("AccountKeeperMock.GetModuleAccountFunc: method is nil but AccountKeeper.GetModuleAccount was just called") - } - callInfo := struct { - Ctx cosmossdktypes.Context - ModuleName string - }{ - Ctx: ctx, - ModuleName: moduleName, - } - mock.lockGetModuleAccount.Lock() - mock.calls.GetModuleAccount = append(mock.calls.GetModuleAccount, callInfo) - mock.lockGetModuleAccount.Unlock() - return mock.GetModuleAccountFunc(ctx, moduleName) -} - -// GetModuleAccountCalls gets all the calls that were made to GetModuleAccount. -// Check the length with: -// -// len(mockedAccountKeeper.GetModuleAccountCalls()) -func (mock *AccountKeeperMock) GetModuleAccountCalls() []struct { - Ctx cosmossdktypes.Context - ModuleName string -} { - var calls []struct { - Ctx cosmossdktypes.Context - ModuleName string - } - mock.lockGetModuleAccount.RLock() - calls = mock.calls.GetModuleAccount - mock.lockGetModuleAccount.RUnlock() - return calls -} - // GetModuleAddress calls GetModuleAddressFunc. func (mock *AccountKeeperMock) GetModuleAddress(moduleName string) cosmossdktypes.AccAddress { if mock.GetModuleAddressFunc == nil { @@ -3409,6 +4303,12 @@ var _ axelarnettypes.IBCKeeper = &IBCKeeperMock{} // // // make and configure a mocked axelarnettypes.IBCKeeper // mockedIBCKeeper := &IBCKeeperMock{ +// GetIBCPathFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (string, bool) { +// panic("mock out the GetIBCPath method") +// }, +// ParseIBCDenomFunc: func(ctx cosmossdktypes.Context, ibcDenom string) (ibctransfertypes.DenomTrace, error) { +// panic("mock out the ParseIBCDenom method") +// }, // SendMessageFunc: func(c context.Context, recipient github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, asset cosmossdktypes.Coin, payload string, id string) error { // panic("mock out the SendMessage method") // }, @@ -3419,11 +4319,31 @@ var _ axelarnettypes.IBCKeeper = &IBCKeeperMock{} // // } type IBCKeeperMock struct { + // GetIBCPathFunc mocks the GetIBCPath method. + GetIBCPathFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (string, bool) + + // ParseIBCDenomFunc mocks the ParseIBCDenom method. + ParseIBCDenomFunc func(ctx cosmossdktypes.Context, ibcDenom string) (ibctransfertypes.DenomTrace, error) + // SendMessageFunc mocks the SendMessage method. SendMessageFunc func(c context.Context, recipient github_com_axelarnetwork_axelar_core_x_nexus_exported.CrossChainAddress, asset cosmossdktypes.Coin, payload string, id string) error // calls tracks calls to the methods. calls struct { + // GetIBCPath holds details about calls to the GetIBCPath method. + GetIBCPath []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Chain is the chain argument value. + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + } + // ParseIBCDenom holds details about calls to the ParseIBCDenom method. + ParseIBCDenom []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // IbcDenom is the ibcDenom argument value. + IbcDenom string + } // SendMessage holds details about calls to the SendMessage method. SendMessage []struct { // C is the c argument value. @@ -3438,7 +4358,81 @@ type IBCKeeperMock struct { ID string } } - lockSendMessage sync.RWMutex + lockGetIBCPath sync.RWMutex + lockParseIBCDenom sync.RWMutex + lockSendMessage sync.RWMutex +} + +// GetIBCPath calls GetIBCPathFunc. +func (mock *IBCKeeperMock) GetIBCPath(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName) (string, bool) { + if mock.GetIBCPathFunc == nil { + panic("IBCKeeperMock.GetIBCPathFunc: method is nil but IBCKeeper.GetIBCPath was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + }{ + Ctx: ctx, + Chain: chain, + } + mock.lockGetIBCPath.Lock() + mock.calls.GetIBCPath = append(mock.calls.GetIBCPath, callInfo) + mock.lockGetIBCPath.Unlock() + return mock.GetIBCPathFunc(ctx, chain) +} + +// GetIBCPathCalls gets all the calls that were made to GetIBCPath. +// Check the length with: +// +// len(mockedIBCKeeper.GetIBCPathCalls()) +func (mock *IBCKeeperMock) GetIBCPathCalls() []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName +} { + var calls []struct { + Ctx cosmossdktypes.Context + Chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName + } + mock.lockGetIBCPath.RLock() + calls = mock.calls.GetIBCPath + mock.lockGetIBCPath.RUnlock() + return calls +} + +// ParseIBCDenom calls ParseIBCDenomFunc. +func (mock *IBCKeeperMock) ParseIBCDenom(ctx cosmossdktypes.Context, ibcDenom string) (ibctransfertypes.DenomTrace, error) { + if mock.ParseIBCDenomFunc == nil { + panic("IBCKeeperMock.ParseIBCDenomFunc: method is nil but IBCKeeper.ParseIBCDenom was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + IbcDenom string + }{ + Ctx: ctx, + IbcDenom: ibcDenom, + } + mock.lockParseIBCDenom.Lock() + mock.calls.ParseIBCDenom = append(mock.calls.ParseIBCDenom, callInfo) + mock.lockParseIBCDenom.Unlock() + return mock.ParseIBCDenomFunc(ctx, ibcDenom) +} + +// ParseIBCDenomCalls gets all the calls that were made to ParseIBCDenom. +// Check the length with: +// +// len(mockedIBCKeeper.ParseIBCDenomCalls()) +func (mock *IBCKeeperMock) ParseIBCDenomCalls() []struct { + Ctx cosmossdktypes.Context + IbcDenom string +} { + var calls []struct { + Ctx cosmossdktypes.Context + IbcDenom string + } + mock.lockParseIBCDenom.RLock() + calls = mock.calls.ParseIBCDenom + mock.lockParseIBCDenom.RUnlock() + return calls } // SendMessage calls SendMessageFunc. From 92df5703a56a979b9cf9b5f5ccaa6e449db7d6f4 Mon Sep 17 00:00:00 2001 From: Sammy Date: Tue, 24 Sep 2024 03:04:06 -0400 Subject: [PATCH 03/11] fix tests and linting --- x/axelarnet/abci_test.go | 3 +- x/axelarnet/keeper/grpc_query_test.go | 3 +- x/axelarnet/keeper/ibc_transfer.go | 2 +- x/axelarnet/keeper/message_route.go | 4 +- x/axelarnet/keeper/message_route_test.go | 20 ++++----- x/axelarnet/keeper/msg_server.go | 4 +- x/axelarnet/keeper/msg_server_test.go | 29 ++++-------- x/axelarnet/message_handler.go | 14 +++--- x/axelarnet/message_handler_test.go | 14 +++--- x/axelarnet/module.go | 7 ++- x/axelarnet/types/expected_keepers.go | 2 + x/axelarnet/types/mock/expected_keepers.go | 51 ++++++++++++++++++++++ x/axelarnet/types/types.go | 10 +---- x/nexus/exported/types.go | 9 ++++ x/nexus/types/coin.go | 5 ++- x/nexus/types/types.go | 9 ---- 16 files changed, 109 insertions(+), 77 deletions(-) diff --git a/x/axelarnet/abci_test.go b/x/axelarnet/abci_test.go index 932033f71..7a4cc699b 100644 --- a/x/axelarnet/abci_test.go +++ b/x/axelarnet/abci_test.go @@ -23,7 +23,6 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/keeper" "github.com/axelarnetwork/axelar-core/x/axelarnet/types" "github.com/axelarnetwork/axelar-core/x/axelarnet/types/mock" - "github.com/axelarnetwork/axelar-core/x/axelarnet/types/testutils" axelartestutils "github.com/axelarnetwork/axelar-core/x/axelarnet/types/testutils" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" "github.com/axelarnetwork/utils/math" @@ -108,7 +107,7 @@ func TestEndBlocker(t *testing.T) { return false } - transfer := testutils.RandomIBCTransfer() + transfer := axelartestutils.RandomIBCTransfer() bz, _ := transfer.Marshal() if err := value.Unmarshal(bz); err != nil { panic(err) diff --git a/x/axelarnet/keeper/grpc_query_test.go b/x/axelarnet/keeper/grpc_query_test.go index a99f6803c..3db031cd2 100644 --- a/x/axelarnet/keeper/grpc_query_test.go +++ b/x/axelarnet/keeper/grpc_query_test.go @@ -8,7 +8,6 @@ import ( "github.com/cosmos/cosmos-sdk/types/query" "github.com/stretchr/testify/assert" "github.com/tendermint/tendermint/libs/log" - abci "github.com/tendermint/tendermint/proto/tendermint/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/axelarnetwork/axelar-core/testutils/fake" @@ -58,7 +57,7 @@ func TestQuerier_PendingIBCTransferCount(t *testing.T) { querier = keeper.NewGRPCQuerier(k, n) }). When("IBC transfer counts are queried", func() { - ctx := sdk.NewContext(fake.NewMultiStore(), abci.Header{}, false, log.TestingLogger()) + ctx := sdk.NewContext(fake.NewMultiStore(), tmproto.Header{}, false, log.TestingLogger()) var err error response, err = querier.PendingIBCTransferCount(sdk.WrapSDKContext(ctx), &types.PendingIBCTransferCountRequest{}) assert.NoError(t, err) diff --git a/x/axelarnet/keeper/ibc_transfer.go b/x/axelarnet/keeper/ibc_transfer.go index 08adfabcf..b4a36e8ee 100644 --- a/x/axelarnet/keeper/ibc_transfer.go +++ b/x/axelarnet/keeper/ibc_transfer.go @@ -75,7 +75,7 @@ func (i IBCKeeper) SendMessage(c context.Context, recipient nexus.CrossChainAddr return err } - msg := ibctypes.NewMsgTransfer(portID, channelID, asset, types.AxelarGMPAccount.String(), recipient.Address, height, 0) + msg := ibctypes.NewMsgTransfer(portID, channelID, asset, types.AxelarIBCAccount.String(), recipient.Address, height, 0) msg.Memo = payload res, err := i.ibcTransferK.Transfer(c, msg) diff --git a/x/axelarnet/keeper/message_route.go b/x/axelarnet/keeper/message_route.go index fc496ad73..e66a19bb1 100644 --- a/x/axelarnet/keeper/message_route.go +++ b/x/axelarnet/keeper/message_route.go @@ -76,14 +76,14 @@ func escrowAssetToMessageSender( sender = routingCtx.FeeGranter } - return asset, bankK.SendCoins(ctx, sender, types.AxelarGMPAccount, sdk.NewCoins(asset)) + return asset, bankK.SendCoins(ctx, sender, types.AxelarIBCAccount, sdk.NewCoins(asset)) case nexus.TypeGeneralMessageWithToken: coin, err := nexustypes.NewCoin(ctx, nexusK, ibcK, bankK, *msg.Asset) if err != nil { return sdk.Coin{}, err } - return coin.GetOriginalCoin(ctx), coin.Unlock(ctx, types.AxelarGMPAccount) + return coin.GetOriginalCoin(ctx), coin.Unlock(ctx, types.AxelarIBCAccount) default: return sdk.Coin{}, fmt.Errorf("unrecognized message type") } diff --git a/x/axelarnet/keeper/message_route_test.go b/x/axelarnet/keeper/message_route_test.go index 6448f5454..3c0346e90 100644 --- a/x/axelarnet/keeper/message_route_test.go +++ b/x/axelarnet/keeper/message_route_test.go @@ -2,6 +2,7 @@ package keeper_test import ( "context" + "crypto/sha256" "testing" sdk "github.com/cosmos/cosmos-sdk/types" @@ -53,6 +54,8 @@ func randMsg(status nexus.GeneralMessage_Status, payload []byte, token ...*sdk.C asset = token[0] } + payloadHash := sha256.Sum256(payload) + return nexus.GeneralMessage{ ID: rand.NormalizedStr(10), Sender: nexus.CrossChainAddress{ @@ -63,7 +66,7 @@ func randMsg(status nexus.GeneralMessage_Status, payload []byte, token ...*sdk.C Chain: nexustestutils.RandomChain(), Address: rand.NormalizedStr(42), }, - PayloadHash: evmtestutils.RandomHash().Bytes(), + PayloadHash: payloadHash[:], Status: status, Asset: asset, SourceTxID: evmtestutils.RandomHash().Bytes(), @@ -78,28 +81,25 @@ func TestNewMessageRoute(t *testing.T) { msg nexus.GeneralMessage route nexus.MessageRoute - k keeper.Keeper feegrantK *mock.FeegrantKeeperMock ibcK *mock.IBCKeeperMock bankK *mock.BankKeeperMock nexusK *mock.NexusMock - accountK *mock.AccountKeeperMock stakingK *mock.StakingKeeperMock ) givenMessageRoute := Given("the message route", func() { - ctx, k, _, feegrantK = setup() + ctx, _, _, feegrantK = setup() ibcK = &mock.IBCKeeperMock{} bankK = &mock.BankKeeperMock{} nexusK = &mock.NexusMock{} - accountK = &mock.AccountKeeperMock{} stakingK = &mock.StakingKeeperMock{} stakingK.BondDenomFunc = func(ctx sdk.Context) string { return exported.NativeAsset } - route = keeper.NewMessageRoute(k, ibcK, feegrantK, bankK, nexusK, accountK, stakingK) + route = keeper.NewMessageRoute(ibcK, feegrantK, bankK, nexusK, stakingK) }) givenMessageRoute. @@ -151,7 +151,7 @@ func TestNewMessageRoute(t *testing.T) { assert.Len(t, bankK.SendCoinsCalls(), 1) assert.Equal(t, routingCtx.Sender, bankK.SendCoinsCalls()[0].FromAddr) - assert.Equal(t, types.AxelarGMPAccount, bankK.SendCoinsCalls()[0].ToAddr) + assert.Equal(t, types.AxelarIBCAccount, bankK.SendCoinsCalls()[0].ToAddr) assert.Equal(t, sdk.NewCoins(sdk.NewCoin(exported.NativeAsset, sdk.OneInt())), bankK.SendCoinsCalls()[0].Amt) assert.Len(t, ibcK.SendMessageCalls(), 1) @@ -181,7 +181,7 @@ func TestNewMessageRoute(t *testing.T) { assert.Len(t, bankK.SendCoinsCalls(), 1) assert.Equal(t, routingCtx.FeeGranter, bankK.SendCoinsCalls()[0].FromAddr) - assert.Equal(t, types.AxelarGMPAccount, bankK.SendCoinsCalls()[0].ToAddr) + assert.Equal(t, types.AxelarIBCAccount, bankK.SendCoinsCalls()[0].ToAddr) assert.Equal(t, sdk.NewCoins(sdk.NewCoin(exported.NativeAsset, sdk.OneInt())), bankK.SendCoinsCalls()[0].Amt) assert.Len(t, ibcK.SendMessageCalls(), 1) @@ -210,8 +210,8 @@ func TestNewMessageRoute(t *testing.T) { assert.NoError(t, route(ctx, routingCtx, msg)) assert.Len(t, bankK.SendCoinsCalls(), 1) - assert.Equal(t, types.GetEscrowAddress(msg.Asset.Denom), bankK.SendCoinsCalls()[0].FromAddr) - assert.Equal(t, types.AxelarGMPAccount, bankK.SendCoinsCalls()[0].ToAddr) + assert.Equal(t, nexus.GetEscrowAddress(msg.Asset.Denom), bankK.SendCoinsCalls()[0].FromAddr) + assert.Equal(t, types.AxelarIBCAccount, bankK.SendCoinsCalls()[0].ToAddr) assert.Equal(t, sdk.NewCoins(*msg.Asset), bankK.SendCoinsCalls()[0].Amt) assert.Len(t, ibcK.SendMessageCalls(), 1) diff --git a/x/axelarnet/keeper/msg_server.go b/x/axelarnet/keeper/msg_server.go index 3b0fa43da..50f891860 100644 --- a/x/axelarnet/keeper/msg_server.go +++ b/x/axelarnet/keeper/msg_server.go @@ -410,12 +410,12 @@ func (s msgServer) RouteIBCTransfers(c context.Context, _ *types.RouteIBCTransfe continue } - if err := coin.Unlock(ctx, types.AxelarGMPAccount); err != nil { + if err := coin.Unlock(ctx, types.AxelarIBCAccount); err != nil { s.Logger(ctx).Error(fmt.Sprintf("failed to route IBC transfer %s: %s", p.String(), err)) continue } - funcs.MustNoErr(s.EnqueueIBCTransfer(ctx, types.NewIBCTransfer(types.AxelarGMPAccount, p.Recipient.Address, coin.GetOriginalCoin(ctx), portID, channelID, p.ID))) + funcs.MustNoErr(s.EnqueueIBCTransfer(ctx, types.NewIBCTransfer(types.AxelarIBCAccount, p.Recipient.Address, coin.GetOriginalCoin(ctx), portID, channelID, p.ID))) s.nexus.ArchivePendingTransfer(ctx, p) } } diff --git a/x/axelarnet/keeper/msg_server_test.go b/x/axelarnet/keeper/msg_server_test.go index 878c809ad..b37798c43 100644 --- a/x/axelarnet/keeper/msg_server_test.go +++ b/x/axelarnet/keeper/msg_server_test.go @@ -48,7 +48,7 @@ func TestHandleMsgLink(t *testing.T) { k.InitGenesis(ctx, types.DefaultGenesisState()) nexusK = &mock.NexusMock{} ibcK := keeper.NewIBCKeeper(k, &mock.IBCTransferKeeperMock{}) - server = keeper.NewMsgServerImpl(k, nexusK, &mock.BankKeeperMock{}, &mock.AccountKeeperMock{}, ibcK) + server = keeper.NewMsgServerImpl(k, nexusK, &mock.BankKeeperMock{}, ibcK) }) whenChainIsRegistered := When("chain is registered", func() { @@ -154,7 +154,7 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { }, } ibcK := keeper.NewIBCKeeper(k, transferK) - server = keeper.NewMsgServerImpl(k, nexusK, bankK, &mock.AccountKeeperMock{}, ibcK) + server = keeper.NewMsgServerImpl(k, nexusK, bankK, ibcK) }) recipientIsFound := When("recipient is found", func() { @@ -387,13 +387,8 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { } bankK = &mock.BankKeeperMock{} transferK = &mock.IBCTransferKeeperMock{} - accountK := &mock.AccountKeeperMock{ - GetModuleAddressFunc: func(moduleName string) sdk.AccAddress { - return rand.AccAddr() - }, - } ibcK := keeper.NewIBCKeeper(k, transferK) - server = keeper.NewMsgServerImpl(k, nexusK, bankK, accountK, ibcK) + server = keeper.NewMsgServerImpl(k, nexusK, bankK, ibcK) }) whenAssetOriginsFromExternalCosmosChain := When("asset is from external cosmos chain", func() { @@ -595,13 +590,8 @@ func TestHandleMsgRouteIBCTransfers(t *testing.T) { } bankK = &mock.BankKeeperMock{} transferK = &mock.IBCTransferKeeperMock{} - accountK := &mock.AccountKeeperMock{ - GetModuleAddressFunc: func(string) sdk.AccAddress { - return rand.AccAddr() - }, - } ibcK := keeper.NewIBCKeeper(k, transferK) - server = keeper.NewMsgServerImpl(k, nexusK, bankK, accountK, ibcK) + server = keeper.NewMsgServerImpl(k, nexusK, bankK, ibcK) }) whenAssetOriginsFromExternalCosmosChain := When("asset is from external cosmos chain", func() { @@ -726,7 +716,6 @@ func TestRetryIBCTransfer(t *testing.T) { n *mock.NexusMock b *mock.BankKeeperMock i *mock.IBCTransferKeeperMock - a *mock.AccountKeeperMock channelK *mock.ChannelKeeperMock ctx sdk.Context chain nexus.Chain @@ -750,7 +739,6 @@ func TestRetryIBCTransfer(t *testing.T) { funcs.MustNoErr(k.SetChainByIBCPath(ctx, path, cosmosChain.Name)) b = &mock.BankKeeperMock{} - a = &mock.AccountKeeperMock{} i = &mock.IBCTransferKeeperMock{ SendTransferFunc: func(sdk.Context, string, string, sdk.Coin, sdk.AccAddress, string, clienttypes.Height, uint64) error { return nil @@ -774,7 +762,7 @@ func TestRetryIBCTransfer(t *testing.T) { } ibcK := keeper.NewIBCKeeper(k, i) - server = keeper.NewMsgServerImpl(k, n, b, a, ibcK) + server = keeper.NewMsgServerImpl(k, n, b, ibcK) }) requestIsMade := When("a retry failed transfer request is made", func() { @@ -858,7 +846,7 @@ func TestAddCosmosBasedChain(t *testing.T) { }, } ibcK := keeper.NewIBCKeeper(k, &mock.IBCTransferKeeperMock{}) - server = keeper.NewMsgServerImpl(k, nexusK, &mock.BankKeeperMock{}, &mock.AccountKeeperMock{}, ibcK) + server = keeper.NewMsgServerImpl(k, nexusK, &mock.BankKeeperMock{}, ibcK) }) addChainRequest := When("an add cosmos based chain request is created", func() { @@ -984,8 +972,7 @@ func TestRouteMessage(t *testing.T) { nexusK = &mock.NexusMock{} ibcK := keeper.NewIBCKeeper(k, &mock.IBCTransferKeeperMock{}) bankK := &mock.BankKeeperMock{} - accountK := &mock.AccountKeeperMock{} - server = keeper.NewMsgServerImpl(k, nexusK, bankK, accountK, ibcK) + server = keeper.NewMsgServerImpl(k, nexusK, bankK, ibcK) }) givenMsgServer. @@ -1022,7 +1009,7 @@ func TestHandleCallContract(t *testing.T) { nexusK = &mock.NexusMock{} ibcK := keeper.NewIBCKeeper(k, &mock.IBCTransferKeeperMock{}) b = &mock.BankKeeperMock{} - server = keeper.NewMsgServerImpl(k, nexusK, b, &mock.AccountKeeperMock{}, ibcK) + server = keeper.NewMsgServerImpl(k, nexusK, b, ibcK) count := 0 nexusK.GenerateMessageIDFunc = func(ctx sdk.Context) (string, []byte, uint64) { count++ diff --git a/x/axelarnet/message_handler.go b/x/axelarnet/message_handler.go index 7050aed99..5211c1ad4 100644 --- a/x/axelarnet/message_handler.go +++ b/x/axelarnet/message_handler.go @@ -112,7 +112,7 @@ func OnRecvMessage(ctx sdk.Context, k keeper.Keeper, ibcK keeper.IBCKeeper, n ty } // Skip if packet not sent to Axelar message sender account. - if data.GetReceiver() != types.AxelarGMPAccount.String() { + if data.GetReceiver() != types.AxelarIBCAccount.String() { // Rate limit non-GMP IBC transfers // IBC receives are rate limited on the from direction (tokens coming from the source chain). if err := r.RateLimitPacket(ctx, packet, nexus.TransferDirectionFrom, types.NewIBCPath(packet.GetDestPort(), packet.GetDestChannel())); err != nil { @@ -160,7 +160,7 @@ func OnRecvMessage(ctx sdk.Context, k keeper.Keeper, ibcK keeper.IBCKeeper, n ty case nexus.TypeSendToken: // Send token is already rate limited in nexus.EnqueueTransfer rateLimitPacket = false - err = handleTokenSent(ctx, n, b, sourceAddress, msg, token) + err = handleTokenSent(ctx, n, sourceAddress, msg, token) default: err = sdkerrors.Wrapf(types.ErrGeneralMessage, "unrecognized Message type") } @@ -293,7 +293,7 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, return err } - if err = token.Lock(ctx, types.AxelarGMPAccount); err != nil { + if err = token.Lock(ctx, types.AxelarIBCAccount); err != nil { return err } @@ -323,11 +323,11 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, return n.SetNewMessage(ctx, m) } -func handleTokenSent(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexustypes.Coin) error { +func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossChainAddress, msg Message, token nexustypes.Coin) error { destChain := funcs.MustOk(n.GetChain(ctx, nexus.ChainName(msg.DestinationChain))) crossChainAddr := nexus.CrossChainAddress{Chain: destChain, Address: msg.DestinationAddress} - if err := token.Lock(ctx, types.AxelarGMPAccount); err != nil { + if err := token.Lock(ctx, types.AxelarIBCAccount); err != nil { return err } @@ -416,12 +416,12 @@ func deductFee(ctx sdk.Context, b types.BankKeeper, fee *Fee, token nexustypes.C // subtract fee from transfer value token.Amount = token.Amount.Sub(feeAmount) - return token, b.SendCoins(ctx, types.AxelarGMPAccount, recipient, sdk.NewCoins(coin)) + return token, b.SendCoins(ctx, types.AxelarIBCAccount, recipient, sdk.NewCoins(coin)) } // validateReceiver rejects uppercase GMP account address func validateReceiver(receiver string) error { - if strings.ToUpper(receiver) == receiver && types.AxelarGMPAccount.Equals(funcs.Must(sdk.AccAddressFromBech32(receiver))) { + if strings.ToUpper(receiver) == receiver && types.AxelarIBCAccount.Equals(funcs.Must(sdk.AccAddressFromBech32(receiver))) { return fmt.Errorf("uppercase GMP account address is not allowed") } diff --git a/x/axelarnet/message_handler_test.go b/x/axelarnet/message_handler_test.go index 601f4c772..b93d6ab2e 100644 --- a/x/axelarnet/message_handler_test.go +++ b/x/axelarnet/message_handler_test.go @@ -168,7 +168,7 @@ func TestHandleMessage(t *testing.T) { whenPacketReceiverIsGMPAccount := givenPacketWithMessage. When("receiver is gmp account", func() { ics20Packet = ibctransfertypes.NewFungibleTokenPacketData( - rand.Denom(5, 10), strconv.FormatInt(rand.PosI64(), 10), rand.AccAddr().String(), types.AxelarGMPAccount.String(), + rand.Denom(5, 10), strconv.FormatInt(rand.PosI64(), 10), rand.AccAddr().String(), types.AxelarIBCAccount.String(), ) ics20Packet.Memo = string(funcs.Must(json.Marshal(message))) packet = axelartestutils.RandomPacket(ics20Packet, ibctransfertypes.PortID, sourceChannel, ibctransfertypes.PortID, receiverChannel) @@ -462,7 +462,7 @@ func TestHandleMessageWithToken(t *testing.T) { denom = rand.Denom(5, 10) amount = strconv.FormatInt(rand.PosI64(), 10) ics20Packet = ibctransfertypes.NewFungibleTokenPacketData( - denom, amount, rand.AccAddr().String(), types.AxelarGMPAccount.String(), + denom, amount, rand.AccAddr().String(), types.AxelarIBCAccount.String(), ) ics20Packet.Memo = string(funcs.Must(json.Marshal(message))) packet = axelartestutils.RandomPacket(ics20Packet, ibctransfertypes.PortID, sourceChannel, ibctransfertypes.PortID, receiverChannel) @@ -527,7 +527,7 @@ func TestHandleMessageWithToken(t *testing.T) { }) b = &mock.BankKeeperMock{ SpendableBalanceFunc: func(ctx sdk.Context, addr sdk.AccAddress, d string) sdk.Coin { - if addr.Equals(types.AxelarGMPAccount) { + if addr.Equals(types.AxelarIBCAccount) { return sdk.NewCoin(d, funcs.MustOk(sdk.NewIntFromString(amount)).Sub(feeAmount)) } return sdk.NewCoin(d, sdk.ZeroInt()) @@ -678,7 +678,7 @@ func TestHandleSendToken(t *testing.T) { denom = rand.Denom(5, 10) amount = strconv.FormatInt(rand.PosI64(), 10) ics20Packet = ibctransfertypes.NewFungibleTokenPacketData( - denom, amount, rand.AccAddr().String(), types.AxelarGMPAccount.String(), + denom, amount, rand.AccAddr().String(), types.AxelarIBCAccount.String(), ) ics20Packet.Memo = string(funcs.Must(json.Marshal(message))) packet = axelartestutils.RandomPacket(ics20Packet, ibctransfertypes.PortID, sourceChannel, ibctransfertypes.PortID, receiverChannel) @@ -741,7 +741,7 @@ func TestHandleSendToken(t *testing.T) { }) b = &mock.BankKeeperMock{ SpendableBalanceFunc: func(ctx sdk.Context, addr sdk.AccAddress, d string) sdk.Coin { - if addr.Equals(types.AxelarGMPAccount) { + if addr.Equals(types.AxelarIBCAccount) { return sdk.NewCoin(d, funcs.MustOk(sdk.NewIntFromString(amount))) } return sdk.NewCoin(d, sdk.ZeroInt()) @@ -908,7 +908,7 @@ func TestTokenAndDestChainNotFound(t *testing.T) { whenPacketReceiverIsGMPWithTokenAccount := givenPacketWithMessage. When("receiver is gmp with token account", func() { ics20Packet = ibctransfertypes.NewFungibleTokenPacketData( - rand.Denom(5, 10), strconv.FormatInt(rand.PosI64(), 10), rand.AccAddr().String(), types.AxelarGMPAccount.String(), + rand.Denom(5, 10), strconv.FormatInt(rand.PosI64(), 10), rand.AccAddr().String(), types.AxelarIBCAccount.String(), ) ics20Packet.Memo = string(funcs.Must(json.Marshal(gmpWithToken))) packet = axelartestutils.RandomPacket(ics20Packet, ibctransfertypes.PortID, sourceChannel, ibctransfertypes.PortID, receiverChannel) @@ -917,7 +917,7 @@ func TestTokenAndDestChainNotFound(t *testing.T) { whenPacketReceiverIsSendTokenAccount := givenPacketWithMessage. When("receiver is send token account", func() { ics20Packet = ibctransfertypes.NewFungibleTokenPacketData( - rand.Denom(5, 10), strconv.FormatInt(rand.PosI64(), 10), rand.AccAddr().String(), types.AxelarGMPAccount.String(), + rand.Denom(5, 10), strconv.FormatInt(rand.PosI64(), 10), rand.AccAddr().String(), types.AxelarIBCAccount.String(), ) ics20Packet.Memo = string(funcs.Must(json.Marshal(sendToken))) packet = axelartestutils.RandomPacket(ics20Packet, ibctransfertypes.PortID, sourceChannel, ibctransfertypes.PortID, receiverChannel) diff --git a/x/axelarnet/module.go b/x/axelarnet/module.go index 3202c1917..d84162ea2 100644 --- a/x/axelarnet/module.go +++ b/x/axelarnet/module.go @@ -343,13 +343,12 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed cross chain transfer transferID, ok := getSeqIDMapping(ctx, m.keeper, port, channel, sequence) if ok { - transfer := funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)) - coin, err := nexustypes.NewCoin(ctx, m.nexus, m.ibcK, m.bank, transfer.Token) + coin, err := nexustypes.NewCoin(ctx, m.nexus, m.ibcK, m.bank, funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)).Token) if err != nil { return err } - err = coin.Lock(ctx, types.AxelarGMPAccount) + err = coin.Lock(ctx, types.AxelarIBCAccount) if err != nil { return err } @@ -375,7 +374,7 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe return err } - err = coin.Lock(ctx, types.AxelarGMPAccount) + err = coin.Lock(ctx, types.AxelarIBCAccount) if err != nil { return err } diff --git a/x/axelarnet/types/expected_keepers.go b/x/axelarnet/types/expected_keepers.go index 8d3fcf469..c13a9cdf7 100644 --- a/x/axelarnet/types/expected_keepers.go +++ b/x/axelarnet/types/expected_keepers.go @@ -6,6 +6,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" govtypes "github.com/cosmos/cosmos-sdk/x/gov/types" ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" @@ -129,6 +130,7 @@ type ChannelKeeper interface { // creating a x/bank keeper. type AccountKeeper interface { GetModuleAddress(moduleName string) sdk.AccAddress + GetModuleAccount(ctx sdk.Context, name string) authtypes.ModuleAccountI } // CosmosChainGetter exposes GetCosmosChainByName diff --git a/x/axelarnet/types/mock/expected_keepers.go b/x/axelarnet/types/mock/expected_keepers.go index 21acd9ecc..760e6cecc 100644 --- a/x/axelarnet/types/mock/expected_keepers.go +++ b/x/axelarnet/types/mock/expected_keepers.go @@ -11,6 +11,7 @@ import ( nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" cosmossdktypes "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" gov "github.com/cosmos/cosmos-sdk/x/gov/types" ibctransfertypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" @@ -3937,6 +3938,9 @@ var _ axelarnettypes.AccountKeeper = &AccountKeeperMock{} // // // make and configure a mocked axelarnettypes.AccountKeeper // mockedAccountKeeper := &AccountKeeperMock{ +// GetModuleAccountFunc: func(ctx cosmossdktypes.Context, name string) authtypes.ModuleAccountI { +// panic("mock out the GetModuleAccount method") +// }, // GetModuleAddressFunc: func(moduleName string) cosmossdktypes.AccAddress { // panic("mock out the GetModuleAddress method") // }, @@ -3947,20 +3951,67 @@ var _ axelarnettypes.AccountKeeper = &AccountKeeperMock{} // // } type AccountKeeperMock struct { + // GetModuleAccountFunc mocks the GetModuleAccount method. + GetModuleAccountFunc func(ctx cosmossdktypes.Context, name string) authtypes.ModuleAccountI + // GetModuleAddressFunc mocks the GetModuleAddress method. GetModuleAddressFunc func(moduleName string) cosmossdktypes.AccAddress // calls tracks calls to the methods. calls struct { + // GetModuleAccount holds details about calls to the GetModuleAccount method. + GetModuleAccount []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Name is the name argument value. + Name string + } // GetModuleAddress holds details about calls to the GetModuleAddress method. GetModuleAddress []struct { // ModuleName is the moduleName argument value. ModuleName string } } + lockGetModuleAccount sync.RWMutex lockGetModuleAddress sync.RWMutex } +// GetModuleAccount calls GetModuleAccountFunc. +func (mock *AccountKeeperMock) GetModuleAccount(ctx cosmossdktypes.Context, name string) authtypes.ModuleAccountI { + if mock.GetModuleAccountFunc == nil { + panic("AccountKeeperMock.GetModuleAccountFunc: method is nil but AccountKeeper.GetModuleAccount was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Name string + }{ + Ctx: ctx, + Name: name, + } + mock.lockGetModuleAccount.Lock() + mock.calls.GetModuleAccount = append(mock.calls.GetModuleAccount, callInfo) + mock.lockGetModuleAccount.Unlock() + return mock.GetModuleAccountFunc(ctx, name) +} + +// GetModuleAccountCalls gets all the calls that were made to GetModuleAccount. +// Check the length with: +// +// len(mockedAccountKeeper.GetModuleAccountCalls()) +func (mock *AccountKeeperMock) GetModuleAccountCalls() []struct { + Ctx cosmossdktypes.Context + Name string +} { + var calls []struct { + Ctx cosmossdktypes.Context + Name string + } + mock.lockGetModuleAccount.RLock() + calls = mock.calls.GetModuleAccount + mock.lockGetModuleAccount.RUnlock() + return calls +} + // GetModuleAddress calls GetModuleAddressFunc. func (mock *AccountKeeperMock) GetModuleAddress(moduleName string) cosmossdktypes.AccAddress { if mock.GetModuleAddressFunc == nil { diff --git a/x/axelarnet/types/types.go b/x/axelarnet/types/types.go index eed4bc886..e56eee213 100644 --- a/x/axelarnet/types/types.go +++ b/x/axelarnet/types/types.go @@ -40,12 +40,6 @@ func NewLinkedAddress(ctx sdk.Context, chain nexus.ChainName, symbol, recipientA return hash[:address.Len] } -// GetEscrowAddress creates an address for an ibc denomination -func GetEscrowAddress(denom string) sdk.AccAddress { - hash := sha256.Sum256([]byte(denom)) - return hash[:address.Len] -} - // Validate checks the stateless validity of the transfer func (m IBCTransfer) Validate() error { if err := sdk.VerifyAddressFormat(m.Sender); err != nil { @@ -256,8 +250,8 @@ const ( ) var ( - // AxelarGMPAccount account is the canonical general message sender - AxelarGMPAccount = GetEscrowAddress(fmt.Sprintf("%s_%s", ModuleName, "gmp")) + // AxelarIBCAccount account is the canonical general message and IBC transfer sender + AxelarIBCAccount = nexus.GetEscrowAddress(fmt.Sprintf("%s_%s", ModuleName, "gmp")) ) // ValidateBasic returns an error if the given Fee is invalid; nil otherwise diff --git a/x/nexus/exported/types.go b/x/nexus/exported/types.go index 6a3fa9dc2..594bcfd58 100644 --- a/x/nexus/exported/types.go +++ b/x/nexus/exported/types.go @@ -1,6 +1,7 @@ package exported import ( + "crypto/sha256" "encoding/binary" "encoding/json" "fmt" @@ -9,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/address" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" @@ -425,3 +427,10 @@ type WasmQueryTxHashAndNonceResponse struct { TxHash [32]byte `json:"tx_hash,omitempty"` // the hash of the current transaction Nonce uint64 `json:"nonce,omitempty"` // the nonce of the current execution, which increments with each entry of any wasm execution } + +// GetEscrowAddress creates an address for the given denomination +func GetEscrowAddress(denom string) sdk.AccAddress { + hash := sha256.Sum256([]byte(denom)) + + return hash[:address.Len] +} diff --git a/x/nexus/types/coin.go b/x/nexus/types/coin.go index d60d4f560..63d8bdbfb 100644 --- a/x/nexus/types/coin.go +++ b/x/nexus/types/coin.go @@ -8,6 +8,7 @@ import ( ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" axelarnet "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" + "github.com/axelarnetwork/axelar-core/x/nexus/exported" "github.com/axelarnetwork/utils/funcs" ) @@ -122,11 +123,11 @@ func (c Coin) toICS20(ctx sdk.Context) (sdk.Coin, error) { } func lock(ctx sdk.Context, bank BankKeeper, fromAddr sdk.AccAddress, coin sdk.Coin) error { - return bank.SendCoins(ctx, fromAddr, GetEscrowAddress(coin.GetDenom()), sdk.NewCoins(coin)) + return bank.SendCoins(ctx, fromAddr, exported.GetEscrowAddress(coin.GetDenom()), sdk.NewCoins(coin)) } func unlock(ctx sdk.Context, bank BankKeeper, toAddr sdk.AccAddress, coin sdk.Coin) error { - return bank.SendCoins(ctx, GetEscrowAddress(coin.GetDenom()), toAddr, sdk.NewCoins(coin)) + return bank.SendCoins(ctx, exported.GetEscrowAddress(coin.GetDenom()), toAddr, sdk.NewCoins(coin)) } func burn(ctx sdk.Context, bank BankKeeper, fromAddr sdk.AccAddress, coin sdk.Coin) error { diff --git a/x/nexus/types/types.go b/x/nexus/types/types.go index 60d4ec6d3..0e7febb7f 100644 --- a/x/nexus/types/types.go +++ b/x/nexus/types/types.go @@ -1,11 +1,9 @@ package types import ( - "crypto/sha256" "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" "github.com/axelarnetwork/axelar-core/utils" @@ -204,10 +202,3 @@ const ( // External means from external chains, such as EVM chains External = 3 ) - -// GetEscrowAddress creates an address for the given denomination -func GetEscrowAddress(denom string) sdk.AccAddress { - hash := sha256.Sum256([]byte(denom)) - - return hash[:address.Len] -} From 80879a234046cb566d24294a79a0ea7ded988ce8 Mon Sep 17 00:00:00 2001 From: Sammy Date: Tue, 24 Sep 2024 14:16:38 -0400 Subject: [PATCH 04/11] move lockable coin from types to keeper package --- x/axelarnet/keeper/message_route.go | 3 +- x/axelarnet/keeper/message_route_test.go | 32 ++- x/axelarnet/keeper/msg_server.go | 13 +- x/axelarnet/message_handler.go | 52 ++-- x/axelarnet/module.go | 5 +- x/axelarnet/types/evm_translator_test.go | 9 +- x/axelarnet/types/expected_keepers.go | 1 + x/axelarnet/types/mock/expected_keepers.go | 62 +++++ x/nexus/exported/mock/types.go | 247 ++++++++++++++++++ x/nexus/exported/types.go | 10 +- .../coin.go => keeper/lockable_coin.go} | 90 ++++--- 11 files changed, 427 insertions(+), 97 deletions(-) rename x/nexus/{types/coin.go => keeper/lockable_coin.go} (58%) diff --git a/x/axelarnet/keeper/message_route.go b/x/axelarnet/keeper/message_route.go index e66a19bb1..29703975c 100644 --- a/x/axelarnet/keeper/message_route.go +++ b/x/axelarnet/keeper/message_route.go @@ -9,7 +9,6 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/types" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" - nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" ) // for IBC execution @@ -78,7 +77,7 @@ func escrowAssetToMessageSender( return asset, bankK.SendCoins(ctx, sender, types.AxelarIBCAccount, sdk.NewCoins(asset)) case nexus.TypeGeneralMessageWithToken: - coin, err := nexustypes.NewCoin(ctx, nexusK, ibcK, bankK, *msg.Asset) + coin, err := nexusK.NewLockableCoin(ctx, ibcK, bankK, *msg.Asset) if err != nil { return sdk.Coin{}, err } diff --git a/x/axelarnet/keeper/message_route_test.go b/x/axelarnet/keeper/message_route_test.go index 3c0346e90..d51f9817e 100644 --- a/x/axelarnet/keeper/message_route_test.go +++ b/x/axelarnet/keeper/message_route_test.go @@ -17,7 +17,9 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/types/mock" evmtestutils "github.com/axelarnetwork/axelar-core/x/evm/types/testutils" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexusmock "github.com/axelarnetwork/axelar-core/x/nexus/exported/mock" nexustestutils "github.com/axelarnetwork/axelar-core/x/nexus/exported/testutils" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" "github.com/axelarnetwork/utils/funcs" "github.com/axelarnetwork/utils/slices" . "github.com/axelarnetwork/utils/test" @@ -81,11 +83,12 @@ func TestNewMessageRoute(t *testing.T) { msg nexus.GeneralMessage route nexus.MessageRoute - feegrantK *mock.FeegrantKeeperMock - ibcK *mock.IBCKeeperMock - bankK *mock.BankKeeperMock - nexusK *mock.NexusMock - stakingK *mock.StakingKeeperMock + feegrantK *mock.FeegrantKeeperMock + ibcK *mock.IBCKeeperMock + bankK *mock.BankKeeperMock + nexusK *mock.NexusMock + stakingK *mock.StakingKeeperMock + lockableCoin *nexusmock.LockableCoinMock ) givenMessageRoute := Given("the message route", func() { @@ -198,21 +201,24 @@ func TestNewMessageRoute(t *testing.T) { coin := rand.Coin() msg = randMsg(nexus.Processing, routingCtx.Payload, &coin) }). - Then("should deduct from the corresponding account", func(t *testing.T) { - nexusK.GetChainByNativeAssetFunc = func(_ sdk.Context, _ string) (nexus.Chain, bool) { - return exported.Axelarnet, true + Then("should unlock from the corresponding account", func(t *testing.T) { + nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + lockableCoin = &nexusmock.LockableCoinMock{ + GetOriginalCoinFunc: func(ctx sdk.Context) sdk.Coin { return coin }, + UnlockFunc: func(ctx sdk.Context, toAddr sdk.AccAddress) error { return nil }, + } + + return lockableCoin, nil } - bankK.SendCoinsFunc = func(_ sdk.Context, _, _ sdk.AccAddress, _ sdk.Coins) error { return nil } + ibcK.SendMessageFunc = func(_ context.Context, _ nexus.CrossChainAddress, _ sdk.Coin, _, _ string) error { return nil } assert.NoError(t, route(ctx, routingCtx, msg)) - assert.Len(t, bankK.SendCoinsCalls(), 1) - assert.Equal(t, nexus.GetEscrowAddress(msg.Asset.Denom), bankK.SendCoinsCalls()[0].FromAddr) - assert.Equal(t, types.AxelarIBCAccount, bankK.SendCoinsCalls()[0].ToAddr) - assert.Equal(t, sdk.NewCoins(*msg.Asset), bankK.SendCoinsCalls()[0].Amt) + assert.Len(t, lockableCoin.UnlockCalls(), 1) + assert.Equal(t, types.AxelarIBCAccount, lockableCoin.UnlockCalls()[0].ToAddr) assert.Len(t, ibcK.SendMessageCalls(), 1) assert.Equal(t, msg.Recipient, ibcK.SendMessageCalls()[0].Recipient) diff --git a/x/axelarnet/keeper/msg_server.go b/x/axelarnet/keeper/msg_server.go index 50f891860..5574c6642 100644 --- a/x/axelarnet/keeper/msg_server.go +++ b/x/axelarnet/keeper/msg_server.go @@ -16,7 +16,6 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" "github.com/axelarnetwork/axelar-core/x/axelarnet/types" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" - nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" tss "github.com/axelarnetwork/axelar-core/x/tss/exported" "github.com/axelarnetwork/utils/funcs" ) @@ -80,7 +79,7 @@ func (s msgServer) CallContract(c context.Context, req *types.CallContractReques }) if req.Fee != nil { - normalizedCoin, err := nexustypes.NewCoin(ctx, s.nexus, s.ibcK, s.bank, req.Fee.Amount) + normalizedCoin, err := s.nexus.NewLockableCoin(ctx, s.ibcK, s.bank, req.Fee.Amount) if err != nil { return nil, sdkerrors.Wrap(err, "unrecognized fee denom") } @@ -94,7 +93,7 @@ func (s msgServer) CallContract(c context.Context, req *types.CallContractReques MessageID: msgID, Recipient: req.Fee.Recipient, Fee: req.Fee.Amount, - Asset: normalizedCoin.GetDenom(), + Asset: normalizedCoin.GetCoin().Denom, } if req.Fee.RefundRecipient != nil { feePaidEvent.RefundRecipient = req.Fee.RefundRecipient.String() @@ -186,7 +185,7 @@ func (s msgServer) ConfirmDeposit(c context.Context, req *types.ConfirmDepositRe return nil, fmt.Errorf("recipient chain '%s' is not activated", recipient.Chain.Name) } - normalizedCoin, err := nexustypes.NewCoin(ctx, s.nexus, s.ibcK, s.bank, coin) + normalizedCoin, err := s.nexus.NewLockableCoin(ctx, s.ibcK, s.bank, coin) if err != nil { return nil, err } @@ -195,7 +194,7 @@ func (s msgServer) ConfirmDeposit(c context.Context, req *types.ConfirmDepositRe return nil, err } - transferID, err := s.nexus.EnqueueForTransfer(ctx, depositAddr, normalizedCoin.Coin) + transferID, err := s.nexus.EnqueueForTransfer(ctx, depositAddr, normalizedCoin.GetCoin()) if err != nil { return nil, err } @@ -404,7 +403,7 @@ func (s msgServer) RouteIBCTransfers(c context.Context, _ *types.RouteIBCTransfe return nil, err } for _, p := range pendingTransfers { - coin, err := nexustypes.NewCoin(ctx, s.nexus, s.ibcK, s.bank, p.Asset) + coin, err := s.nexus.NewLockableCoin(ctx, s.ibcK, s.bank, p.Asset) if err != nil { s.Logger(ctx).Error(fmt.Sprintf("failed to route IBC transfer %s: %s", p.String(), err)) continue @@ -500,7 +499,7 @@ func (s msgServer) RouteMessage(c context.Context, req *types.RouteMessageReques } func transfer(ctx sdk.Context, k Keeper, n types.Nexus, b types.BankKeeper, ibc types.IBCKeeper, recipient sdk.AccAddress, coin sdk.Coin) error { - c, err := nexustypes.NewCoin(ctx, n, ibc, b, coin) + c, err := n.NewLockableCoin(ctx, ibc, b, coin) if err != nil { return err } diff --git a/x/axelarnet/message_handler.go b/x/axelarnet/message_handler.go index 5211c1ad4..4aab0db7e 100644 --- a/x/axelarnet/message_handler.go +++ b/x/axelarnet/message_handler.go @@ -19,7 +19,6 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/keeper" "github.com/axelarnetwork/axelar-core/x/axelarnet/types" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" - nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" tss "github.com/axelarnetwork/axelar-core/x/tss/exported" "github.com/axelarnetwork/utils/funcs" ) @@ -154,9 +153,9 @@ func OnRecvMessage(ctx sdk.Context, k keeper.Keeper, ibcK keeper.IBCKeeper, n ty switch msg.Type { case nexus.TypeGeneralMessage: - err = handleMessage(ctx, n, b, sourceAddress, msg, token) + err = handleMessage(ctx, n, b, ibcK, sourceAddress, msg, token) case nexus.TypeGeneralMessageWithToken: - err = handleMessageWithToken(ctx, n, b, sourceAddress, msg, token) + err = handleMessageWithToken(ctx, n, b, ibcK, sourceAddress, msg, token) case nexus.TypeSendToken: // Send token is already rate limited in nexus.EnqueueTransfer rateLimitPacket = false @@ -185,7 +184,7 @@ func OnRecvMessage(ctx sdk.Context, k keeper.Keeper, ibcK keeper.IBCKeeper, n ty return ack } -func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcPath string, msg Message, token nexustypes.Coin) error { +func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcPath string, msg Message, token nexus.LockableCoin) error { // validate source chain srcChainName, srcChainFound := ibcK.GetChainNameByIBCPath(ctx, ibcPath) if !srcChainFound { @@ -198,7 +197,7 @@ func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcP } if msg.Fee != nil { - err := validateFee(ctx, n, token.Coin, nexus.MessageType(msg.Type), srcChain, *msg.Fee) + err := validateFee(ctx, n, token.GetCoin(), nexus.MessageType(msg.Type), srcChain, *msg.Fee) if err != nil { return err } @@ -231,12 +230,12 @@ func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcP return fmt.Errorf("unrecognized destination chain %s", destChainName) } - if !n.IsAssetRegistered(ctx, srcChain, token.GetDenom()) { - return fmt.Errorf("asset %s is not registered on chain %s", token.GetDenom(), srcChain.Name) + if !n.IsAssetRegistered(ctx, srcChain, token.GetCoin().Denom) { + return fmt.Errorf("asset %s is not registered on chain %s", token.GetCoin().Denom, srcChain.Name) } - if !n.IsAssetRegistered(ctx, destChain, token.GetDenom()) { - return fmt.Errorf("asset %s is not registered on chain %s", token.GetDenom(), destChain.Name) + if !n.IsAssetRegistered(ctx, destChain, token.GetCoin().Denom) { + return fmt.Errorf("asset %s is not registered on chain %s", token.GetCoin().Denom, destChain.Name) } return nil default: @@ -244,11 +243,11 @@ func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcP } } -func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexustypes.Coin) error { +func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableCoin) error { id, txID, nonce := n.GenerateMessageID(ctx) // ignore token for call contract - _, err := deductFee(ctx, b, msg.Fee, token, id) + _, err := deductFee(ctx, n, b, ibcK, msg.Fee, token, id) if err != nil { return err } @@ -285,10 +284,10 @@ func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAdd return n.SetNewMessage(ctx, m) } -func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexustypes.Coin) error { +func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableCoin) error { id, txID, nonce := n.GenerateMessageID(ctx) - token, err := deductFee(ctx, b, msg.Fee, token, id) + token, err := deductFee(ctx, n, b, ibcK, msg.Fee, token, id) if err != nil { return err } @@ -299,6 +298,7 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, destChain := funcs.MustOk(n.GetChain(ctx, nexus.ChainName(msg.DestinationChain))) recipient := nexus.CrossChainAddress{Chain: destChain, Address: msg.DestinationAddress} + coin := token.GetCoin() m := nexus.NewGeneralMessage( id, sourceAddress, @@ -306,7 +306,7 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, crypto.Keccak256Hash(msg.Payload).Bytes(), txID, nonce, - &token.Coin, + &coin, ) events.Emit(ctx, &types.ContractCallWithTokenSubmitted{ @@ -317,13 +317,13 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ContractAddress: m.GetDestinationAddress(), PayloadHash: m.PayloadHash, Payload: msg.Payload, - Asset: token.Coin, + Asset: token.GetCoin(), }) return n.SetNewMessage(ctx, m) } -func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossChainAddress, msg Message, token nexustypes.Coin) error { +func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableCoin) error { destChain := funcs.MustOk(n.GetChain(ctx, nexus.ChainName(msg.DestinationChain))) crossChainAddr := nexus.CrossChainAddress{Chain: destChain, Address: msg.DestinationAddress} @@ -331,7 +331,7 @@ func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossCh return err } - transferID, err := n.EnqueueTransfer(ctx, sourceAddress.Chain, crossChainAddr, token.Coin) + transferID, err := n.EnqueueTransfer(ctx, sourceAddress.Chain, crossChainAddr, token.GetCoin()) if err != nil { return err } @@ -342,7 +342,7 @@ func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossCh SourceChain: sourceAddress.Chain.Name, DestinationAddress: crossChainAddr.Address, DestinationChain: crossChainAddr.Chain.Name, - Asset: token.Coin, + Asset: token.GetCoin(), }) return nil @@ -351,7 +351,7 @@ func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossCh // extractTokenFromPacketData get normalized token from ICS20 packet // panic if unable to unmarshal packet data -func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, b types.BankKeeper, packet ibcexported.PacketI) (nexustypes.Coin, error) { +func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, b types.BankKeeper, packet ibcexported.PacketI) (nexus.LockableCoin, error) { data := funcs.Must(types.ToICS20Packet(packet)) // parse the transfer amount @@ -389,24 +389,24 @@ func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types. denom = denomTrace.IBCDenom() } - return nexustypes.NewCoin(ctx, n, ibcK, b, sdk.NewCoin(denom, amount)) + return n.NewLockableCoin(ctx, ibcK, b, sdk.NewCoin(denom, amount)) } // deductFee pays the fee and returns the updated transfer amount with the fee deducted -func deductFee(ctx sdk.Context, b types.BankKeeper, fee *Fee, token nexustypes.Coin, msgID string) (nexustypes.Coin, error) { +func deductFee(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, fee *Fee, token nexus.LockableCoin, msgID string) (nexus.LockableCoin, error) { if fee == nil { return token, nil } feeAmount := funcs.MustOk(sdk.NewIntFromString(fee.Amount)) - coin := sdk.NewCoin(token.GetOriginalCoin(ctx).Denom, feeAmount) + feeCoin := sdk.NewCoin(token.GetOriginalCoin(ctx).Denom, feeAmount) recipient := funcs.Must(sdk.AccAddressFromBech32(fee.Recipient)) feePaidEvent := types.FeePaid{ MessageID: msgID, Recipient: recipient, - Fee: coin, - Asset: token.GetDenom(), + Fee: feeCoin, + Asset: token.GetCoin().Denom, } if fee.RefundRecipient != nil { feePaidEvent.RefundRecipient = *fee.RefundRecipient @@ -414,9 +414,9 @@ func deductFee(ctx sdk.Context, b types.BankKeeper, fee *Fee, token nexustypes.C events.Emit(ctx, &feePaidEvent) // subtract fee from transfer value - token.Amount = token.Amount.Sub(feeAmount) + coinAfterFee := token.GetOriginalCoin(ctx).Sub(feeCoin) - return token, b.SendCoins(ctx, types.AxelarIBCAccount, recipient, sdk.NewCoins(coin)) + return funcs.Must(n.NewLockableCoin(ctx, ibcK, b, coinAfterFee)), b.SendCoins(ctx, types.AxelarIBCAccount, recipient, sdk.NewCoins(feeCoin)) } // validateReceiver rejects uppercase GMP account address diff --git a/x/axelarnet/module.go b/x/axelarnet/module.go index d84162ea2..be94430ed 100644 --- a/x/axelarnet/module.go +++ b/x/axelarnet/module.go @@ -29,7 +29,6 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/keeper" "github.com/axelarnetwork/axelar-core/x/axelarnet/types" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" - nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" "github.com/axelarnetwork/utils/funcs" ) @@ -343,7 +342,7 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed cross chain transfer transferID, ok := getSeqIDMapping(ctx, m.keeper, port, channel, sequence) if ok { - coin, err := nexustypes.NewCoin(ctx, m.nexus, m.ibcK, m.bank, funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)).Token) + coin, err := m.nexus.NewLockableCoin(ctx, m.ibcK, m.bank, funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)).Token) if err != nil { return err } @@ -369,7 +368,7 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed general message messageID, ok := getSeqMessageIDMapping(ctx, m.keeper, port, channel, sequence) if ok { - coin, err := nexustypes.NewCoin(ctx, m.nexus, m.ibcK, m.bank, extractTokenFromAckOrTimeoutPacket(packet)) + coin, err := m.nexus.NewLockableCoin(ctx, m.ibcK, m.bank, extractTokenFromAckOrTimeoutPacket(packet)) if err != nil { return err } diff --git a/x/axelarnet/types/evm_translator_test.go b/x/axelarnet/types/evm_translator_test.go index 1547d5984..82a96d150 100644 --- a/x/axelarnet/types/evm_translator_test.go +++ b/x/axelarnet/types/evm_translator_test.go @@ -32,7 +32,6 @@ var ( addressType = funcs.Must(abi.NewType("address", "address", nil)) stringType = funcs.Must(abi.NewType("string", "string", nil)) bytesType = funcs.Must(abi.NewType("bytes", "bytes", nil)) - bytes32Type = funcs.Must(abi.NewType("bytes32", "bytes32", nil)) uint8Type = funcs.Must(abi.NewType("uint8", "uint8", nil)) uint64Type = funcs.Must(abi.NewType("uint64", "uint64", nil)) uint64ArrayType = funcs.Must(abi.NewType("uint64[]", "uint64[]", nil)) @@ -173,15 +172,15 @@ func TestConstructWasmMessageV1Large(t *testing.T) { assert.True(t, ok) assert.Equal(t, boolTrue, actualBool) - arrayInterface, ok := executeMsg["string_array"].([]interface{}) + arrayInterface, _ := executeMsg["string_array"].([]interface{}) actualStringArray := slices.Map(arrayInterface, func(t interface{}) string { return t.(string) }) assert.Equal(t, stringArray, actualStringArray) - arrayInterface, ok = executeMsg["uint64_array"].([]interface{}) + arrayInterface, _ = executeMsg["uint64_array"].([]interface{}) uint64StrArray := slices.Map(arrayInterface, func(t interface{}) string { return t.(json.Number).String() }) assert.Equal(t, uint64Array, slices.Map(uint64StrArray, func(t string) uint64 { return funcs.Must(strconv.ParseUint(t, 10, 64)) })) - arrayInterface, ok = executeMsg["uint64_array_nested"].([]interface{}) + arrayInterface, _ = executeMsg["uint64_array_nested"].([]interface{}) actualUint64NestedArray := slices.Map(arrayInterface, func(inner interface{}) []uint64 { return slices.Map(inner.([]interface{}), func(t interface{}) uint64 { return funcs.Must(strconv.ParseUint(t.(json.Number).String(), 10, 64)) @@ -189,7 +188,7 @@ func TestConstructWasmMessageV1Large(t *testing.T) { }) assert.Equal(t, uint64NestedArray, actualUint64NestedArray) - arrayInterface, ok = executeMsg["string_array_nested"].([]interface{}) + arrayInterface, _ = executeMsg["string_array_nested"].([]interface{}) actualStringNestedArray := slices.Map(arrayInterface, func(inner interface{}) []string { return slices.Map(inner.([]interface{}), func(t interface{}) string { return t.(string) diff --git a/x/axelarnet/types/expected_keepers.go b/x/axelarnet/types/expected_keepers.go index c13a9cdf7..b79b28568 100644 --- a/x/axelarnet/types/expected_keepers.go +++ b/x/axelarnet/types/expected_keepers.go @@ -87,6 +87,7 @@ type Nexus interface { SetMessageFailed(ctx sdk.Context, id string) error GenerateMessageID(ctx sdk.Context) (string, []byte, uint64) ValidateAddress(ctx sdk.Context, address nexus.CrossChainAddress) error + NewLockableCoin(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) } // BankKeeper defines the expected interface contract the vesting module requires diff --git a/x/axelarnet/types/mock/expected_keepers.go b/x/axelarnet/types/mock/expected_keepers.go index 760e6cecc..af78ed715 100644 --- a/x/axelarnet/types/mock/expected_keepers.go +++ b/x/axelarnet/types/mock/expected_keepers.go @@ -751,6 +751,9 @@ var _ axelarnettypes.Nexus = &NexusMock{} // LoggerFunc: func(ctx cosmossdktypes.Context) log.Logger { // panic("mock out the Logger method") // }, +// NewLockableCoinFunc: func(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableCoin, error) { +// panic("mock out the NewLockableCoin method") +// }, // RateLimitTransferFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, asset cosmossdktypes.Coin, direction github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferDirection) error { // panic("mock out the RateLimitTransfer method") // }, @@ -884,6 +887,9 @@ type NexusMock struct { // LoggerFunc mocks the Logger method. LoggerFunc func(ctx cosmossdktypes.Context) log.Logger + // NewLockableCoinFunc mocks the NewLockableCoin method. + NewLockableCoinFunc func(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableCoin, error) + // RateLimitTransferFunc mocks the RateLimitTransfer method. RateLimitTransferFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, asset cosmossdktypes.Coin, direction github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferDirection) error @@ -1128,6 +1134,17 @@ type NexusMock struct { // Ctx is the ctx argument value. Ctx cosmossdktypes.Context } + // NewLockableCoin holds details about calls to the NewLockableCoin method. + NewLockableCoin []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Ibc is the ibc argument value. + Ibc nexustypes.IBCKeeper + // Bank is the bank argument value. + Bank nexustypes.BankKeeper + // Coin is the coin argument value. + Coin cosmossdktypes.Coin + } // RateLimitTransfer holds details about calls to the RateLimitTransfer method. RateLimitTransfer []struct { // Ctx is the ctx argument value. @@ -1269,6 +1286,7 @@ type NexusMock struct { lockIsWasmConnectionActivated sync.RWMutex lockLinkAddresses sync.RWMutex lockLogger sync.RWMutex + lockNewLockableCoin sync.RWMutex lockRateLimitTransfer sync.RWMutex lockRegisterAsset sync.RWMutex lockRegisterFee sync.RWMutex @@ -2328,6 +2346,50 @@ func (mock *NexusMock) LoggerCalls() []struct { return calls } +// NewLockableCoin calls NewLockableCoinFunc. +func (mock *NexusMock) NewLockableCoin(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableCoin, error) { + if mock.NewLockableCoinFunc == nil { + panic("NexusMock.NewLockableCoinFunc: method is nil but Nexus.NewLockableCoin was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Ibc nexustypes.IBCKeeper + Bank nexustypes.BankKeeper + Coin cosmossdktypes.Coin + }{ + Ctx: ctx, + Ibc: ibc, + Bank: bank, + Coin: coin, + } + mock.lockNewLockableCoin.Lock() + mock.calls.NewLockableCoin = append(mock.calls.NewLockableCoin, callInfo) + mock.lockNewLockableCoin.Unlock() + return mock.NewLockableCoinFunc(ctx, ibc, bank, coin) +} + +// NewLockableCoinCalls gets all the calls that were made to NewLockableCoin. +// Check the length with: +// +// len(mockedNexus.NewLockableCoinCalls()) +func (mock *NexusMock) NewLockableCoinCalls() []struct { + Ctx cosmossdktypes.Context + Ibc nexustypes.IBCKeeper + Bank nexustypes.BankKeeper + Coin cosmossdktypes.Coin +} { + var calls []struct { + Ctx cosmossdktypes.Context + Ibc nexustypes.IBCKeeper + Bank nexustypes.BankKeeper + Coin cosmossdktypes.Coin + } + mock.lockNewLockableCoin.RLock() + calls = mock.calls.NewLockableCoin + mock.lockNewLockableCoin.RUnlock() + return calls +} + // RateLimitTransfer calls RateLimitTransferFunc. func (mock *NexusMock) RateLimitTransfer(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, asset cosmossdktypes.Coin, direction github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferDirection) error { if mock.RateLimitTransferFunc == nil { diff --git a/x/nexus/exported/mock/types.go b/x/nexus/exported/mock/types.go index 602639da5..53bce9497 100644 --- a/x/nexus/exported/mock/types.go +++ b/x/nexus/exported/mock/types.go @@ -560,3 +560,250 @@ func (mock *MaintainerStateMock) UnmarshalCalls() []struct { mock.lockUnmarshal.RUnlock() return calls } + +// Ensure, that LockableCoinMock does implement exported.LockableCoin. +// If this is not the case, regenerate this file with moq. +var _ exported.LockableCoin = &LockableCoinMock{} + +// LockableCoinMock is a mock implementation of exported.LockableCoin. +// +// func TestSomethingThatUsesLockableCoin(t *testing.T) { +// +// // make and configure a mocked exported.LockableCoin +// mockedLockableCoin := &LockableCoinMock{ +// GetCoinFunc: func() types.Coin { +// panic("mock out the GetCoin method") +// }, +// GetOriginalCoinFunc: func(ctx types.Context) types.Coin { +// panic("mock out the GetOriginalCoin method") +// }, +// LockFunc: func(ctx types.Context, fromAddr types.AccAddress) error { +// panic("mock out the Lock method") +// }, +// SubFunc: func(coin types.Coin) exported.LockableCoin { +// panic("mock out the Sub method") +// }, +// UnlockFunc: func(ctx types.Context, toAddr types.AccAddress) error { +// panic("mock out the Unlock method") +// }, +// } +// +// // use mockedLockableCoin in code that requires exported.LockableCoin +// // and then make assertions. +// +// } +type LockableCoinMock struct { + // GetCoinFunc mocks the GetCoin method. + GetCoinFunc func() types.Coin + + // GetOriginalCoinFunc mocks the GetOriginalCoin method. + GetOriginalCoinFunc func(ctx types.Context) types.Coin + + // LockFunc mocks the Lock method. + LockFunc func(ctx types.Context, fromAddr types.AccAddress) error + + // SubFunc mocks the Sub method. + SubFunc func(coin types.Coin) exported.LockableCoin + + // UnlockFunc mocks the Unlock method. + UnlockFunc func(ctx types.Context, toAddr types.AccAddress) error + + // calls tracks calls to the methods. + calls struct { + // GetCoin holds details about calls to the GetCoin method. + GetCoin []struct { + } + // GetOriginalCoin holds details about calls to the GetOriginalCoin method. + GetOriginalCoin []struct { + // Ctx is the ctx argument value. + Ctx types.Context + } + // Lock holds details about calls to the Lock method. + Lock []struct { + // Ctx is the ctx argument value. + Ctx types.Context + // FromAddr is the fromAddr argument value. + FromAddr types.AccAddress + } + // Sub holds details about calls to the Sub method. + Sub []struct { + // Coin is the coin argument value. + Coin types.Coin + } + // Unlock holds details about calls to the Unlock method. + Unlock []struct { + // Ctx is the ctx argument value. + Ctx types.Context + // ToAddr is the toAddr argument value. + ToAddr types.AccAddress + } + } + lockGetCoin sync.RWMutex + lockGetOriginalCoin sync.RWMutex + lockLock sync.RWMutex + lockSub sync.RWMutex + lockUnlock sync.RWMutex +} + +// GetCoin calls GetCoinFunc. +func (mock *LockableCoinMock) GetCoin() types.Coin { + if mock.GetCoinFunc == nil { + panic("LockableCoinMock.GetCoinFunc: method is nil but LockableCoin.GetCoin was just called") + } + callInfo := struct { + }{} + mock.lockGetCoin.Lock() + mock.calls.GetCoin = append(mock.calls.GetCoin, callInfo) + mock.lockGetCoin.Unlock() + return mock.GetCoinFunc() +} + +// GetCoinCalls gets all the calls that were made to GetCoin. +// Check the length with: +// +// len(mockedLockableCoin.GetCoinCalls()) +func (mock *LockableCoinMock) GetCoinCalls() []struct { +} { + var calls []struct { + } + mock.lockGetCoin.RLock() + calls = mock.calls.GetCoin + mock.lockGetCoin.RUnlock() + return calls +} + +// GetOriginalCoin calls GetOriginalCoinFunc. +func (mock *LockableCoinMock) GetOriginalCoin(ctx types.Context) types.Coin { + if mock.GetOriginalCoinFunc == nil { + panic("LockableCoinMock.GetOriginalCoinFunc: method is nil but LockableCoin.GetOriginalCoin was just called") + } + callInfo := struct { + Ctx types.Context + }{ + Ctx: ctx, + } + mock.lockGetOriginalCoin.Lock() + mock.calls.GetOriginalCoin = append(mock.calls.GetOriginalCoin, callInfo) + mock.lockGetOriginalCoin.Unlock() + return mock.GetOriginalCoinFunc(ctx) +} + +// GetOriginalCoinCalls gets all the calls that were made to GetOriginalCoin. +// Check the length with: +// +// len(mockedLockableCoin.GetOriginalCoinCalls()) +func (mock *LockableCoinMock) GetOriginalCoinCalls() []struct { + Ctx types.Context +} { + var calls []struct { + Ctx types.Context + } + mock.lockGetOriginalCoin.RLock() + calls = mock.calls.GetOriginalCoin + mock.lockGetOriginalCoin.RUnlock() + return calls +} + +// Lock calls LockFunc. +func (mock *LockableCoinMock) Lock(ctx types.Context, fromAddr types.AccAddress) error { + if mock.LockFunc == nil { + panic("LockableCoinMock.LockFunc: method is nil but LockableCoin.Lock was just called") + } + callInfo := struct { + Ctx types.Context + FromAddr types.AccAddress + }{ + Ctx: ctx, + FromAddr: fromAddr, + } + mock.lockLock.Lock() + mock.calls.Lock = append(mock.calls.Lock, callInfo) + mock.lockLock.Unlock() + return mock.LockFunc(ctx, fromAddr) +} + +// LockCalls gets all the calls that were made to Lock. +// Check the length with: +// +// len(mockedLockableCoin.LockCalls()) +func (mock *LockableCoinMock) LockCalls() []struct { + Ctx types.Context + FromAddr types.AccAddress +} { + var calls []struct { + Ctx types.Context + FromAddr types.AccAddress + } + mock.lockLock.RLock() + calls = mock.calls.Lock + mock.lockLock.RUnlock() + return calls +} + +// Sub calls SubFunc. +func (mock *LockableCoinMock) Sub(coin types.Coin) exported.LockableCoin { + if mock.SubFunc == nil { + panic("LockableCoinMock.SubFunc: method is nil but LockableCoin.Sub was just called") + } + callInfo := struct { + Coin types.Coin + }{ + Coin: coin, + } + mock.lockSub.Lock() + mock.calls.Sub = append(mock.calls.Sub, callInfo) + mock.lockSub.Unlock() + return mock.SubFunc(coin) +} + +// SubCalls gets all the calls that were made to Sub. +// Check the length with: +// +// len(mockedLockableCoin.SubCalls()) +func (mock *LockableCoinMock) SubCalls() []struct { + Coin types.Coin +} { + var calls []struct { + Coin types.Coin + } + mock.lockSub.RLock() + calls = mock.calls.Sub + mock.lockSub.RUnlock() + return calls +} + +// Unlock calls UnlockFunc. +func (mock *LockableCoinMock) Unlock(ctx types.Context, toAddr types.AccAddress) error { + if mock.UnlockFunc == nil { + panic("LockableCoinMock.UnlockFunc: method is nil but LockableCoin.Unlock was just called") + } + callInfo := struct { + Ctx types.Context + ToAddr types.AccAddress + }{ + Ctx: ctx, + ToAddr: toAddr, + } + mock.lockUnlock.Lock() + mock.calls.Unlock = append(mock.calls.Unlock, callInfo) + mock.lockUnlock.Unlock() + return mock.UnlockFunc(ctx, toAddr) +} + +// UnlockCalls gets all the calls that were made to Unlock. +// Check the length with: +// +// len(mockedLockableCoin.UnlockCalls()) +func (mock *LockableCoinMock) UnlockCalls() []struct { + Ctx types.Context + ToAddr types.AccAddress +} { + var calls []struct { + Ctx types.Context + ToAddr types.AccAddress + } + mock.lockUnlock.RLock() + calls = mock.calls.Unlock + mock.lockUnlock.RUnlock() + return calls +} diff --git a/x/nexus/exported/types.go b/x/nexus/exported/types.go index 594bcfd58..1fe4f28ff 100644 --- a/x/nexus/exported/types.go +++ b/x/nexus/exported/types.go @@ -19,7 +19,15 @@ import ( "github.com/axelarnetwork/utils/slices" ) -//go:generate moq -out ./mock/types.go -pkg mock . MaintainerState +//go:generate moq -out ./mock/types.go -pkg mock . MaintainerState LockableCoin + +// LockableCoin defines a coin that can be locked and unlocked +type LockableCoin interface { + GetCoin() sdk.Coin + GetOriginalCoin(ctx sdk.Context) sdk.Coin + Lock(ctx sdk.Context, fromAddr sdk.AccAddress) error + Unlock(ctx sdk.Context, toAddr sdk.AccAddress) error +} // AddressValidator defines a function that implements address verification upon a request to link addresses type AddressValidator func(ctx sdk.Context, address CrossChainAddress) error diff --git a/x/nexus/types/coin.go b/x/nexus/keeper/lockable_coin.go similarity index 58% rename from x/nexus/types/coin.go rename to x/nexus/keeper/lockable_coin.go index 63d8bdbfb..c9e580443 100644 --- a/x/nexus/types/coin.go +++ b/x/nexus/keeper/lockable_coin.go @@ -1,4 +1,4 @@ -package types +package keeper import ( "fmt" @@ -9,37 +9,43 @@ import ( axelarnet "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" "github.com/axelarnetwork/axelar-core/x/nexus/exported" + "github.com/axelarnetwork/axelar-core/x/nexus/types" "github.com/axelarnetwork/utils/funcs" ) -// Coin provides functionality to lock and release coins -type Coin struct { +// NewLockableCoin creates a new lockable coin +func (k Keeper) NewLockableCoin(ctx sdk.Context, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (exported.LockableCoin, error) { + return newLockableCoin(ctx, k, ibc, bank, coin) +} + +// lockableCoin provides functionality to lock and release coins +type lockableCoin struct { sdk.Coin - coinType CoinType - nexus Nexus - ibc IBCKeeper - bank BankKeeper + coinType types.CoinType + nexus types.Nexus + ibc types.IBCKeeper + bank types.BankKeeper } -// NewCoin creates a coin struct, assign a coin type and normalize the denom if it's a ICS20 token -func NewCoin(ctx sdk.Context, nexus Nexus, ibc IBCKeeper, bank BankKeeper, coin sdk.Coin) (Coin, error) { +// newLockableCoin creates a coin struct, assign a coin type and normalize the denom if it's a ICS20 token +func newLockableCoin(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (lockableCoin, error) { coinType, err := getCoinType(ctx, nexus, coin.GetDenom()) if err != nil { - return Coin{}, err + return lockableCoin{}, err } // If coin type is ICS20, we need to normalize it to convert from 'ibc/{hash}' // to native asset denom so that nexus could recognize it - if coinType == ICS20 { + if coinType == types.ICS20 { denomTrace, err := ibc.ParseIBCDenom(ctx, coin.GetDenom()) if err != nil { - return Coin{}, err + return lockableCoin{}, err } coin = sdk.NewCoin(denomTrace.GetBaseDenom(), coin.Amount) } - c := Coin{ + c := lockableCoin{ Coin: coin, coinType: coinType, nexus: nexus, @@ -47,26 +53,30 @@ func NewCoin(ctx sdk.Context, nexus Nexus, ibc IBCKeeper, bank BankKeeper, coin bank: bank, } if _, err := c.getOriginalCoin(ctx); err != nil { - return Coin{}, err + return lockableCoin{}, err } return c, nil } +func (c lockableCoin) GetCoin() sdk.Coin { + return c.Coin +} + // GetOriginalCoin returns the original coin -func (c Coin) GetOriginalCoin(ctx sdk.Context) sdk.Coin { +func (c lockableCoin) GetOriginalCoin(ctx sdk.Context) sdk.Coin { // NOTE: must not fail since it's already checked in NewCoin return funcs.Must(c.getOriginalCoin(ctx)) } // Lock locks the given coin from the given address -func (c Coin) Lock(ctx sdk.Context, fromAddr sdk.AccAddress) error { +func (c lockableCoin) Lock(ctx sdk.Context, fromAddr sdk.AccAddress) error { coin := c.GetOriginalCoin(ctx) switch c.coinType { - case ICS20, Native: + case types.ICS20, types.Native: return lock(ctx, c.bank, fromAddr, coin) - case External: + case types.External: return burn(ctx, c.bank, fromAddr, coin) default: return fmt.Errorf("unrecognized coin type %d", c.coinType) @@ -74,32 +84,32 @@ func (c Coin) Lock(ctx sdk.Context, fromAddr sdk.AccAddress) error { } // Unlock unlocks the given coin to the given address -func (c Coin) Unlock(ctx sdk.Context, toAddr sdk.AccAddress) error { +func (c lockableCoin) Unlock(ctx sdk.Context, toAddr sdk.AccAddress) error { coin := c.GetOriginalCoin(ctx) switch c.coinType { - case ICS20, Native: + case types.ICS20, types.Native: return unlock(ctx, c.bank, toAddr, coin) - case External: + case types.External: return mint(ctx, c.bank, toAddr, coin) default: return fmt.Errorf("unrecognized coin type %d", c.coinType) } } -func (c Coin) getOriginalCoin(ctx sdk.Context) (sdk.Coin, error) { +func (c lockableCoin) getOriginalCoin(ctx sdk.Context) (sdk.Coin, error) { switch c.coinType { - case ICS20: + case types.ICS20: return c.toICS20(ctx) - case Native, External: + case types.Native, types.External: return c.Coin, nil default: return sdk.Coin{}, fmt.Errorf("unrecognized coin type %d", c.coinType) } } -func (c Coin) toICS20(ctx sdk.Context) (sdk.Coin, error) { - if c.coinType != ICS20 { +func (c lockableCoin) toICS20(ctx sdk.Context) (sdk.Coin, error) { + if c.coinType != types.ICS20 { return sdk.Coin{}, fmt.Errorf("%s is not ICS20 token", c.GetDenom()) } @@ -122,53 +132,53 @@ func (c Coin) toICS20(ctx sdk.Context) (sdk.Coin, error) { return sdk.NewCoin(trace.IBCDenom(), c.Amount), nil } -func lock(ctx sdk.Context, bank BankKeeper, fromAddr sdk.AccAddress, coin sdk.Coin) error { +func lock(ctx sdk.Context, bank types.BankKeeper, fromAddr sdk.AccAddress, coin sdk.Coin) error { return bank.SendCoins(ctx, fromAddr, exported.GetEscrowAddress(coin.GetDenom()), sdk.NewCoins(coin)) } -func unlock(ctx sdk.Context, bank BankKeeper, toAddr sdk.AccAddress, coin sdk.Coin) error { +func unlock(ctx sdk.Context, bank types.BankKeeper, toAddr sdk.AccAddress, coin sdk.Coin) error { return bank.SendCoins(ctx, exported.GetEscrowAddress(coin.GetDenom()), toAddr, sdk.NewCoins(coin)) } -func burn(ctx sdk.Context, bank BankKeeper, fromAddr sdk.AccAddress, coin sdk.Coin) error { +func burn(ctx sdk.Context, bank types.BankKeeper, fromAddr sdk.AccAddress, coin sdk.Coin) error { coins := sdk.NewCoins(coin) - if err := bank.SendCoinsFromAccountToModule(ctx, fromAddr, ModuleName, coins); err != nil { + if err := bank.SendCoinsFromAccountToModule(ctx, fromAddr, types.ModuleName, coins); err != nil { return err } // NOTE: should never fail since the coin is just transfered to the module // account before the burn - funcs.MustNoErr(bank.BurnCoins(ctx, ModuleName, coins)) + funcs.MustNoErr(bank.BurnCoins(ctx, types.ModuleName, coins)) return nil } -func mint(ctx sdk.Context, bank BankKeeper, toAddr sdk.AccAddress, coin sdk.Coin) error { +func mint(ctx sdk.Context, bank types.BankKeeper, toAddr sdk.AccAddress, coin sdk.Coin) error { coins := sdk.NewCoins(coin) - if err := bank.MintCoins(ctx, ModuleName, coins); err != nil { + if err := bank.MintCoins(ctx, types.ModuleName, coins); err != nil { return err } // NOTE: should never fail since the coin is just minted to the module // account before the transfer - funcs.MustNoErr(bank.SendCoinsFromModuleToAccount(ctx, ModuleName, toAddr, coins)) + funcs.MustNoErr(bank.SendCoinsFromModuleToAccount(ctx, types.ModuleName, toAddr, coins)) return nil } -func getCoinType(ctx sdk.Context, nexus Nexus, denom string) (CoinType, error) { +func getCoinType(ctx sdk.Context, nexus types.Nexus, denom string) (types.CoinType, error) { switch { // check if the format of token denomination is 'ibc/{hash}' case isIBCDenom(denom): - return ICS20, nil + return types.ICS20, nil case isNativeAssetOnAxelarnet(ctx, nexus, denom): - return Native, nil + return types.Native, nil case nexus.IsAssetRegistered(ctx, axelarnet.Axelarnet, denom): - return External, nil + return types.External, nil default: - return Unrecognized, fmt.Errorf("unrecognized coin %s", denom) + return types.Unrecognized, fmt.Errorf("unrecognized coin %s", denom) } } @@ -190,7 +200,7 @@ func isIBCDenom(denom string) bool { return true } -func isNativeAssetOnAxelarnet(ctx sdk.Context, nexus Nexus, denom string) bool { +func isNativeAssetOnAxelarnet(ctx sdk.Context, nexus types.Nexus, denom string) bool { chain, ok := nexus.GetChainByNativeAsset(ctx, denom) return ok && chain.Name.Equals(axelarnet.Axelarnet.Name) From 6f0087b194a0e3a979ea3bffa90f26a90b379c1d Mon Sep 17 00:00:00 2001 From: Sammy Date: Wed, 25 Sep 2024 12:53:12 -0400 Subject: [PATCH 05/11] fix tests --- x/axelarnet/keeper/msg_server_test.go | 394 +++++++------------------- x/axelarnet/message_handler_test.go | 145 +++++++--- x/axelarnet/module_test.go | 61 ++-- x/nexus/exported/mock/types.go | 44 --- 4 files changed, 263 insertions(+), 381 deletions(-) diff --git a/x/axelarnet/keeper/msg_server_test.go b/x/axelarnet/keeper/msg_server_test.go index b37798c43..41cfc3752 100644 --- a/x/axelarnet/keeper/msg_server_test.go +++ b/x/axelarnet/keeper/msg_server_test.go @@ -27,7 +27,9 @@ import ( evmtypes "github.com/axelarnetwork/axelar-core/x/evm/types" evmtestutils "github.com/axelarnetwork/axelar-core/x/evm/types/testutils" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexusmock "github.com/axelarnetwork/axelar-core/x/nexus/exported/mock" nexustestutils "github.com/axelarnetwork/axelar-core/x/nexus/exported/testutils" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" tss "github.com/axelarnetwork/axelar-core/x/tss/exported" "github.com/axelarnetwork/utils/funcs" "github.com/axelarnetwork/utils/slices" @@ -174,39 +176,13 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { nexusK.IsChainActivatedFunc = func(sdk.Context, nexus.Chain) bool { return true } }) - assetIsRegistered := When("asset is registered", func() { - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { return true } - }) - - assetIsLinkedToCosmosChain := When("asset is linked to a cosmos chain", func() { - nexusK.GetChainByNativeAssetFunc = func(ctx sdk.Context, asset string) (nexus.Chain, bool) { - return chain, true - } - }) - - sendCoinSucceeds := When("send to module account succeeds", func() { - bankK.SendCoinsFunc = func(sdk.Context, sdk.AccAddress, sdk.AccAddress, sdk.Coins) error { - return nil - } - }) - enqueueTransferSucceeds := When("enqueue transfer succeeds", func() { nexusK.EnqueueForTransferFunc = func(sdk.Context, nexus.CrossChainAddress, sdk.Coin) (nexus.TransferID, error) { return nexus.TransferID(rand.I64Between(1, 9999)), nil } }) - confirmExternalICS20TokenRequest := When("a confirm external ICS20 token deposit request is made", func() { - req = randomMsgConfirmDeposit() - req.Denom = denomTrace.IBCDenom() - }) - - confirmNativeAXLRequest := When("a confirm native AXL token deposit request is made", func() { - req = randomMsgConfirmDeposit() - req.Denom = exported.NativeAsset - }) - - confirmExternalERC20Token := When("a confirm external ERC20 token deposit request is made", func() { + confirmToken := When("a confirm token deposit request is made", func() { req = randomMsgConfirmDeposit() }) @@ -223,7 +199,7 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { return sdk.NewCoin(denom, sdk.ZeroInt()) } }). - When2(confirmExternalICS20TokenRequest). + When2(confirmToken). Then2(confirmDepositFails), whenDepositAddressHasBalance. @@ -232,7 +208,7 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { return nexus.CrossChainAddress{}, false } }). - When2(confirmExternalICS20TokenRequest). + When2(confirmToken). Then2(confirmDepositFails), whenDepositAddressHasBalance. @@ -240,119 +216,57 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { When("chain is not activated", func() { nexusK.IsChainActivatedFunc = func(sdk.Context, nexus.Chain) bool { return false } }). - When2(confirmExternalICS20TokenRequest). + When2(confirmToken). Then2(confirmDepositFails), whenDepositAddressHasBalance. When2(recipientIsFound). When2(chainIsActivated). - When("asset is not registered", func() { - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { return false } - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return nexus.Chain{}, false + When("fails to create a lockable coin", func() { + nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + return nil, fmt.Errorf("failed to create lockable coin") } }). - When2(confirmExternalICS20TokenRequest). - When("confirm an invalid IBC denom", func() { - req.Denom = fmt.Sprintf("ibc/%s", rand.HexStr(50)) - }). + When2(confirmToken). Then2(confirmDepositFails), whenDepositAddressHasBalance. When2(recipientIsFound). When2(chainIsActivated). - When2(assetIsLinkedToCosmosChain). - When("send to escrow account fails", func() { - bankK.SendCoinsFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { - return fmt.Errorf("failed to send %s from %s to %s", amt.String(), fromAddr.String(), toAddr.String()) + When("suceeded to create a lockable coin but lock fails", func() { + nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + lockbleCoin := &nexusmock.LockableCoinMock{ + LockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + return fmt.Errorf("failed to lock coin") + }, + } + + return lockbleCoin, nil } }). - When2(confirmExternalICS20TokenRequest). + When2(confirmToken). Then2(confirmDepositFails), whenDepositAddressHasBalance. When2(recipientIsFound). When2(chainIsActivated). - When2(assetIsLinkedToCosmosChain). - When2(sendCoinSucceeds). - When("enqueue transfer fails", func() { - nexusK.EnqueueForTransferFunc = func(sdk.Context, nexus.CrossChainAddress, sdk.Coin) (nexus.TransferID, error) { - return nexus.TransferID(0), fmt.Errorf("failed to enqueue tranfer") + When("suceeded to create a lockable coin but lock succeeds", func() { + nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + lockbleCoin := &nexusmock.LockableCoinMock{ + LockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + return nil + }, + GetCoinFunc: func() sdk.Coin { + return sdk.NewCoin(req.Denom, sdk.NewInt(1e18)) + }, + } + + return lockbleCoin, nil } }). - When2(confirmExternalICS20TokenRequest). - Then2(confirmDepositFails), - - whenDepositAddressHasBalance. - When2(recipientIsFound). - When2(chainIsActivated). - When2(assetIsLinkedToCosmosChain). - When2(sendCoinSucceeds). When2(enqueueTransferSucceeds). - When2(confirmExternalICS20TokenRequest). - Then("confirm external IBC deposit succeeds", func(t *testing.T) { - _, err := server.ConfirmDeposit(sdk.WrapSDKContext(ctx), req) - assert.NoError(t, err) - }), - - whenDepositAddressHasBalance. - When2(recipientIsFound). - When2(chainIsActivated). - When("is native asset on Axelarnet", func() { - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return exported.Axelarnet, true - } - }). - When("send to escrow account fails", func() { - bankK.SendCoinsFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { - return fmt.Errorf("failed to send %s from %s to %s", amt.String(), fromAddr.String(), toAddr.String()) - } - }). - When2(confirmNativeAXLRequest). - Then2(confirmDepositFails), - - whenDepositAddressHasBalance. - When2(recipientIsFound). - When2(chainIsActivated). - When("is native asset on Axelarnet", func() { - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return exported.Axelarnet, true - } - }). - When2(sendCoinSucceeds). - When2(enqueueTransferSucceeds). - When2(confirmNativeAXLRequest). - Then("confirm native AXL deposit succeeds", func(t *testing.T) { - _, err := server.ConfirmDeposit(sdk.WrapSDKContext(ctx), req) - assert.NoError(t, err) - }), - - whenDepositAddressHasBalance. - When2(recipientIsFound). - When2(chainIsActivated). - When("asset is not registered", func() { - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { return false } - }). - When2(confirmExternalERC20Token). - Then2(confirmDepositFails), - - whenDepositAddressHasBalance. - When2(recipientIsFound). - When2(chainIsActivated). - When2(assetIsRegistered). - When("send coins to module account succeeds", func() { - bankK.SendCoinsFromAccountToModuleFunc = func(sdk.Context, sdk.AccAddress, string, sdk.Coins) error { - return nil - } - }). - When("burn coin succeeds", func() { - bankK.BurnCoinsFunc = func(ctx sdk.Context, moduleName string, amt sdk.Coins) error { - return nil - } - }). - When2(enqueueTransferSucceeds). - When2(confirmExternalERC20Token). - Then("confirm external ERC20 deposit succeeds", func(t *testing.T) { + When2(confirmToken). + Then("confirm deposit succeeds", func(t *testing.T) { _, err := server.ConfirmDeposit(sdk.WrapSDKContext(ctx), req) assert.NoError(t, err) }), @@ -362,13 +276,14 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { func TestHandleMsgExecutePendingTransfers(t *testing.T) { var ( - server types.MsgServiceServer - k keeper.Keeper - nexusK *mock.NexusMock - bankK *mock.BankKeeperMock - transferK *mock.IBCTransferKeeperMock - ctx sdk.Context - req *types.ExecutePendingTransfersRequest + server types.MsgServiceServer + k keeper.Keeper + nexusK *mock.NexusMock + bankK *mock.BankKeeperMock + transferK *mock.IBCTransferKeeperMock + ctx sdk.Context + req *types.ExecutePendingTransfersRequest + lockableCoin *nexusmock.LockableCoinMock ) givenMsgServer := Given("an axelarnet msg server", func() { @@ -391,28 +306,23 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { server = keeper.NewMsgServerImpl(k, nexusK, bankK, ibcK) }) - whenAssetOriginsFromExternalCosmosChain := When("asset is from external cosmos chain", func() { - chain := nexustestutils.RandomChain() - funcs.MustNoErr(k.SetCosmosChain(ctx, types.CosmosChain{ - Name: chain.Name, - AddrPrefix: rand.StrBetween(1, 10), - IBCPath: axelartestutils.RandomIBCPath(), - })) - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return chain, true - } - }) - - hasPendingTransfers := When("has pending transfers", func() { + whenHasPendingTransfers := When("has pending transfers", func() { nexusK.GetTransfersForChainPaginatedFunc = func(ctx sdk.Context, chain nexus.Chain, state nexus.TransferState, pageRequest *query.PageRequest) ([]nexus.CrossChainTransfer, *query.PageResponse, error) { return []nexus.CrossChainTransfer{randomTransfer(rand.Denom(3, 10), nexus.ChainName(rand.StrBetween(2, 10)))}, nil, nil } }) - sendCoinSucceeds := When("send coins succeeds", func() { - bankK.SendCoinsFunc = func(sdk.Context, sdk.AccAddress, sdk.AccAddress, sdk.Coins) error { - return nil + unlocksCoinSucceeds := When("unlock coins succeeds", func() { + lockableCoin = &nexusmock.LockableCoinMock{ + UnlockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + return nil + }, } + + nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + return lockableCoin, nil + } + }) requestIsMade := When("an execute pending transfer request is made", func() { @@ -430,121 +340,57 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { When2(requestIsMade). Then("do nothing", func(t *testing.T) { _, err := server.ExecutePendingTransfers(sdk.WrapSDKContext(ctx), req) + assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), 0) - assert.Len(t, bankK.SendCoinsCalls(), 0) assert.Len(t, nexusK.ArchivePendingTransferCalls(), 0) }), - whenAssetOriginsFromExternalCosmosChain. - When2(hasPendingTransfers). - When("send coins fails", func() { - bankK.SendCoinsFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error { - return fmt.Errorf("failed to send %s from %s to %s", amt.String(), fromAddr.String(), toAddr.String()) + whenHasPendingTransfers. + When("unlock coins fails", func() { + lockableCoin = &nexusmock.LockableCoinMock{ + UnlockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + return fmt.Errorf("failed to unlock coin") + }, + } + nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + return lockableCoin, nil } }). When2(requestIsMade). Then("should not archive the transfer", func(t *testing.T) { _, err := server.ExecutePendingTransfers(sdk.WrapSDKContext(ctx), req) assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), 0) - assert.Len(t, bankK.SendCoinsCalls(), 1) + assert.Len(t, nexusK.ArchivePendingTransferCalls(), 0) }), - whenAssetOriginsFromExternalCosmosChain. - When2(hasPendingTransfers). - When2(sendCoinSucceeds). + whenHasPendingTransfers. + When2(unlocksCoinSucceeds). When2(requestIsMade). Then("archive the transfer", func(t *testing.T) { _, err := server.ExecutePendingTransfers(sdk.WrapSDKContext(ctx), req) assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), 0) - assert.Len(t, bankK.SendCoinsCalls(), 1) - assert.Len(t, nexusK.ArchivePendingTransferCalls(), 1) - }), - When("asset is native on Axelarnet", func() { - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return exported.Axelarnet, true - } - }). - When2(hasPendingTransfers). - When2(sendCoinSucceeds). - When2(requestIsMade). - Then("send coin and archive the transfer", func(t *testing.T) { - _, err := server.ExecutePendingTransfers(sdk.WrapSDKContext(ctx), req) - assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), 0) - assert.Len(t, bankK.SendCoinsCalls(), 1) assert.Len(t, nexusK.ArchivePendingTransferCalls(), 1) + assert.Len(t, lockableCoin.UnlockCalls(), 1) }), - When("asset is not registered", func() { - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { - return false - } - }). - When2(requestIsMade). - Then("should panic", func(t *testing.T) { - assert.Panics(t, func() { - _, _ = server.ExecutePendingTransfers(sdk.WrapSDKContext(ctx), req) - }) - }), - - When("asset is registered", func() { - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { - return true - } - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return nexustestutils.RandomChain(), true - } - }). - When2(hasPendingTransfers). - When("mint coins succeeds", func() { - bankK.MintCoinsFunc = func(sdk.Context, string, sdk.Coins) error { - return nil - } - }). - When2(sendCoinSucceeds). - When2(requestIsMade). - Then("mint coin and archive the transfer", func(t *testing.T) { - _, err := server.ExecutePendingTransfers(sdk.WrapSDKContext(ctx), req) - assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), 1) - assert.Len(t, bankK.SendCoinsCalls(), 1) - assert.Len(t, nexusK.ArchivePendingTransferCalls(), 1) - }), - - When("asset is registered", func() { - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { - return true - } - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return nexustestutils.RandomChain(), true + When("has many pending transfers", func() { + nexusK.GetTransfersForChainPaginatedFunc = func(ctx sdk.Context, chain nexus.Chain, state nexus.TransferState, pageRequest *query.PageRequest) ([]nexus.CrossChainTransfer, *query.PageResponse, error) { + return slices.Expand(func(int) nexus.CrossChainTransfer { + return randomTransfer(rand.Denom(3, 10), nexus.ChainName(rand.StrBetween(2, 10))) + }, int(pageRequest.Limit)), nil, nil } }). - When("has many pending transfers", func() { - nexusK.GetTransfersForChainPaginatedFunc = func(ctx sdk.Context, chain nexus.Chain, state nexus.TransferState, pageRequest *query.PageRequest) ([]nexus.CrossChainTransfer, *query.PageResponse, error) { - return slices.Expand(func(int) nexus.CrossChainTransfer { - return randomTransfer(rand.Denom(3, 10), nexus.ChainName(rand.StrBetween(2, 10))) - }, int(pageRequest.Limit)), nil, nil - } - }). - When("mint coins succeeds", func() { - bankK.MintCoinsFunc = func(sdk.Context, string, sdk.Coins) error { - return nil - } - }). - When2(sendCoinSucceeds). + When2(unlocksCoinSucceeds). When2(requestIsMade). Then("mint coin and archive the transfer", func(t *testing.T) { transferLimit := int(k.GetTransferLimit(ctx)) _, err := server.ExecutePendingTransfers(sdk.WrapSDKContext(ctx), req) + assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), transferLimit) - assert.Len(t, bankK.SendCoinsCalls(), transferLimit) assert.Len(t, nexusK.ArchivePendingTransferCalls(), transferLimit) + assert.Len(t, lockableCoin.UnlockCalls(), transferLimit) }), ).Run(t) }) @@ -561,6 +407,7 @@ func TestHandleMsgRouteIBCTransfers(t *testing.T) { req *types.RouteIBCTransfersRequest cosmosChains []types.CosmosChain transfersNum int + lockableCoin *nexusmock.LockableCoinMock ) givenMsgServer := Given("an axelarnet msg server", func() { @@ -594,14 +441,7 @@ func TestHandleMsgRouteIBCTransfers(t *testing.T) { server = keeper.NewMsgServerImpl(k, nexusK, bankK, ibcK) }) - whenAssetOriginsFromExternalCosmosChain := When("asset is from external cosmos chain", func() { - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - chainName := cosmosChains[rand.I64Between(0, int64(len(cosmosChains)))].Name - return nexus.Chain{Name: chainName}, true - } - - }) - hasPendingTranfers := When("has pending transfers", func() { + whenHasPendingTranfers := When("has pending transfers", func() { nexusK.GetTransfersForChainPaginatedFunc = func(ctx sdk.Context, chain nexus.Chain, state nexus.TransferState, pageRequest *query.PageRequest) ([]nexus.CrossChainTransfer, *query.PageResponse, error) { var transfers []nexus.CrossChainTransfer for i := int64(0); i < rand.I64Between(1, 5); i++ { @@ -651,59 +491,28 @@ func TestHandleMsgRouteIBCTransfers(t *testing.T) { When2(requestIsMade). Then2(doNothing), - whenAssetOriginsFromExternalCosmosChain. - When2(hasPendingTranfers). + whenHasPendingTranfers. When2(requestIsMade). - Then("archive the transfer", func(t *testing.T) { - _, err := server.RouteIBCTransfers(sdk.WrapSDKContext(ctx), req) - assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), 0) - assert.Len(t, nexusK.ArchivePendingTransferCalls(), transfersNum, fmt.Sprintf("expected %d got %d", transfersNum, len(nexusK.ArchivePendingTransferCalls()))) - }), - - When("asset is native on Axelarnet", func() { - nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { - return exported.Axelarnet, true - } - }). - When2(hasPendingTranfers). - When2(requestIsMade). - Then("send coin, archive the transfer", func(t *testing.T) { - _, err := server.RouteIBCTransfers(sdk.WrapSDKContext(ctx), req) - assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), 0) - assert.Len(t, nexusK.ArchivePendingTransferCalls(), transfersNum) - }), - - When("asset is not registered", func() { - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { - return false - } - }). - When2(requestIsMade). - Then("should panic", func(t *testing.T) { - assert.Panics(t, func() { - _, _ = server.RouteIBCTransfers(sdk.WrapSDKContext(ctx), req) - }) - }), + When("unlock coin succeeds", func() { + lockableCoin = &nexusmock.LockableCoinMock{ + UnlockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + return nil + }, + GetOriginalCoinFunc: func(ctx sdk.Context) sdk.Coin { + return sdk.NewCoin(rand.Denom(3, 10), sdk.NewInt(1e18)) + }, + } - When("asset is registered", func() { - nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { - return true - } - }). - When2(hasPendingTranfers). - When("mint succeeds", func() { - bankK.MintCoinsFunc = func(sdk.Context, string, sdk.Coins) error { - return nil + nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + return lockableCoin, nil } }). - When2(requestIsMade). - Then("mint coin, archive the transfer", func(t *testing.T) { + Then("archive the transfer", func(t *testing.T) { _, err := server.RouteIBCTransfers(sdk.WrapSDKContext(ctx), req) + assert.NoError(t, err) - assert.Len(t, bankK.MintCoinsCalls(), transfersNum) - assert.Len(t, nexusK.ArchivePendingTransferCalls(), transfersNum) + assert.Len(t, nexusK.ArchivePendingTransferCalls(), transfersNum, fmt.Sprintf("expected %d got %d", transfersNum, len(nexusK.ArchivePendingTransferCalls()))) + assert.Len(t, lockableCoin.UnlockCalls(), transfersNum) }), ).Run(t) }) @@ -1006,7 +815,15 @@ func TestHandleCallContract(t *testing.T) { givenMsgServer := Given("an axelarnet msg server", func() { ctx, k, _, _ = setup() k.InitGenesis(ctx, types.DefaultGenesisState()) - nexusK = &mock.NexusMock{} + nexusK = &mock.NexusMock{ + NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + lockableCoin := &nexusmock.LockableCoinMock{ + GetCoinFunc: func() sdk.Coin { return req.Fee.Amount }, + } + + return lockableCoin, nil + }, + } ibcK := keeper.NewIBCKeeper(k, &mock.IBCTransferKeeperMock{}) b = &mock.BankKeeperMock{} server = keeper.NewMsgServerImpl(k, nexusK, b, ibcK) @@ -1091,6 +908,7 @@ func TestHandleCallContract(t *testing.T) { payloadHash := crypto.Keccak256(req.Payload) assert.Equal(t, msg.PayloadHash, payloadHash) }), + whenChainIsRegistered. When2(whenChainIsActivated). When2(whenAddressIsValid). @@ -1121,6 +939,7 @@ func TestHandleCallContract(t *testing.T) { payloadHash := crypto.Keccak256(req.Payload) assert.Equal(t, msg.PayloadHash, payloadHash) }), + whenChainIsRegistered. When2(whenChainIsActivated). When2(whenAddressIsValid). @@ -1143,6 +962,7 @@ func TestHandleCallContract(t *testing.T) { payloadHash := crypto.Keccak256(req.Payload) assert.Equal(t, msg.PayloadHash, payloadHash) }), + whenChainIsRegistered. When2(whenChainIsActivated). When2(whenAddressIsValid). @@ -1151,6 +971,7 @@ func TestHandleCallContract(t *testing.T) { req.Fee.Amount.Amount = sdk.NewInt(0) }). Then2(validationFails), + whenChainIsRegistered. When2(whenChainIsActivated). When2(whenAddressIsValid). @@ -1160,6 +981,7 @@ func TestHandleCallContract(t *testing.T) { } }). Then2(callFails), + whenChainIsRegistered. When2(whenChainIsActivated). When("address is not valid", func() { @@ -1168,11 +990,13 @@ func TestHandleCallContract(t *testing.T) { } }). Then2(callFails), + whenChainIsRegistered. When("chain is not activated", func() { nexusK.IsChainActivatedFunc = func(_ sdk.Context, chain nexus.Chain) bool { return false } }). Then2(callFails), + When("chain is not registered", func() { nexusK.GetChainFunc = func(_ sdk.Context, chain nexus.ChainName) (nexus.Chain, bool) { return nexus.Chain{}, false diff --git a/x/axelarnet/message_handler_test.go b/x/axelarnet/message_handler_test.go index b93d6ab2e..726040d59 100644 --- a/x/axelarnet/message_handler_test.go +++ b/x/axelarnet/message_handler_test.go @@ -29,21 +29,24 @@ import ( evmtypes "github.com/axelarnetwork/axelar-core/x/evm/types" evmtestutils "github.com/axelarnetwork/axelar-core/x/evm/types/testutils" nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexusmock "github.com/axelarnetwork/axelar-core/x/nexus/exported/mock" nexustestutils "github.com/axelarnetwork/axelar-core/x/nexus/exported/testutils" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" "github.com/axelarnetwork/utils/funcs" . "github.com/axelarnetwork/utils/test" ) func TestHandleMessage(t *testing.T) { var ( - ctx sdk.Context - k keeper.Keeper - packet ibcchanneltypes.Packet - b *mock.BankKeeperMock - n *mock.NexusMock - channelK *mock.ChannelKeeperMock - ibcK keeper.IBCKeeper - r axelarnet.RateLimiter + ctx sdk.Context + k keeper.Keeper + packet ibcchanneltypes.Packet + b *mock.BankKeeperMock + n *mock.NexusMock + channelK *mock.ChannelKeeperMock + ibcK keeper.IBCKeeper + r axelarnet.RateLimiter + lockableCoin *nexusmock.LockableCoinMock ics20Packet ibctransfertypes.FungibleTokenPacketData message axelarnet.Message @@ -74,6 +77,14 @@ func TestHandleMessage(t *testing.T) { })) channelK.SendPacketFunc = func(sdk.Context, *captypes.Capability, ibcexported.PacketI) error { return nil } n = &mock.NexusMock{ + NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + lockableCoin = &nexusmock.LockableCoinMock{ + GetCoinFunc: func() sdk.Coin { return coin }, + GetOriginalCoinFunc: func(_ sdk.Context) sdk.Coin { return coin }, + } + + return lockableCoin, nil + }, SetNewMessageFunc: func(ctx sdk.Context, msg nexus.GeneralMessage) error { genMsg = msg return nil @@ -423,14 +434,15 @@ func TestHandleMessage(t *testing.T) { func TestHandleMessageWithToken(t *testing.T) { var ( - ctx sdk.Context - k keeper.Keeper - packet ibcchanneltypes.Packet - b *mock.BankKeeperMock - n *mock.NexusMock - channelK *mock.ChannelKeeperMock - ibcK keeper.IBCKeeper - r axelarnet.RateLimiter + ctx sdk.Context + k keeper.Keeper + packet ibcchanneltypes.Packet + b *mock.BankKeeperMock + n *mock.NexusMock + channelK *mock.ChannelKeeperMock + ibcK keeper.IBCKeeper + r axelarnet.RateLimiter + lockableCoin *nexusmock.LockableCoinMock denom string amount string @@ -479,7 +491,14 @@ func TestHandleMessageWithToken(t *testing.T) { })) channelK.SendPacketFunc = func(sdk.Context, *captypes.Capability, ibcexported.PacketI) error { return nil } + lockableCoin = &nexusmock.LockableCoinMock{ + GetCoinFunc: func() sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, + GetOriginalCoinFunc: func(_ sdk.Context) sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, + } n = &mock.NexusMock{ + NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + return lockableCoin, nil + }, SetNewMessageFunc: func(ctx sdk.Context, msg nexus.GeneralMessage) error { genMsg = msg return nil @@ -578,6 +597,18 @@ func TestHandleMessageWithToken(t *testing.T) { } } + lockCoin := func(success bool) func() { + if success { + return func() { + lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + } + } + + return func() { + lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + } + } + givenPacketWithMessageWithToken. When("asset is not registered on source chain", isAssetRegistered(srcChain, false)). Then("should return ack error", ackError()). @@ -592,13 +623,22 @@ func TestHandleMessageWithToken(t *testing.T) { givenPacketWithMessageWithToken. When("asset is registered on source chain", isAssetRegistered(srcChain, true)). When("asset is registered on dest chain", isAssetRegistered(destChain, true)). - When("rate limit is set", whenRateLimitIsSet(false)). + When("lock coin succeeds", lockCoin(true)). + When("rate limit is exceeded", whenRateLimitIsSet(false)). Then("should return ack error", ackError()). Run(t) givenPacketWithMessageWithToken. When("asset is registered on source chain", isAssetRegistered(srcChain, true)). When("asset is registered on dest chain", isAssetRegistered(destChain, true)). + When("lock coin fails", lockCoin(false)). + Then("should return ack error", ackError()). + Run(t) + + givenPacketWithMessageWithToken. + When("asset is registered on source chain", isAssetRegistered(srcChain, true)). + When("asset is registered on dest chain", isAssetRegistered(destChain, true)). + When("lock coin succeeds", lockCoin(true)). When("rate limit on another asset is set", whenRateLimitIsSet(true)). Then("should return ack success", func(t *testing.T) { assert.True(t, axelarnet.OnRecvMessage(ctx, k, ibcK, n, b, r, packet).Success()) @@ -633,24 +673,28 @@ func TestHandleMessageWithToken(t *testing.T) { feeAmount = funcs.MustOk(sdk.NewIntFromString(ics20Packet.Amount)).Sub(sdk.OneInt()) setFee(feeAmount, rand.AccAddr()) }). + When("lock coin succeeds", lockCoin(true)). Then("should return ack success", func(t *testing.T) { assert.True(t, axelarnet.OnRecvMessage(ctx, k, ibcK, n, b, r, packet).Success()) assert.Equal(t, genMsg.Status, nexus.Approved) - assert.True(t, genMsg.Asset.Amount.Equal(sdk.OneInt())) + assert.Len(t, n.NewLockableCoinCalls(), 2) + assert.Equal(t, n.NewLockableCoinCalls()[0].Coin.Amount, funcs.MustOk(sdk.NewIntFromString(amount))) + assert.Equal(t, n.NewLockableCoinCalls()[1].Coin.Amount, sdk.OneInt()) }). Run(t) } func TestHandleSendToken(t *testing.T) { var ( - ctx sdk.Context - k keeper.Keeper - packet ibcchanneltypes.Packet - b *mock.BankKeeperMock - n *mock.NexusMock - channelK *mock.ChannelKeeperMock - ibcK keeper.IBCKeeper - r axelarnet.RateLimiter + ctx sdk.Context + k keeper.Keeper + packet ibcchanneltypes.Packet + b *mock.BankKeeperMock + n *mock.NexusMock + channelK *mock.ChannelKeeperMock + ibcK keeper.IBCKeeper + r axelarnet.RateLimiter + lockableCoin *nexusmock.LockableCoinMock denom string amount string @@ -695,7 +739,14 @@ func TestHandleSendToken(t *testing.T) { })) channelK.SendPacketFunc = func(sdk.Context, *captypes.Capability, ibcexported.PacketI) error { return nil } + lockableCoin = &nexusmock.LockableCoinMock{ + GetCoinFunc: func() sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, + GetOriginalCoinFunc: func(_ sdk.Context) sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, + } n = &mock.NexusMock{ + NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + return lockableCoin, nil + }, SetNewMessageFunc: func(sdk.Context, nexus.GeneralMessage) error { return nil }, GetChainFunc: func(ctx sdk.Context, chain nexus.ChainName) (nexus.Chain, bool) { switch chain { @@ -781,6 +832,18 @@ func TestHandleSendToken(t *testing.T) { } } + lockCoin := func(success bool) func() { + if success { + return func() { + lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + } + } + + return func() { + lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + } + } + givenPacketWithSendToken. When("asset is not registered on source chain", isAssetRegistered(srcChain, false)). Then("should return ack error", ackError()). @@ -795,6 +858,7 @@ func TestHandleSendToken(t *testing.T) { givenPacketWithSendToken. When("asset is registered on source chain", isAssetRegistered(srcChain, true)). When("asset is registered on dest chain", isAssetRegistered(destChain, true)). + When("lock coin succeeds", lockCoin(true)). When("enqueue transfer failed", whenEnqueueTransferFailed). Then("should return ack error", ackError()). Run(t) @@ -802,6 +866,14 @@ func TestHandleSendToken(t *testing.T) { givenPacketWithSendToken. When("asset is registered on source chain", isAssetRegistered(srcChain, true)). When("asset is registered on dest chain", isAssetRegistered(destChain, true)). + When("lock coin fails", lockCoin(false)). + Then("should return ack error", ackError()). + Run(t) + + givenPacketWithSendToken. + When("asset is registered on source chain", isAssetRegistered(srcChain, true)). + When("asset is registered on dest chain", isAssetRegistered(destChain, true)). + When("lock coin succeeds", lockCoin(true)). Then("should return ack success", func(t *testing.T) { assert.True(t, axelarnet.OnRecvMessage(ctx, k, ibcK, n, b, r, packet).Success()) }). @@ -810,14 +882,15 @@ func TestHandleSendToken(t *testing.T) { func TestTokenAndDestChainNotFound(t *testing.T) { var ( - ctx sdk.Context - k keeper.Keeper - packet ibcchanneltypes.Packet - b *mock.BankKeeperMock - n *mock.NexusMock - channelK *mock.ChannelKeeperMock - ibcK keeper.IBCKeeper - r axelarnet.RateLimiter + ctx sdk.Context + k keeper.Keeper + packet ibcchanneltypes.Packet + b *mock.BankKeeperMock + n *mock.NexusMock + channelK *mock.ChannelKeeperMock + ibcK keeper.IBCKeeper + r axelarnet.RateLimiter + lockableCoin *nexusmock.LockableCoinMock ics20Packet ibctransfertypes.FungibleTokenPacketData gmpWithToken axelarnet.Message @@ -854,7 +927,11 @@ func TestTokenAndDestChainNotFound(t *testing.T) { AddrPrefix: "cosmos", })) channelK.SendPacketFunc = func(sdk.Context, *captypes.Capability, ibcexported.PacketI) error { return nil } + lockableCoin = &nexusmock.LockableCoinMock{} n = &mock.NexusMock{ + NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + return lockableCoin, nil + }, SetNewMessageFunc: func(ctx sdk.Context, msg nexus.GeneralMessage) error { return nil }, diff --git a/x/axelarnet/module_test.go b/x/axelarnet/module_test.go index 372ea1a3b..77999f2eb 100644 --- a/x/axelarnet/module_test.go +++ b/x/axelarnet/module_test.go @@ -25,8 +25,10 @@ import ( "github.com/axelarnetwork/axelar-core/x/axelarnet/types" "github.com/axelarnetwork/axelar-core/x/axelarnet/types/mock" "github.com/axelarnetwork/axelar-core/x/axelarnet/types/testutils" - "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexusmock "github.com/axelarnetwork/axelar-core/x/nexus/exported/mock" nexustestutils "github.com/axelarnetwork/axelar-core/x/nexus/exported/testutils" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" "github.com/axelarnetwork/utils/funcs" "github.com/axelarnetwork/utils/slices" . "github.com/axelarnetwork/utils/test" @@ -34,15 +36,16 @@ import ( func TestIBCModule(t *testing.T) { var ( - ctx sdk.Context - ibcModule axelarnet.AxelarnetIBCModule - k keeper.Keeper - n *mock.NexusMock - bankK *mock.BankKeeperMock + ctx sdk.Context + ibcModule axelarnet.AxelarnetIBCModule + k keeper.Keeper + n *mock.NexusMock + bankK *mock.BankKeeperMock + lockableCoin *nexusmock.LockableCoinMock ack channeltypes.Acknowledgement transfer types.IBCTransfer - message exported.GeneralMessage + message nexus.GeneralMessage transfers []types.IBCTransfer ) @@ -86,7 +89,12 @@ func TestIBCModule(t *testing.T) { transferSubspace := params.NewSubspace(encCfg.Codec, encCfg.Amino, sdk.NewKVStoreKey(ibctransfertypes.StoreKey), sdk.NewKVStoreKey("tTrasferKey"), ibctransfertypes.ModuleName) transferK := ibctransferkeeper.NewKeeper(encCfg.Codec, sdk.NewKVStoreKey("transfer"), transferSubspace, &mock.ChannelKeeperMock{}, &mock.ChannelKeeperMock{}, &mock.PortKeeperMock{}, accountK, bankK, scopedTransferK) - n = &mock.NexusMock{} + lockableCoin = &nexusmock.LockableCoinMock{} + n = &mock.NexusMock{ + NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { + return lockableCoin, nil + }, + } ibcModule = axelarnet.NewAxelarnetIBCModule(ibcTransfer.NewIBCModule(transferK), ibcK, axelarnet.NewRateLimiter(&k, n), n, bankK) }) @@ -119,19 +127,19 @@ func TestIBCModule(t *testing.T) { }) seqMapsToMessageID := When("packet seq maps to message ID", func() { - message = nexustestutils.RandomMessage(exported.Processing) + message = nexustestutils.RandomMessage(nexus.Processing) funcs.MustNoErr(k.SetSeqMessageIDMapping(ctx, ibctransfertypes.PortID, channelID, packetSeq, message.ID)) - n.GetMessageFunc = func(sdk.Context, string) (exported.GeneralMessage, bool) { return message, true } - n.IsAssetRegisteredFunc = func(sdk.Context, exported.Chain, string) bool { return true } + n.GetMessageFunc = func(sdk.Context, string) (nexus.GeneralMessage, bool) { return message, true } + n.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { return true } n.SetMessageFailedFunc = func(ctx sdk.Context, id string) error { if id == message.ID { - message.Status = exported.Failed + message.Status = nexus.Failed } return nil } - n.GetChainByNativeAssetFunc = func(sdk.Context, string) (exported.Chain, bool) { return exported.Chain{}, false } + n.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { return nexus.Chain{}, false } }) whenOnAck := When("on acknowledgement", func() { @@ -151,13 +159,25 @@ func TestIBCModule(t *testing.T) { }) whenChainIsActivated := When("chain is activated", func() { - n.GetChainFunc = func(ctx sdk.Context, chain exported.ChainName) (exported.Chain, bool) { return exported.Chain{}, true } - n.IsChainActivatedFunc = func(ctx sdk.Context, chain exported.Chain) bool { return true } - n.RateLimitTransferFunc = func(ctx sdk.Context, chain exported.ChainName, asset sdk.Coin, direction exported.TransferDirection) error { + n.GetChainFunc = func(ctx sdk.Context, chain nexus.ChainName) (nexus.Chain, bool) { return nexus.Chain{}, true } + n.IsChainActivatedFunc = func(ctx sdk.Context, chain nexus.Chain) bool { return true } + n.RateLimitTransferFunc = func(ctx sdk.Context, chain nexus.ChainName, asset sdk.Coin, direction nexus.TransferDirection) error { return nil } }) + lockCoin := func(success bool) func() { + if success { + return func() { + lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + } + } + + return func() { + lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + } + } + givenAnIBCModule. Branch( whenGetValidAckResult. @@ -171,10 +191,12 @@ func TestIBCModule(t *testing.T) { whenGetValidAckError. When2(whenChainIsActivated). When2(seqMapsToID). + When("lock coin succeeds", lockCoin(true)). When2(whenOnAck). Then("should set transfer to failed", func(t *testing.T) { transfer := funcs.MustOk(k.GetTransfer(ctx, transfer.ID)) assert.Equal(t, types.TransferFailed, transfer.Status) + assert.Len(t, lockableCoin.LockCalls(), 1) }), whenPendingTransfersExist. @@ -192,10 +214,12 @@ func TestIBCModule(t *testing.T) { seqMapsToID. When2(whenChainIsActivated). + When("lock coin succeeds", lockCoin(true)). When2(whenOnTimeout). Then("should set transfer to failed", func(t *testing.T) { transfer := funcs.MustOk(k.GetTransfer(ctx, transfer.ID)) assert.Equal(t, types.TransferFailed, transfer.Status) + assert.Len(t, lockableCoin.LockCalls(), 1) }), whenPendingTransfersExist. @@ -207,10 +231,11 @@ func TestIBCModule(t *testing.T) { whenGetValidAckError. When2(whenChainIsActivated). When2(seqMapsToMessageID). + When("lock coin succeeds", lockCoin(true)). When2(whenOnAck). Then("should set message to failed", func(t *testing.T) { - assert.Equal(t, exported.Failed, message.Status) - assert.Len(t, bankK.SendCoinsFromAccountToModuleCalls(), 1) + assert.Equal(t, nexus.Failed, message.Status) + assert.Len(t, lockableCoin.LockCalls(), 1) }), ).Run(t) } diff --git a/x/nexus/exported/mock/types.go b/x/nexus/exported/mock/types.go index 53bce9497..312e5cedf 100644 --- a/x/nexus/exported/mock/types.go +++ b/x/nexus/exported/mock/types.go @@ -580,9 +580,6 @@ var _ exported.LockableCoin = &LockableCoinMock{} // LockFunc: func(ctx types.Context, fromAddr types.AccAddress) error { // panic("mock out the Lock method") // }, -// SubFunc: func(coin types.Coin) exported.LockableCoin { -// panic("mock out the Sub method") -// }, // UnlockFunc: func(ctx types.Context, toAddr types.AccAddress) error { // panic("mock out the Unlock method") // }, @@ -602,9 +599,6 @@ type LockableCoinMock struct { // LockFunc mocks the Lock method. LockFunc func(ctx types.Context, fromAddr types.AccAddress) error - // SubFunc mocks the Sub method. - SubFunc func(coin types.Coin) exported.LockableCoin - // UnlockFunc mocks the Unlock method. UnlockFunc func(ctx types.Context, toAddr types.AccAddress) error @@ -625,11 +619,6 @@ type LockableCoinMock struct { // FromAddr is the fromAddr argument value. FromAddr types.AccAddress } - // Sub holds details about calls to the Sub method. - Sub []struct { - // Coin is the coin argument value. - Coin types.Coin - } // Unlock holds details about calls to the Unlock method. Unlock []struct { // Ctx is the ctx argument value. @@ -641,7 +630,6 @@ type LockableCoinMock struct { lockGetCoin sync.RWMutex lockGetOriginalCoin sync.RWMutex lockLock sync.RWMutex - lockSub sync.RWMutex lockUnlock sync.RWMutex } @@ -740,38 +728,6 @@ func (mock *LockableCoinMock) LockCalls() []struct { return calls } -// Sub calls SubFunc. -func (mock *LockableCoinMock) Sub(coin types.Coin) exported.LockableCoin { - if mock.SubFunc == nil { - panic("LockableCoinMock.SubFunc: method is nil but LockableCoin.Sub was just called") - } - callInfo := struct { - Coin types.Coin - }{ - Coin: coin, - } - mock.lockSub.Lock() - mock.calls.Sub = append(mock.calls.Sub, callInfo) - mock.lockSub.Unlock() - return mock.SubFunc(coin) -} - -// SubCalls gets all the calls that were made to Sub. -// Check the length with: -// -// len(mockedLockableCoin.SubCalls()) -func (mock *LockableCoinMock) SubCalls() []struct { - Coin types.Coin -} { - var calls []struct { - Coin types.Coin - } - mock.lockSub.RLock() - calls = mock.calls.Sub - mock.lockSub.RUnlock() - return calls -} - // Unlock calls UnlockFunc. func (mock *LockableCoinMock) Unlock(ctx types.Context, toAddr types.AccAddress) error { if mock.UnlockFunc == nil { From 2812f34df2a3a206262bcf8fdb9bba382dc09ae7 Mon Sep 17 00:00:00 2001 From: Sammy Date: Thu, 26 Sep 2024 02:52:43 -0400 Subject: [PATCH 06/11] add tests for lockable coin --- x/nexus/keeper/lockable_coin_test.go | 255 +++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 x/nexus/keeper/lockable_coin_test.go diff --git a/x/nexus/keeper/lockable_coin_test.go b/x/nexus/keeper/lockable_coin_test.go new file mode 100644 index 000000000..0fb06a988 --- /dev/null +++ b/x/nexus/keeper/lockable_coin_test.go @@ -0,0 +1,255 @@ +package keeper + +import ( + "fmt" + "testing" + + "github.com/axelarnetwork/axelar-core/testutils/fake" + "github.com/axelarnetwork/axelar-core/testutils/rand" + axelarnet "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" + "github.com/axelarnetwork/axelar-core/x/axelarnet/types/testutils" + "github.com/axelarnetwork/axelar-core/x/nexus/exported" + "github.com/axelarnetwork/axelar-core/x/nexus/types" + "github.com/axelarnetwork/axelar-core/x/nexus/types/mock" + "github.com/axelarnetwork/utils/funcs" + . "github.com/axelarnetwork/utils/test" + sdk "github.com/cosmos/cosmos-sdk/types" + ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + "github.com/stretchr/testify/assert" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" +) + +func TestLockableCoin(t *testing.T) { + var ( + ctx sdk.Context + nexus *mock.NexusMock + ibc *mock.IBCKeeperMock + bank *mock.BankKeeperMock + + coin sdk.Coin + trace ibctypes.DenomTrace + ) + + givenKeeper := Given("the nexus keeper", func() { + ctx = sdk.NewContext(fake.NewMultiStore(), tmproto.Header{}, false, log.TestingLogger()) + + nexus = &mock.NexusMock{} + ibc = &mock.IBCKeeperMock{} + bank = &mock.BankKeeperMock{} + }) + + whenCoinIsNative := When("coin is native", func() { + coin = sdk.NewCoin(rand.Denom(5, 10), sdk.NewInt(rand.PosI64())) + nexus.GetChainByNativeAssetFunc = func(ctx sdk.Context, asset string) (exported.Chain, bool) { + if asset == coin.Denom { + return axelarnet.Axelarnet, true + } + + return exported.Chain{}, false + } + }) + + whenCoinIsExternal := When("coin is external", func() { + coin = sdk.NewCoin(rand.Denom(5, 10), sdk.NewInt(rand.PosI64())) + nexus.GetChainByNativeAssetFunc = func(ctx sdk.Context, asset string) (exported.Chain, bool) { + return exported.Chain{}, false + } + nexus.IsAssetRegisteredFunc = func(ctx sdk.Context, chain exported.Chain, asset string) bool { + return chain == axelarnet.Axelarnet && asset == coin.Denom + } + }) + + whenCoinIsICS20 := When("coin is ICS20", func() { + path := testutils.RandomIBCPath() + trace = ibctypes.DenomTrace{ + Path: path, + BaseDenom: rand.Denom(5, 10), + } + + ibc.ParseIBCDenomFunc = func(ctx sdk.Context, ibcDenom string) (ibctypes.DenomTrace, error) { + if ibcDenom == coin.Denom { + return trace, nil + } + + return ibctypes.DenomTrace{}, fmt.Errorf("denom not found") + } + ibc.GetIBCPathFunc = func(ctx sdk.Context, chain exported.ChainName) (string, bool) { + if chain == axelarnet.Axelarnet.Name { + return path, true + } + + return "", false + } + nexus.GetChainByNativeAssetFunc = func(ctx sdk.Context, asset string) (exported.Chain, bool) { + if asset == trace.BaseDenom { + return axelarnet.Axelarnet, true + } + + return exported.Chain{}, false + } + + coin = sdk.NewCoin(trace.IBCDenom(), sdk.NewInt(rand.PosI64())) + }) + + t.Run("NewLockableCoin, GetCoin and GetOriginalCoin", func(t *testing.T) { + givenKeeper. + When2(whenCoinIsICS20). + Then("should create a new lockable coin of type ICS20", func(t *testing.T) { + lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin) + + assert.NoError(t, err) + assert.Equal(t, types.CoinType(types.ICS20), lockableCoin.coinType) + assert.Equal(t, sdk.NewCoin(trace.GetBaseDenom(), coin.Amount), lockableCoin.GetCoin()) + assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx)) + }). + Run(t) + + givenKeeper. + When2(whenCoinIsNative). + Then("should create a new lockable coin of type native", func(t *testing.T) { + lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin) + + assert.NoError(t, err) + assert.Equal(t, types.CoinType(types.Native), lockableCoin.coinType) + assert.Equal(t, coin, lockableCoin.GetCoin()) + assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx)) + }). + Run(t) + + givenKeeper. + When2(whenCoinIsExternal). + Then("should create a new lockable coin of type external", func(t *testing.T) { + lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin) + + assert.NoError(t, err) + assert.Equal(t, types.CoinType(types.External), lockableCoin.coinType) + assert.Equal(t, coin, lockableCoin.GetCoin()) + assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx)) + }). + Run(t) + }) + + t.Run("Lock", func(t *testing.T) { + givenKeeper. + When2(whenCoinIsICS20). + Then("should lock the coin", func(t *testing.T) { + bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil } + + lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + fromAddr := rand.AccAddr() + + err := lockableCoin.Lock(ctx, fromAddr) + + assert.NoError(t, err) + assert.Len(t, bank.SendCoinsCalls(), 1) + assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt) + assert.Equal(t, fromAddr, bank.SendCoinsCalls()[0].FromAddr) + assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].ToAddr) + }). + Run(t) + + givenKeeper. + When2(whenCoinIsNative). + Then("should lock the coin", func(t *testing.T) { + bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil } + + lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + fromAddr := rand.AccAddr() + + err := lockableCoin.Lock(ctx, fromAddr) + + assert.NoError(t, err) + assert.Len(t, bank.SendCoinsCalls(), 1) + assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt) + assert.Equal(t, fromAddr, bank.SendCoinsCalls()[0].FromAddr) + assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].ToAddr) + }). + Run(t) + + givenKeeper. + When2(whenCoinIsExternal). + Then("should burn the coin", func(t *testing.T) { + bank.SendCoinsFromAccountToModuleFunc = func(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error { + return nil + } + bank.BurnCoinsFunc = func(ctx sdk.Context, moduleName string, amt sdk.Coins) error { return nil } + + lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + fromAddr := rand.AccAddr() + + err := lockableCoin.Lock(ctx, fromAddr) + + assert.NoError(t, err) + assert.Len(t, bank.SendCoinsFromAccountToModuleCalls(), 1) + assert.Equal(t, fromAddr, bank.SendCoinsFromAccountToModuleCalls()[0].SenderAddr) + assert.Equal(t, types.ModuleName, bank.SendCoinsFromAccountToModuleCalls()[0].RecipientModule) + assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsFromAccountToModuleCalls()[0].Amt) + assert.Len(t, bank.BurnCoinsCalls(), 1) + assert.Equal(t, types.ModuleName, bank.BurnCoinsCalls()[0].ModuleName) + assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.BurnCoinsCalls()[0].Amt) + }). + Run(t) + }) + + t.Run("Unlock", func(t *testing.T) { + givenKeeper. + When2(whenCoinIsICS20). + Then("should unlock the coin", func(t *testing.T) { + bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil } + + lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + toAddr := rand.AccAddr() + + err := lockableCoin.Unlock(ctx, toAddr) + + assert.NoError(t, err) + assert.Len(t, bank.SendCoinsCalls(), 1) + assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt) + assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].FromAddr) + assert.Equal(t, toAddr, bank.SendCoinsCalls()[0].ToAddr) + }). + Run(t) + + givenKeeper. + When2(whenCoinIsNative). + Then("should unlock the coin", func(t *testing.T) { + bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil } + + lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + toAddr := rand.AccAddr() + + err := lockableCoin.Unlock(ctx, toAddr) + + assert.NoError(t, err) + assert.Len(t, bank.SendCoinsCalls(), 1) + assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt) + assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].FromAddr) + assert.Equal(t, toAddr, bank.SendCoinsCalls()[0].ToAddr) + }). + Run(t) + + givenKeeper. + When2(whenCoinIsExternal). + Then("should mint the coin", func(t *testing.T) { + bank.MintCoinsFunc = func(ctx sdk.Context, moduleName string, amt sdk.Coins) error { return nil } + bank.SendCoinsFromModuleToAccountFunc = func(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error { + return nil + } + + lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + toAddr := rand.AccAddr() + + err := lockableCoin.Unlock(ctx, toAddr) + + assert.NoError(t, err) + assert.Len(t, bank.MintCoinsCalls(), 1) + assert.Equal(t, types.ModuleName, bank.MintCoinsCalls()[0].ModuleName) + assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.MintCoinsCalls()[0].Amt) + assert.Len(t, bank.SendCoinsFromModuleToAccountCalls(), 1) + assert.Equal(t, types.ModuleName, bank.SendCoinsFromModuleToAccountCalls()[0].SenderModule) + assert.Equal(t, toAddr, bank.SendCoinsFromModuleToAccountCalls()[0].RecipientAddr) + }). + Run(t) + }) +} From f93dbcd0c0fb0c1b8fe7cc3c8fa726af89866b63 Mon Sep 17 00:00:00 2001 From: Sammy Date: Thu, 26 Sep 2024 03:51:53 -0400 Subject: [PATCH 07/11] move balances from axelarnet module account to nexus --- app/app.go | 2 + x/axelarnet/types/expected_keepers.go | 2 + x/axelarnet/types/mock/expected_keepers.go | 112 +++++++++++++++++++++ x/nexus/keeper/lockable_coin_test.go | 11 +- x/nexus/keeper/migrate.go | 18 ++-- x/nexus/keeper/migrate_test.go | 79 +++++++-------- x/nexus/module.go | 10 +- x/nexus/types/expected_keepers.go | 2 + x/nexus/types/mock/expected_keepers.go | 112 +++++++++++++++++++++ 9 files changed, 289 insertions(+), 59 deletions(-) diff --git a/app/app.go b/app/app.go index 561248016..94c22cce1 100644 --- a/app/app.go +++ b/app/app.go @@ -596,6 +596,8 @@ func initAppModules(keepers *KeeperCache, bApp *bam.BaseApp, encodingConfig axel GetKeeper[stakingkeeper.Keeper](keepers), GetKeeper[axelarnetKeeper.Keeper](keepers), GetKeeper[rewardKeeper.Keeper](keepers), + GetKeeper[bankkeeper.BaseKeeper](keepers), + GetKeeper[authkeeper.AccountKeeper](keepers), ), evm.NewAppModule( GetKeeper[evmKeeper.BaseKeeper](keepers), diff --git a/x/axelarnet/types/expected_keepers.go b/x/axelarnet/types/expected_keepers.go index b79b28568..c8c38c823 100644 --- a/x/axelarnet/types/expected_keepers.go +++ b/x/axelarnet/types/expected_keepers.go @@ -102,6 +102,8 @@ type BankKeeper interface { IsSendEnabledCoins(ctx sdk.Context, coins ...sdk.Coin) error BlockedAddr(addr sdk.AccAddress) bool SpendableBalance(ctx sdk.Context, address sdk.AccAddress, denom string) sdk.Coin + SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error + GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins } // IBCTransferKeeper provides functionality to manage IBC transfers diff --git a/x/axelarnet/types/mock/expected_keepers.go b/x/axelarnet/types/mock/expected_keepers.go index af78ed715..40eff4531 100644 --- a/x/axelarnet/types/mock/expected_keepers.go +++ b/x/axelarnet/types/mock/expected_keepers.go @@ -2914,6 +2914,9 @@ var _ axelarnettypes.BankKeeper = &BankKeeperMock{} // BurnCoinsFunc: func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error { // panic("mock out the BurnCoins method") // }, +// GetAllBalancesFunc: func(ctx cosmossdktypes.Context, addr cosmossdktypes.AccAddress) cosmossdktypes.Coins { +// panic("mock out the GetAllBalances method") +// }, // IsSendEnabledCoinFunc: func(ctx cosmossdktypes.Context, coin cosmossdktypes.Coin) bool { // panic("mock out the IsSendEnabledCoin method") // }, @@ -2932,6 +2935,9 @@ var _ axelarnettypes.BankKeeper = &BankKeeperMock{} // SendCoinsFromModuleToAccountFunc: func(ctx cosmossdktypes.Context, senderModule string, recipientAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error { // panic("mock out the SendCoinsFromModuleToAccount method") // }, +// SendCoinsFromModuleToModuleFunc: func(ctx cosmossdktypes.Context, senderModule string, recipientModule string, amt cosmossdktypes.Coins) error { +// panic("mock out the SendCoinsFromModuleToModule method") +// }, // SpendableBalanceFunc: func(ctx cosmossdktypes.Context, address cosmossdktypes.AccAddress, denom string) cosmossdktypes.Coin { // panic("mock out the SpendableBalance method") // }, @@ -2948,6 +2954,9 @@ type BankKeeperMock struct { // BurnCoinsFunc mocks the BurnCoins method. BurnCoinsFunc func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error + // GetAllBalancesFunc mocks the GetAllBalances method. + GetAllBalancesFunc func(ctx cosmossdktypes.Context, addr cosmossdktypes.AccAddress) cosmossdktypes.Coins + // IsSendEnabledCoinFunc mocks the IsSendEnabledCoin method. IsSendEnabledCoinFunc func(ctx cosmossdktypes.Context, coin cosmossdktypes.Coin) bool @@ -2966,6 +2975,9 @@ type BankKeeperMock struct { // SendCoinsFromModuleToAccountFunc mocks the SendCoinsFromModuleToAccount method. SendCoinsFromModuleToAccountFunc func(ctx cosmossdktypes.Context, senderModule string, recipientAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error + // SendCoinsFromModuleToModuleFunc mocks the SendCoinsFromModuleToModule method. + SendCoinsFromModuleToModuleFunc func(ctx cosmossdktypes.Context, senderModule string, recipientModule string, amt cosmossdktypes.Coins) error + // SpendableBalanceFunc mocks the SpendableBalance method. SpendableBalanceFunc func(ctx cosmossdktypes.Context, address cosmossdktypes.AccAddress, denom string) cosmossdktypes.Coin @@ -2985,6 +2997,13 @@ type BankKeeperMock struct { // Amt is the amt argument value. Amt cosmossdktypes.Coins } + // GetAllBalances holds details about calls to the GetAllBalances method. + GetAllBalances []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Addr is the addr argument value. + Addr cosmossdktypes.AccAddress + } // IsSendEnabledCoin holds details about calls to the IsSendEnabledCoin method. IsSendEnabledCoin []struct { // Ctx is the ctx argument value. @@ -3041,6 +3060,17 @@ type BankKeeperMock struct { // Amt is the amt argument value. Amt cosmossdktypes.Coins } + // SendCoinsFromModuleToModule holds details about calls to the SendCoinsFromModuleToModule method. + SendCoinsFromModuleToModule []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // SenderModule is the senderModule argument value. + SenderModule string + // RecipientModule is the recipientModule argument value. + RecipientModule string + // Amt is the amt argument value. + Amt cosmossdktypes.Coins + } // SpendableBalance holds details about calls to the SpendableBalance method. SpendableBalance []struct { // Ctx is the ctx argument value. @@ -3053,12 +3083,14 @@ type BankKeeperMock struct { } lockBlockedAddr sync.RWMutex lockBurnCoins sync.RWMutex + lockGetAllBalances sync.RWMutex lockIsSendEnabledCoin sync.RWMutex lockIsSendEnabledCoins sync.RWMutex lockMintCoins sync.RWMutex lockSendCoins sync.RWMutex lockSendCoinsFromAccountToModule sync.RWMutex lockSendCoinsFromModuleToAccount sync.RWMutex + lockSendCoinsFromModuleToModule sync.RWMutex lockSpendableBalance sync.RWMutex } @@ -3134,6 +3166,42 @@ func (mock *BankKeeperMock) BurnCoinsCalls() []struct { return calls } +// GetAllBalances calls GetAllBalancesFunc. +func (mock *BankKeeperMock) GetAllBalances(ctx cosmossdktypes.Context, addr cosmossdktypes.AccAddress) cosmossdktypes.Coins { + if mock.GetAllBalancesFunc == nil { + panic("BankKeeperMock.GetAllBalancesFunc: method is nil but BankKeeper.GetAllBalances was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Addr cosmossdktypes.AccAddress + }{ + Ctx: ctx, + Addr: addr, + } + mock.lockGetAllBalances.Lock() + mock.calls.GetAllBalances = append(mock.calls.GetAllBalances, callInfo) + mock.lockGetAllBalances.Unlock() + return mock.GetAllBalancesFunc(ctx, addr) +} + +// GetAllBalancesCalls gets all the calls that were made to GetAllBalances. +// Check the length with: +// +// len(mockedBankKeeper.GetAllBalancesCalls()) +func (mock *BankKeeperMock) GetAllBalancesCalls() []struct { + Ctx cosmossdktypes.Context + Addr cosmossdktypes.AccAddress +} { + var calls []struct { + Ctx cosmossdktypes.Context + Addr cosmossdktypes.AccAddress + } + mock.lockGetAllBalances.RLock() + calls = mock.calls.GetAllBalances + mock.lockGetAllBalances.RUnlock() + return calls +} + // IsSendEnabledCoin calls IsSendEnabledCoinFunc. func (mock *BankKeeperMock) IsSendEnabledCoin(ctx cosmossdktypes.Context, coin cosmossdktypes.Coin) bool { if mock.IsSendEnabledCoinFunc == nil { @@ -3378,6 +3446,50 @@ func (mock *BankKeeperMock) SendCoinsFromModuleToAccountCalls() []struct { return calls } +// SendCoinsFromModuleToModule calls SendCoinsFromModuleToModuleFunc. +func (mock *BankKeeperMock) SendCoinsFromModuleToModule(ctx cosmossdktypes.Context, senderModule string, recipientModule string, amt cosmossdktypes.Coins) error { + if mock.SendCoinsFromModuleToModuleFunc == nil { + panic("BankKeeperMock.SendCoinsFromModuleToModuleFunc: method is nil but BankKeeper.SendCoinsFromModuleToModule was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientModule string + Amt cosmossdktypes.Coins + }{ + Ctx: ctx, + SenderModule: senderModule, + RecipientModule: recipientModule, + Amt: amt, + } + mock.lockSendCoinsFromModuleToModule.Lock() + mock.calls.SendCoinsFromModuleToModule = append(mock.calls.SendCoinsFromModuleToModule, callInfo) + mock.lockSendCoinsFromModuleToModule.Unlock() + return mock.SendCoinsFromModuleToModuleFunc(ctx, senderModule, recipientModule, amt) +} + +// SendCoinsFromModuleToModuleCalls gets all the calls that were made to SendCoinsFromModuleToModule. +// Check the length with: +// +// len(mockedBankKeeper.SendCoinsFromModuleToModuleCalls()) +func (mock *BankKeeperMock) SendCoinsFromModuleToModuleCalls() []struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientModule string + Amt cosmossdktypes.Coins +} { + var calls []struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientModule string + Amt cosmossdktypes.Coins + } + mock.lockSendCoinsFromModuleToModule.RLock() + calls = mock.calls.SendCoinsFromModuleToModule + mock.lockSendCoinsFromModuleToModule.RUnlock() + return calls +} + // SpendableBalance calls SpendableBalanceFunc. func (mock *BankKeeperMock) SpendableBalance(ctx cosmossdktypes.Context, address cosmossdktypes.AccAddress, denom string) cosmossdktypes.Coin { if mock.SpendableBalanceFunc == nil { diff --git a/x/nexus/keeper/lockable_coin_test.go b/x/nexus/keeper/lockable_coin_test.go index 0fb06a988..70aa344c2 100644 --- a/x/nexus/keeper/lockable_coin_test.go +++ b/x/nexus/keeper/lockable_coin_test.go @@ -4,6 +4,12 @@ import ( "fmt" "testing" + sdk "github.com/cosmos/cosmos-sdk/types" + ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" + "github.com/stretchr/testify/assert" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/axelarnetwork/axelar-core/testutils/fake" "github.com/axelarnetwork/axelar-core/testutils/rand" axelarnet "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" @@ -13,11 +19,6 @@ import ( "github.com/axelarnetwork/axelar-core/x/nexus/types/mock" "github.com/axelarnetwork/utils/funcs" . "github.com/axelarnetwork/utils/test" - sdk "github.com/cosmos/cosmos-sdk/types" - ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" - "github.com/stretchr/testify/assert" - "github.com/tendermint/tendermint/libs/log" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) func TestLockableCoin(t *testing.T) { diff --git a/x/nexus/keeper/migrate.go b/x/nexus/keeper/migrate.go index 19a94133f..3c191deb8 100644 --- a/x/nexus/keeper/migrate.go +++ b/x/nexus/keeper/migrate.go @@ -3,23 +3,23 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" + axelarnettypes "github.com/axelarnetwork/axelar-core/x/axelarnet/types" "github.com/axelarnetwork/axelar-core/x/nexus/types" ) -// Migrate6to7 returns the handler that performs in-place store migrations -func Migrate6to7(k Keeper) func(ctx sdk.Context) error { +// Migrate7to8 returns the handler that performs in-place store migrations +func Migrate7to8(_ Keeper, bank types.BankKeeper, account types.AccountKeeper) func(ctx sdk.Context) error { return func(ctx sdk.Context) error { - addModuleParamGateway(ctx, k) - addModuleParamEndBlockerLimit(ctx, k) + if err := sendCoinsFromAxelarnetToNexus(ctx, bank, account); err != nil { + return err + } return nil } } -func addModuleParamGateway(ctx sdk.Context, k Keeper) { - k.params.Set(ctx, types.KeyGateway, types.DefaultParams().Gateway) -} +func sendCoinsFromAxelarnetToNexus(ctx sdk.Context, bank types.BankKeeper, account types.AccountKeeper) error { + balances := bank.GetAllBalances(ctx, account.GetModuleAddress(axelarnettypes.ModuleName)) -func addModuleParamEndBlockerLimit(ctx sdk.Context, k Keeper) { - k.params.Set(ctx, types.KeyEndBlockerLimit, types.DefaultParams().EndBlockerLimit) + return bank.SendCoinsFromModuleToModule(ctx, axelarnettypes.ModuleName, types.ModuleName, balances) } diff --git a/x/nexus/keeper/migrate_test.go b/x/nexus/keeper/migrate_test.go index 702c033bc..2a2d8d4cf 100644 --- a/x/nexus/keeper/migrate_test.go +++ b/x/nexus/keeper/migrate_test.go @@ -11,55 +11,50 @@ import ( "github.com/axelarnetwork/axelar-core/app" "github.com/axelarnetwork/axelar-core/testutils/fake" + "github.com/axelarnetwork/axelar-core/testutils/rand" + axelarnettypes "github.com/axelarnetwork/axelar-core/x/axelarnet/types" "github.com/axelarnetwork/axelar-core/x/nexus/keeper" "github.com/axelarnetwork/axelar-core/x/nexus/types" - . "github.com/axelarnetwork/utils/test" + "github.com/axelarnetwork/axelar-core/x/nexus/types/mock" ) -func TestMigrate6to7(t *testing.T) { +func TestMigrate7to8(t *testing.T) { encCfg := app.MakeEncodingConfig() subspace := params.NewSubspace(encCfg.Codec, encCfg.Amino, sdk.NewKVStoreKey("nexusKey"), sdk.NewKVStoreKey("tNexusKey"), "nexus") k := keeper.NewKeeper(encCfg.Codec, sdk.NewKVStoreKey("nexus"), subspace) ctx := sdk.NewContext(fake.NewMultiStore(), tmproto.Header{}, false, log.TestingLogger()) - Given("subspace is setup with params before migration", func() { - subspace.Set(ctx, types.KeyChainActivationThreshold, types.DefaultParams().ChainActivationThreshold) - subspace.Set(ctx, types.KeyChainMaintainerMissingVoteThreshold, types.DefaultParams().ChainMaintainerMissingVoteThreshold) - subspace.Set(ctx, types.KeyChainMaintainerIncorrectVoteThreshold, types.DefaultParams().ChainMaintainerIncorrectVoteThreshold) - subspace.Set(ctx, types.KeyChainMaintainerCheckWindow, types.DefaultParams().ChainMaintainerCheckWindow) - }). - When("", func() {}). - Then("the migration should add the new param with the default value", func(t *testing.T) { - actualGateway := sdk.AccAddress{} - actualEndBlockerLimit := uint64(0) - - assert.PanicsWithError(t, "UnmarshalJSON cannot decode empty bytes", func() { - subspace.Get(ctx, types.KeyGateway, &actualGateway) - }) - assert.PanicsWithError(t, "UnmarshalJSON cannot decode empty bytes", func() { - subspace.Get(ctx, types.KeyEndBlockerLimit, &actualEndBlockerLimit) - }) - assert.PanicsWithError(t, "UnmarshalJSON cannot decode empty bytes", func() { - k.GetParams(ctx) - }) - - keeper.Migrate6to7(k)(ctx) - - assert.NotPanics(t, func() { - subspace.Get(ctx, types.KeyGateway, &actualGateway) - }) - assert.NotPanics(t, func() { - subspace.Get(ctx, types.KeyEndBlockerLimit, &actualEndBlockerLimit) - }) - assert.NotPanics(t, func() { - k.GetParams(ctx) - }) - - assert.Equal(t, types.DefaultParams().Gateway, actualGateway) - assert.Equal(t, types.DefaultParams().Gateway, k.GetParams(ctx).Gateway) - assert.Equal(t, types.DefaultParams().EndBlockerLimit, actualEndBlockerLimit) - assert.Equal(t, types.DefaultParams().EndBlockerLimit, k.GetParams(ctx).EndBlockerLimit) - }). - Run(t) - + t.Run("sendCoinsFromAxelarnetToNexus", func(t *testing.T) { + bank := &mock.BankKeeperMock{} + account := &mock.AccountKeeperMock{} + balances := sdk.NewCoins(rand.Coin(), rand.Coin(), rand.Coin()) + axelarnetModuleAccount := rand.AccAddr() + nexusModuleAccount := rand.AccAddr() + + account.GetModuleAddressFunc = func(name string) sdk.AccAddress { + switch name { + case axelarnettypes.ModuleName: + return axelarnetModuleAccount + case types.ModuleName: + return nexusModuleAccount + default: + return sdk.AccAddress{} + } + } + bank.GetAllBalancesFunc = func(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { + if addr.Equals(axelarnetModuleAccount) { + return balances + } + return sdk.NewCoins() + } + bank.SendCoinsFromModuleToModuleFunc = func(ctx sdk.Context, sender, recipient string, coins sdk.Coins) error { return nil } + + err := keeper.Migrate7to8(k, bank, account)(ctx) + + assert.NoError(t, err) + assert.Len(t, bank.SendCoinsFromModuleToModuleCalls(), 1) + assert.Equal(t, axelarnettypes.ModuleName, bank.SendCoinsFromModuleToModuleCalls()[0].SenderModule) + assert.Equal(t, types.ModuleName, bank.SendCoinsFromModuleToModuleCalls()[0].RecipientModule) + assert.Equal(t, balances, bank.SendCoinsFromModuleToModuleCalls()[0].Amt) + }) } diff --git a/x/nexus/module.go b/x/nexus/module.go index 44c6d667d..0b5e7f657 100644 --- a/x/nexus/module.go +++ b/x/nexus/module.go @@ -89,10 +89,12 @@ type AppModule struct { staking types.StakingKeeper axelarnet types.AxelarnetKeeper reward types.RewardKeeper + bank types.BankKeeper + account types.AccountKeeper } // NewAppModule creates a new AppModule object -func NewAppModule(k keeper.Keeper, snapshotter types.Snapshotter, slashing types.SlashingKeeper, staking types.StakingKeeper, axelarnet types.AxelarnetKeeper, reward types.RewardKeeper) AppModule { +func NewAppModule(k keeper.Keeper, snapshotter types.Snapshotter, slashing types.SlashingKeeper, staking types.StakingKeeper, axelarnet types.AxelarnetKeeper, reward types.RewardKeeper, bank types.BankKeeper, account types.AccountKeeper) AppModule { return AppModule{ AppModuleBasic: AppModuleBasic{}, keeper: k, @@ -101,6 +103,8 @@ func NewAppModule(k keeper.Keeper, snapshotter types.Snapshotter, slashing types staking: staking, axelarnet: axelarnet, reward: reward, + bank: bank, + account: account, } } @@ -116,7 +120,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServiceServer(grpc.ServerWithSDKErrors{Server: cfg.MsgServer(), Err: types.ErrNexus, Logger: am.keeper.Logger}, msgServer) types.RegisterQueryServiceServer(cfg.QueryServer(), keeper.NewGRPCQuerier(am.keeper, am.axelarnet)) - err := cfg.RegisterMigration(types.ModuleName, 6, keeper.Migrate6to7(am.keeper)) + err := cfg.RegisterMigration(types.ModuleName, 7, keeper.Migrate7to8(am.keeper, am.bank, am.account)) if err != nil { panic(err) } @@ -167,4 +171,4 @@ func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 7 } +func (AppModule) ConsensusVersion() uint64 { return 8 } diff --git a/x/nexus/types/expected_keepers.go b/x/nexus/types/expected_keepers.go index 4a3a42bf4..12b18e119 100644 --- a/x/nexus/types/expected_keepers.go +++ b/x/nexus/types/expected_keepers.go @@ -111,6 +111,8 @@ type BankKeeper interface { SendCoins(ctx sdk.Context, fromAddr sdk.AccAddress, toAddr sdk.AccAddress, amt sdk.Coins) error SendCoinsFromAccountToModule(ctx sdk.Context, senderAddr sdk.AccAddress, recipientModule string, amt sdk.Coins) error SendCoinsFromModuleToAccount(ctx sdk.Context, senderModule string, recipientAddr sdk.AccAddress, amt sdk.Coins) error + SendCoinsFromModuleToModule(ctx sdk.Context, senderModule, recipientModule string, amt sdk.Coins) error + GetAllBalances(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins BurnCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error MintCoins(ctx sdk.Context, moduleName string, amt sdk.Coins) error } diff --git a/x/nexus/types/mock/expected_keepers.go b/x/nexus/types/mock/expected_keepers.go index dfce1e915..141f98b97 100644 --- a/x/nexus/types/mock/expected_keepers.go +++ b/x/nexus/types/mock/expected_keepers.go @@ -3269,6 +3269,9 @@ var _ nexustypes.BankKeeper = &BankKeeperMock{} // BurnCoinsFunc: func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error { // panic("mock out the BurnCoins method") // }, +// GetAllBalancesFunc: func(ctx cosmossdktypes.Context, addr cosmossdktypes.AccAddress) cosmossdktypes.Coins { +// panic("mock out the GetAllBalances method") +// }, // MintCoinsFunc: func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error { // panic("mock out the MintCoins method") // }, @@ -3281,6 +3284,9 @@ var _ nexustypes.BankKeeper = &BankKeeperMock{} // SendCoinsFromModuleToAccountFunc: func(ctx cosmossdktypes.Context, senderModule string, recipientAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error { // panic("mock out the SendCoinsFromModuleToAccount method") // }, +// SendCoinsFromModuleToModuleFunc: func(ctx cosmossdktypes.Context, senderModule string, recipientModule string, amt cosmossdktypes.Coins) error { +// panic("mock out the SendCoinsFromModuleToModule method") +// }, // } // // // use mockedBankKeeper in code that requires nexustypes.BankKeeper @@ -3291,6 +3297,9 @@ type BankKeeperMock struct { // BurnCoinsFunc mocks the BurnCoins method. BurnCoinsFunc func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error + // GetAllBalancesFunc mocks the GetAllBalances method. + GetAllBalancesFunc func(ctx cosmossdktypes.Context, addr cosmossdktypes.AccAddress) cosmossdktypes.Coins + // MintCoinsFunc mocks the MintCoins method. MintCoinsFunc func(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error @@ -3303,6 +3312,9 @@ type BankKeeperMock struct { // SendCoinsFromModuleToAccountFunc mocks the SendCoinsFromModuleToAccount method. SendCoinsFromModuleToAccountFunc func(ctx cosmossdktypes.Context, senderModule string, recipientAddr cosmossdktypes.AccAddress, amt cosmossdktypes.Coins) error + // SendCoinsFromModuleToModuleFunc mocks the SendCoinsFromModuleToModule method. + SendCoinsFromModuleToModuleFunc func(ctx cosmossdktypes.Context, senderModule string, recipientModule string, amt cosmossdktypes.Coins) error + // calls tracks calls to the methods. calls struct { // BurnCoins holds details about calls to the BurnCoins method. @@ -3314,6 +3326,13 @@ type BankKeeperMock struct { // Amt is the amt argument value. Amt cosmossdktypes.Coins } + // GetAllBalances holds details about calls to the GetAllBalances method. + GetAllBalances []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // Addr is the addr argument value. + Addr cosmossdktypes.AccAddress + } // MintCoins holds details about calls to the MintCoins method. MintCoins []struct { // Ctx is the ctx argument value. @@ -3356,12 +3375,25 @@ type BankKeeperMock struct { // Amt is the amt argument value. Amt cosmossdktypes.Coins } + // SendCoinsFromModuleToModule holds details about calls to the SendCoinsFromModuleToModule method. + SendCoinsFromModuleToModule []struct { + // Ctx is the ctx argument value. + Ctx cosmossdktypes.Context + // SenderModule is the senderModule argument value. + SenderModule string + // RecipientModule is the recipientModule argument value. + RecipientModule string + // Amt is the amt argument value. + Amt cosmossdktypes.Coins + } } lockBurnCoins sync.RWMutex + lockGetAllBalances sync.RWMutex lockMintCoins sync.RWMutex lockSendCoins sync.RWMutex lockSendCoinsFromAccountToModule sync.RWMutex lockSendCoinsFromModuleToAccount sync.RWMutex + lockSendCoinsFromModuleToModule sync.RWMutex } // BurnCoins calls BurnCoinsFunc. @@ -3404,6 +3436,42 @@ func (mock *BankKeeperMock) BurnCoinsCalls() []struct { return calls } +// GetAllBalances calls GetAllBalancesFunc. +func (mock *BankKeeperMock) GetAllBalances(ctx cosmossdktypes.Context, addr cosmossdktypes.AccAddress) cosmossdktypes.Coins { + if mock.GetAllBalancesFunc == nil { + panic("BankKeeperMock.GetAllBalancesFunc: method is nil but BankKeeper.GetAllBalances was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + Addr cosmossdktypes.AccAddress + }{ + Ctx: ctx, + Addr: addr, + } + mock.lockGetAllBalances.Lock() + mock.calls.GetAllBalances = append(mock.calls.GetAllBalances, callInfo) + mock.lockGetAllBalances.Unlock() + return mock.GetAllBalancesFunc(ctx, addr) +} + +// GetAllBalancesCalls gets all the calls that were made to GetAllBalances. +// Check the length with: +// +// len(mockedBankKeeper.GetAllBalancesCalls()) +func (mock *BankKeeperMock) GetAllBalancesCalls() []struct { + Ctx cosmossdktypes.Context + Addr cosmossdktypes.AccAddress +} { + var calls []struct { + Ctx cosmossdktypes.Context + Addr cosmossdktypes.AccAddress + } + mock.lockGetAllBalances.RLock() + calls = mock.calls.GetAllBalances + mock.lockGetAllBalances.RUnlock() + return calls +} + // MintCoins calls MintCoinsFunc. func (mock *BankKeeperMock) MintCoins(ctx cosmossdktypes.Context, moduleName string, amt cosmossdktypes.Coins) error { if mock.MintCoinsFunc == nil { @@ -3575,3 +3643,47 @@ func (mock *BankKeeperMock) SendCoinsFromModuleToAccountCalls() []struct { mock.lockSendCoinsFromModuleToAccount.RUnlock() return calls } + +// SendCoinsFromModuleToModule calls SendCoinsFromModuleToModuleFunc. +func (mock *BankKeeperMock) SendCoinsFromModuleToModule(ctx cosmossdktypes.Context, senderModule string, recipientModule string, amt cosmossdktypes.Coins) error { + if mock.SendCoinsFromModuleToModuleFunc == nil { + panic("BankKeeperMock.SendCoinsFromModuleToModuleFunc: method is nil but BankKeeper.SendCoinsFromModuleToModule was just called") + } + callInfo := struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientModule string + Amt cosmossdktypes.Coins + }{ + Ctx: ctx, + SenderModule: senderModule, + RecipientModule: recipientModule, + Amt: amt, + } + mock.lockSendCoinsFromModuleToModule.Lock() + mock.calls.SendCoinsFromModuleToModule = append(mock.calls.SendCoinsFromModuleToModule, callInfo) + mock.lockSendCoinsFromModuleToModule.Unlock() + return mock.SendCoinsFromModuleToModuleFunc(ctx, senderModule, recipientModule, amt) +} + +// SendCoinsFromModuleToModuleCalls gets all the calls that were made to SendCoinsFromModuleToModule. +// Check the length with: +// +// len(mockedBankKeeper.SendCoinsFromModuleToModuleCalls()) +func (mock *BankKeeperMock) SendCoinsFromModuleToModuleCalls() []struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientModule string + Amt cosmossdktypes.Coins +} { + var calls []struct { + Ctx cosmossdktypes.Context + SenderModule string + RecipientModule string + Amt cosmossdktypes.Coins + } + mock.lockSendCoinsFromModuleToModule.RLock() + calls = mock.calls.SendCoinsFromModuleToModule + mock.lockSendCoinsFromModuleToModule.RUnlock() + return calls +} From 7fcf49799a0ee257af9a935fb0fe55b9d6d26289 Mon Sep 17 00:00:00 2001 From: Haiyi Zhong Date: Sat, 5 Oct 2024 01:25:06 +0800 Subject: [PATCH 08/11] address comments --- app/app.go | 2 +- x/ante/check_refund_test.go | 5 +- x/axelarnet/keeper/coin_test.go | 147 ----------------------- x/axelarnet/keeper/message_route.go | 2 +- x/axelarnet/keeper/message_route_test.go | 6 +- x/axelarnet/keeper/msg_server.go | 6 +- x/axelarnet/keeper/msg_server_test.go | 16 +-- x/axelarnet/message_handler.go | 4 +- x/axelarnet/message_handler_test.go | 8 +- x/axelarnet/module.go | 4 +- x/axelarnet/module_test.go | 10 +- x/nexus/exported/mock/types.go | 84 ++++++------- x/nexus/exported/types.go | 4 +- x/nexus/keeper/lockable_coin.go | 21 ++-- x/nexus/keeper/lockable_coin_test.go | 16 +-- 15 files changed, 98 insertions(+), 237 deletions(-) delete mode 100644 x/axelarnet/keeper/coin_test.go diff --git a/app/app.go b/app/app.go index 94c22cce1..42df2cdf1 100644 --- a/app/app.go +++ b/app/app.go @@ -717,7 +717,7 @@ func InitModuleAccountPermissions() map[string][]string { stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, govtypes.ModuleName: {authtypes.Burner}, ibctransfertypes.ModuleName: {authtypes.Minter, authtypes.Burner}, - axelarnetTypes.ModuleName: {authtypes.Minter, authtypes.Burner}, + axelarnetTypes.ModuleName: nil, rewardTypes.ModuleName: {authtypes.Minter}, wasm.ModuleName: {authtypes.Burner}, nexusTypes.ModuleName: {authtypes.Minter, authtypes.Burner}, diff --git a/x/ante/check_refund_test.go b/x/ante/check_refund_test.go index fe384d805..4b654d0a8 100644 --- a/x/ante/check_refund_test.go +++ b/x/ante/check_refund_test.go @@ -31,6 +31,7 @@ import ( evm "github.com/axelarnetwork/axelar-core/x/evm/types" multisig "github.com/axelarnetwork/axelar-core/x/multisig/types" "github.com/axelarnetwork/axelar-core/x/nexus/exported" + nexustypes "github.com/axelarnetwork/axelar-core/x/nexus/types" rewardtypes "github.com/axelarnetwork/axelar-core/x/reward/types" snapshotkeeper "github.com/axelarnetwork/axelar-core/x/snapshot/keeper" snapshottypes "github.com/axelarnetwork/axelar-core/x/snapshot/types" @@ -200,8 +201,8 @@ func prepareAnteHandler(ctx sdk.Context, sender sdk.AccAddress, encConfig params bankKeeper := app.GetKeeper[bankkeeper.BaseKeeper](axelarApp.Keepers) bankKeeper.SetParams(ctx, banktypes.DefaultParams()) balance := sdk.NewCoins(sdk.NewInt64Coin("stake", 1e10)) - funcs.MustNoErr(bankKeeper.MintCoins(ctx, axelarnet.ModuleName, balance)) - funcs.MustNoErr(bankKeeper.SendCoinsFromModuleToAccount(ctx, axelarnet.ModuleName, sender, balance)) + funcs.MustNoErr(bankKeeper.MintCoins(ctx, nexustypes.ModuleName, balance)) + funcs.MustNoErr(bankKeeper.SendCoinsFromModuleToAccount(ctx, nexustypes.ModuleName, sender, balance)) stakingKeeper := app.GetKeeper[stakingkeeper.Keeper](axelarApp.Keepers) stakingKeeper.SetParams(ctx, stakingtypes.DefaultParams()) diff --git a/x/axelarnet/keeper/coin_test.go b/x/axelarnet/keeper/coin_test.go deleted file mode 100644 index f407035b3..000000000 --- a/x/axelarnet/keeper/coin_test.go +++ /dev/null @@ -1,147 +0,0 @@ -package keeper_test - -// import ( -// "testing" -// sdk "github.com/cosmos/cosmos-sdk/types" -// ibctypes "github.com/cosmos/ibc-go/v4/modules/apps/transfer/types" -// "github.com/stretchr/testify/assert" -// tmbytes "github.com/tendermint/tendermint/libs/bytes" -// "github.com/axelarnetwork/axelar-core/testutils/rand" -// "github.com/axelarnetwork/axelar-core/x/axelarnet/exported" -// "github.com/axelarnetwork/axelar-core/x/axelarnet/keeper" -// "github.com/axelarnetwork/axelar-core/x/axelarnet/types" -// "github.com/axelarnetwork/axelar-core/x/axelarnet/types/mock" -// "github.com/axelarnetwork/axelar-core/x/axelarnet/types/testutils" -// nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported" -// nexustestutils "github.com/axelarnetwork/axelar-core/x/nexus/exported/testutils" -// "github.com/axelarnetwork/utils/funcs" -// . "github.com/axelarnetwork/utils/test" -// ) - -// func TestCoin(t *testing.T) { -// var ( -// ctx sdk.Context -// nexusK *mock.NexusMock -// bankK *mock.BankKeeperMock -// transferK *mock.IBCTransferKeeperMock -// ibcK keeper.IBCKeeper -// chain nexus.Chain -// coin keeper.Coin -// trace ibctypes.DenomTrace -// ) - -// givenAKeeper := Given("a keeper", func() { -// ctx2, k, _, _ := setup() -// ctx = ctx2 -// nexusK = &mock.NexusMock{} -// bankK = &mock.BankKeeperMock{} -// transferK = &mock.IBCTransferKeeperMock{} -// ibcK = keeper.NewIBCKeeper(k, transferK) -// bankK.SendCoinsFromAccountToModuleFunc = func(sdk.Context, sdk.AccAddress, string, sdk.Coins) error { -// return nil -// } -// bankK.BurnCoinsFunc = func(sdk.Context, string, sdk.Coins) error { -// return nil -// } -// bankK.SendCoinsFunc = func(sdk.Context, sdk.AccAddress, sdk.AccAddress, sdk.Coins) error { -// return nil -// } -// bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { -// return coin.Coin -// } -// }) - -// whenCoinIsNative := When("coin is native", func() { -// nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { -// return exported.Axelarnet, true -// } -// coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(exported.NativeAsset, sdk.NewInt(rand.PosI64())))) -// }) - -// whenCoinIsExternal := When("coin is external", func() { -// nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { -// return nexustestutils.RandomChain(), true -// } -// nexusK.IsAssetRegisteredFunc = func(sdk.Context, nexus.Chain, string) bool { -// return true -// } -// coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(rand.Denom(5, 10), sdk.NewInt(rand.PosI64())))) -// }) - -// whenCoinIsICS20 := When("coin is from ICS20", func() { -// // setup -// path := testutils.RandomIBCPath() -// chain = nexustestutils.RandomChain() -// trace = ibctypes.DenomTrace{ -// Path: path, -// BaseDenom: rand.Denom(5, 10), -// } -// transferK.GetDenomTraceFunc = func(ctx sdk.Context, denomTraceHash tmbytes.HexBytes) (ibctypes.DenomTrace, bool) { -// return trace, true -// } - -// funcs.MustNoErr(ibcK.SetCosmosChain(ctx, types.CosmosChain{ -// Name: chain.Name, -// AddrPrefix: rand.StrBetween(1, 10), -// IBCPath: path, -// })) - -// coin = funcs.Must(keeper.NewCoin(ctx, ibcK, nexusK, sdk.NewCoin(trace.IBCDenom(), sdk.NewInt(rand.PosI64())))) - -// nexusK.GetChainFunc = func(sdk.Context, nexus.ChainName) (nexus.Chain, bool) { -// return chain, true -// } -// nexusK.GetChainByNativeAssetFunc = func(sdk.Context, string) (nexus.Chain, bool) { -// return chain, true -// } -// }) - -// givenAKeeper. -// Branch( -// whenCoinIsNative. -// Then("should Lock native coin in escrow account", func(t *testing.T) { -// err := coin.Lock(bankK, rand.AccAddr()) -// assert.NoError(t, err) -// assert.Len(t, bankK.SendCoinsCalls(), 1) -// }), -// whenCoinIsExternal. -// Then("should burn external token", func(t *testing.T) { -// err := coin.Lock(bankK, rand.AccAddr()) -// assert.NoError(t, err) -// assert.Len(t, bankK.SendCoinsFromAccountToModuleCalls(), 1) -// assert.Len(t, bankK.BurnCoinsCalls(), 1) -// }), -// whenCoinIsICS20. -// When("coin is greater than bank balance", func() { -// bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { -// return sdk.NewCoin(trace.IBCDenom(), coin.Amount.Sub(sdk.OneInt())) -// } -// }). -// Then("should return error", func(t *testing.T) { -// err := coin.Lock(bankK, rand.AccAddr()) -// assert.ErrorContains(t, err, "is greater than account balance") -// }), -// whenCoinIsICS20. -// When("coin equals to bank balance", func() { -// bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { -// return sdk.NewCoin(trace.IBCDenom(), coin.Amount) -// } -// }). -// Then("should Lock ICS20 coin in escrow account", func(t *testing.T) { -// err := coin.Lock(bankK, rand.AccAddr()) -// assert.NoError(t, err) -// assert.Len(t, bankK.SendCoinsCalls(), 1) -// }), -// whenCoinIsICS20. -// When("coin is less than bank balance", func() { -// bankK.SpendableBalanceFunc = func(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin { -// return sdk.NewCoin(trace.IBCDenom(), coin.Amount.Add(sdk.OneInt())) -// } -// }). -// Then("should Lock ICS20 coin in escrow account", func(t *testing.T) { -// err := coin.Lock(bankK, rand.AccAddr()) -// assert.NoError(t, err) -// assert.Len(t, bankK.SendCoinsCalls(), 1) -// }), -// ).Run(t) -// } diff --git a/x/axelarnet/keeper/message_route.go b/x/axelarnet/keeper/message_route.go index 29703975c..f0841418a 100644 --- a/x/axelarnet/keeper/message_route.go +++ b/x/axelarnet/keeper/message_route.go @@ -82,7 +82,7 @@ func escrowAssetToMessageSender( return sdk.Coin{}, err } - return coin.GetOriginalCoin(ctx), coin.Unlock(ctx, types.AxelarIBCAccount) + return coin.GetOriginalCoin(ctx), coin.UnlockTo(ctx, types.AxelarIBCAccount) default: return sdk.Coin{}, fmt.Errorf("unrecognized message type") } diff --git a/x/axelarnet/keeper/message_route_test.go b/x/axelarnet/keeper/message_route_test.go index d51f9817e..b8f3d4ce3 100644 --- a/x/axelarnet/keeper/message_route_test.go +++ b/x/axelarnet/keeper/message_route_test.go @@ -205,7 +205,7 @@ func TestNewMessageRoute(t *testing.T) { nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { lockableCoin = &nexusmock.LockableCoinMock{ GetOriginalCoinFunc: func(ctx sdk.Context) sdk.Coin { return coin }, - UnlockFunc: func(ctx sdk.Context, toAddr sdk.AccAddress) error { return nil }, + UnlockToFunc: func(ctx sdk.Context, toAddr sdk.AccAddress) error { return nil }, } return lockableCoin, nil @@ -217,8 +217,8 @@ func TestNewMessageRoute(t *testing.T) { assert.NoError(t, route(ctx, routingCtx, msg)) - assert.Len(t, lockableCoin.UnlockCalls(), 1) - assert.Equal(t, types.AxelarIBCAccount, lockableCoin.UnlockCalls()[0].ToAddr) + assert.Len(t, lockableCoin.UnlockToCalls(), 1) + assert.Equal(t, types.AxelarIBCAccount, lockableCoin.UnlockToCalls()[0].ToAddr) assert.Len(t, ibcK.SendMessageCalls(), 1) assert.Equal(t, msg.Recipient, ibcK.SendMessageCalls()[0].Recipient) diff --git a/x/axelarnet/keeper/msg_server.go b/x/axelarnet/keeper/msg_server.go index 5574c6642..ec71460bc 100644 --- a/x/axelarnet/keeper/msg_server.go +++ b/x/axelarnet/keeper/msg_server.go @@ -190,7 +190,7 @@ func (s msgServer) ConfirmDeposit(c context.Context, req *types.ConfirmDepositRe return nil, err } - if err := normalizedCoin.Lock(ctx, req.DepositAddress); err != nil { + if err := normalizedCoin.LockFrom(ctx, req.DepositAddress); err != nil { return nil, err } @@ -409,7 +409,7 @@ func (s msgServer) RouteIBCTransfers(c context.Context, _ *types.RouteIBCTransfe continue } - if err := coin.Unlock(ctx, types.AxelarIBCAccount); err != nil { + if err := coin.UnlockTo(ctx, types.AxelarIBCAccount); err != nil { s.Logger(ctx).Error(fmt.Sprintf("failed to route IBC transfer %s: %s", p.String(), err)) continue } @@ -504,7 +504,7 @@ func transfer(ctx sdk.Context, k Keeper, n types.Nexus, b types.BankKeeper, ibc return err } - if err := c.Unlock(ctx, recipient); err != nil { + if err := c.UnlockTo(ctx, recipient); err != nil { return err } diff --git a/x/axelarnet/keeper/msg_server_test.go b/x/axelarnet/keeper/msg_server_test.go index 41cfc3752..dee968cd8 100644 --- a/x/axelarnet/keeper/msg_server_test.go +++ b/x/axelarnet/keeper/msg_server_test.go @@ -236,7 +236,7 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { When("suceeded to create a lockable coin but lock fails", func() { nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { lockbleCoin := &nexusmock.LockableCoinMock{ - LockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + LockFromFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("failed to lock coin") }, } @@ -253,7 +253,7 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { When("suceeded to create a lockable coin but lock succeeds", func() { nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { lockbleCoin := &nexusmock.LockableCoinMock{ - LockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + LockFromFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil }, GetCoinFunc: func() sdk.Coin { @@ -314,7 +314,7 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { unlocksCoinSucceeds := When("unlock coins succeeds", func() { lockableCoin = &nexusmock.LockableCoinMock{ - UnlockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + UnlockToFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil }, } @@ -348,7 +348,7 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { whenHasPendingTransfers. When("unlock coins fails", func() { lockableCoin = &nexusmock.LockableCoinMock{ - UnlockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + UnlockToFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("failed to unlock coin") }, } @@ -372,7 +372,7 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { assert.NoError(t, err) assert.Len(t, nexusK.ArchivePendingTransferCalls(), 1) - assert.Len(t, lockableCoin.UnlockCalls(), 1) + assert.Len(t, lockableCoin.UnlockToCalls(), 1) }), When("has many pending transfers", func() { @@ -390,7 +390,7 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { assert.NoError(t, err) assert.Len(t, nexusK.ArchivePendingTransferCalls(), transferLimit) - assert.Len(t, lockableCoin.UnlockCalls(), transferLimit) + assert.Len(t, lockableCoin.UnlockToCalls(), transferLimit) }), ).Run(t) }) @@ -495,7 +495,7 @@ func TestHandleMsgRouteIBCTransfers(t *testing.T) { When2(requestIsMade). When("unlock coin succeeds", func() { lockableCoin = &nexusmock.LockableCoinMock{ - UnlockFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { + UnlockToFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil }, GetOriginalCoinFunc: func(ctx sdk.Context) sdk.Coin { @@ -512,7 +512,7 @@ func TestHandleMsgRouteIBCTransfers(t *testing.T) { assert.NoError(t, err) assert.Len(t, nexusK.ArchivePendingTransferCalls(), transfersNum, fmt.Sprintf("expected %d got %d", transfersNum, len(nexusK.ArchivePendingTransferCalls()))) - assert.Len(t, lockableCoin.UnlockCalls(), transfersNum) + assert.Len(t, lockableCoin.UnlockToCalls(), transfersNum) }), ).Run(t) }) diff --git a/x/axelarnet/message_handler.go b/x/axelarnet/message_handler.go index 4aab0db7e..efd9a9e66 100644 --- a/x/axelarnet/message_handler.go +++ b/x/axelarnet/message_handler.go @@ -292,7 +292,7 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, return err } - if err = token.Lock(ctx, types.AxelarIBCAccount); err != nil { + if err = token.LockFrom(ctx, types.AxelarIBCAccount); err != nil { return err } @@ -327,7 +327,7 @@ func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossCh destChain := funcs.MustOk(n.GetChain(ctx, nexus.ChainName(msg.DestinationChain))) crossChainAddr := nexus.CrossChainAddress{Chain: destChain, Address: msg.DestinationAddress} - if err := token.Lock(ctx, types.AxelarIBCAccount); err != nil { + if err := token.LockFrom(ctx, types.AxelarIBCAccount); err != nil { return err } diff --git a/x/axelarnet/message_handler_test.go b/x/axelarnet/message_handler_test.go index 726040d59..42a7d5087 100644 --- a/x/axelarnet/message_handler_test.go +++ b/x/axelarnet/message_handler_test.go @@ -600,12 +600,12 @@ func TestHandleMessageWithToken(t *testing.T) { lockCoin := func(success bool) func() { if success { return func() { - lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } } } return func() { - lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } } } @@ -835,12 +835,12 @@ func TestHandleSendToken(t *testing.T) { lockCoin := func(success bool) func() { if success { return func() { - lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } } } return func() { - lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } } } diff --git a/x/axelarnet/module.go b/x/axelarnet/module.go index be94430ed..304865c0a 100644 --- a/x/axelarnet/module.go +++ b/x/axelarnet/module.go @@ -347,7 +347,7 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe return err } - err = coin.Lock(ctx, types.AxelarIBCAccount) + err = coin.LockFrom(ctx, types.AxelarIBCAccount) if err != nil { return err } @@ -373,7 +373,7 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe return err } - err = coin.Lock(ctx, types.AxelarIBCAccount) + err = coin.LockFrom(ctx, types.AxelarIBCAccount) if err != nil { return err } diff --git a/x/axelarnet/module_test.go b/x/axelarnet/module_test.go index 77999f2eb..0f6b53060 100644 --- a/x/axelarnet/module_test.go +++ b/x/axelarnet/module_test.go @@ -169,12 +169,12 @@ func TestIBCModule(t *testing.T) { lockCoin := func(success bool) func() { if success { return func() { - lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } } } return func() { - lockableCoin.LockFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } } } @@ -196,7 +196,7 @@ func TestIBCModule(t *testing.T) { Then("should set transfer to failed", func(t *testing.T) { transfer := funcs.MustOk(k.GetTransfer(ctx, transfer.ID)) assert.Equal(t, types.TransferFailed, transfer.Status) - assert.Len(t, lockableCoin.LockCalls(), 1) + assert.Len(t, lockableCoin.LockFromCalls(), 1) }), whenPendingTransfersExist. @@ -219,7 +219,7 @@ func TestIBCModule(t *testing.T) { Then("should set transfer to failed", func(t *testing.T) { transfer := funcs.MustOk(k.GetTransfer(ctx, transfer.ID)) assert.Equal(t, types.TransferFailed, transfer.Status) - assert.Len(t, lockableCoin.LockCalls(), 1) + assert.Len(t, lockableCoin.LockFromCalls(), 1) }), whenPendingTransfersExist. @@ -235,7 +235,7 @@ func TestIBCModule(t *testing.T) { When2(whenOnAck). Then("should set message to failed", func(t *testing.T) { assert.Equal(t, nexus.Failed, message.Status) - assert.Len(t, lockableCoin.LockCalls(), 1) + assert.Len(t, lockableCoin.LockFromCalls(), 1) }), ).Run(t) } diff --git a/x/nexus/exported/mock/types.go b/x/nexus/exported/mock/types.go index 312e5cedf..992726699 100644 --- a/x/nexus/exported/mock/types.go +++ b/x/nexus/exported/mock/types.go @@ -577,11 +577,11 @@ var _ exported.LockableCoin = &LockableCoinMock{} // GetOriginalCoinFunc: func(ctx types.Context) types.Coin { // panic("mock out the GetOriginalCoin method") // }, -// LockFunc: func(ctx types.Context, fromAddr types.AccAddress) error { -// panic("mock out the Lock method") +// LockFromFunc: func(ctx types.Context, fromAddr types.AccAddress) error { +// panic("mock out the LockFrom method") // }, -// UnlockFunc: func(ctx types.Context, toAddr types.AccAddress) error { -// panic("mock out the Unlock method") +// UnlockToFunc: func(ctx types.Context, toAddr types.AccAddress) error { +// panic("mock out the UnlockTo method") // }, // } // @@ -596,11 +596,11 @@ type LockableCoinMock struct { // GetOriginalCoinFunc mocks the GetOriginalCoin method. GetOriginalCoinFunc func(ctx types.Context) types.Coin - // LockFunc mocks the Lock method. - LockFunc func(ctx types.Context, fromAddr types.AccAddress) error + // LockFromFunc mocks the LockFrom method. + LockFromFunc func(ctx types.Context, fromAddr types.AccAddress) error - // UnlockFunc mocks the Unlock method. - UnlockFunc func(ctx types.Context, toAddr types.AccAddress) error + // UnlockToFunc mocks the UnlockTo method. + UnlockToFunc func(ctx types.Context, toAddr types.AccAddress) error // calls tracks calls to the methods. calls struct { @@ -612,15 +612,15 @@ type LockableCoinMock struct { // Ctx is the ctx argument value. Ctx types.Context } - // Lock holds details about calls to the Lock method. - Lock []struct { + // LockFrom holds details about calls to the LockFrom method. + LockFrom []struct { // Ctx is the ctx argument value. Ctx types.Context // FromAddr is the fromAddr argument value. FromAddr types.AccAddress } - // Unlock holds details about calls to the Unlock method. - Unlock []struct { + // UnlockTo holds details about calls to the UnlockTo method. + UnlockTo []struct { // Ctx is the ctx argument value. Ctx types.Context // ToAddr is the toAddr argument value. @@ -629,8 +629,8 @@ type LockableCoinMock struct { } lockGetCoin sync.RWMutex lockGetOriginalCoin sync.RWMutex - lockLock sync.RWMutex - lockUnlock sync.RWMutex + lockLockFrom sync.RWMutex + lockUnlockTo sync.RWMutex } // GetCoin calls GetCoinFunc. @@ -692,10 +692,10 @@ func (mock *LockableCoinMock) GetOriginalCoinCalls() []struct { return calls } -// Lock calls LockFunc. -func (mock *LockableCoinMock) Lock(ctx types.Context, fromAddr types.AccAddress) error { - if mock.LockFunc == nil { - panic("LockableCoinMock.LockFunc: method is nil but LockableCoin.Lock was just called") +// LockFrom calls LockFromFunc. +func (mock *LockableCoinMock) LockFrom(ctx types.Context, fromAddr types.AccAddress) error { + if mock.LockFromFunc == nil { + panic("LockableCoinMock.LockFromFunc: method is nil but LockableCoin.LockFrom was just called") } callInfo := struct { Ctx types.Context @@ -704,17 +704,17 @@ func (mock *LockableCoinMock) Lock(ctx types.Context, fromAddr types.AccAddress) Ctx: ctx, FromAddr: fromAddr, } - mock.lockLock.Lock() - mock.calls.Lock = append(mock.calls.Lock, callInfo) - mock.lockLock.Unlock() - return mock.LockFunc(ctx, fromAddr) + mock.lockLockFrom.Lock() + mock.calls.LockFrom = append(mock.calls.LockFrom, callInfo) + mock.lockLockFrom.Unlock() + return mock.LockFromFunc(ctx, fromAddr) } -// LockCalls gets all the calls that were made to Lock. +// LockFromCalls gets all the calls that were made to LockFrom. // Check the length with: // -// len(mockedLockableCoin.LockCalls()) -func (mock *LockableCoinMock) LockCalls() []struct { +// len(mockedLockableCoin.LockFromCalls()) +func (mock *LockableCoinMock) LockFromCalls() []struct { Ctx types.Context FromAddr types.AccAddress } { @@ -722,16 +722,16 @@ func (mock *LockableCoinMock) LockCalls() []struct { Ctx types.Context FromAddr types.AccAddress } - mock.lockLock.RLock() - calls = mock.calls.Lock - mock.lockLock.RUnlock() + mock.lockLockFrom.RLock() + calls = mock.calls.LockFrom + mock.lockLockFrom.RUnlock() return calls } -// Unlock calls UnlockFunc. -func (mock *LockableCoinMock) Unlock(ctx types.Context, toAddr types.AccAddress) error { - if mock.UnlockFunc == nil { - panic("LockableCoinMock.UnlockFunc: method is nil but LockableCoin.Unlock was just called") +// UnlockTo calls UnlockToFunc. +func (mock *LockableCoinMock) UnlockTo(ctx types.Context, toAddr types.AccAddress) error { + if mock.UnlockToFunc == nil { + panic("LockableCoinMock.UnlockToFunc: method is nil but LockableCoin.UnlockTo was just called") } callInfo := struct { Ctx types.Context @@ -740,17 +740,17 @@ func (mock *LockableCoinMock) Unlock(ctx types.Context, toAddr types.AccAddress) Ctx: ctx, ToAddr: toAddr, } - mock.lockUnlock.Lock() - mock.calls.Unlock = append(mock.calls.Unlock, callInfo) - mock.lockUnlock.Unlock() - return mock.UnlockFunc(ctx, toAddr) + mock.lockUnlockTo.Lock() + mock.calls.UnlockTo = append(mock.calls.UnlockTo, callInfo) + mock.lockUnlockTo.Unlock() + return mock.UnlockToFunc(ctx, toAddr) } -// UnlockCalls gets all the calls that were made to Unlock. +// UnlockToCalls gets all the calls that were made to UnlockTo. // Check the length with: // -// len(mockedLockableCoin.UnlockCalls()) -func (mock *LockableCoinMock) UnlockCalls() []struct { +// len(mockedLockableCoin.UnlockToCalls()) +func (mock *LockableCoinMock) UnlockToCalls() []struct { Ctx types.Context ToAddr types.AccAddress } { @@ -758,8 +758,8 @@ func (mock *LockableCoinMock) UnlockCalls() []struct { Ctx types.Context ToAddr types.AccAddress } - mock.lockUnlock.RLock() - calls = mock.calls.Unlock - mock.lockUnlock.RUnlock() + mock.lockUnlockTo.RLock() + calls = mock.calls.UnlockTo + mock.lockUnlockTo.RUnlock() return calls } diff --git a/x/nexus/exported/types.go b/x/nexus/exported/types.go index 4462ba1ab..213e52fed 100644 --- a/x/nexus/exported/types.go +++ b/x/nexus/exported/types.go @@ -25,8 +25,8 @@ import ( type LockableCoin interface { GetCoin() sdk.Coin GetOriginalCoin(ctx sdk.Context) sdk.Coin - Lock(ctx sdk.Context, fromAddr sdk.AccAddress) error - Unlock(ctx sdk.Context, toAddr sdk.AccAddress) error + LockFrom(ctx sdk.Context, fromAddr sdk.AccAddress) error + UnlockTo(ctx sdk.Context, toAddr sdk.AccAddress) error } // AddressValidator defines a function that implements address verification upon a request to link addresses diff --git a/x/nexus/keeper/lockable_coin.go b/x/nexus/keeper/lockable_coin.go index c9e580443..ad0d88cb4 100644 --- a/x/nexus/keeper/lockable_coin.go +++ b/x/nexus/keeper/lockable_coin.go @@ -29,7 +29,9 @@ type lockableCoin struct { // newLockableCoin creates a coin struct, assign a coin type and normalize the denom if it's a ICS20 token func newLockableCoin(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (lockableCoin, error) { - coinType, err := getCoinType(ctx, nexus, coin.GetDenom()) + denom := coin.GetDenom() + + coinType, err := getCoinType(ctx, nexus, denom) if err != nil { return lockableCoin{}, err } @@ -37,7 +39,7 @@ func newLockableCoin(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, ba // If coin type is ICS20, we need to normalize it to convert from 'ibc/{hash}' // to native asset denom so that nexus could recognize it if coinType == types.ICS20 { - denomTrace, err := ibc.ParseIBCDenom(ctx, coin.GetDenom()) + denomTrace, err := ibc.ParseIBCDenom(ctx, denom) if err != nil { return lockableCoin{}, err } @@ -52,9 +54,14 @@ func newLockableCoin(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, ba ibc: ibc, bank: bank, } - if _, err := c.getOriginalCoin(ctx); err != nil { + + originalCoin, err := c.getOriginalCoin(ctx) + if err != nil { return lockableCoin{}, err } + if originalCoin.GetDenom() != denom { + return lockableCoin{}, fmt.Errorf("denom mismatch, expected %s, got %s", denom, originalCoin.GetDenom()) + } return c, nil } @@ -69,8 +76,8 @@ func (c lockableCoin) GetOriginalCoin(ctx sdk.Context) sdk.Coin { return funcs.Must(c.getOriginalCoin(ctx)) } -// Lock locks the given coin from the given address -func (c lockableCoin) Lock(ctx sdk.Context, fromAddr sdk.AccAddress) error { +// LockFrom locks the given coin from the given address +func (c lockableCoin) LockFrom(ctx sdk.Context, fromAddr sdk.AccAddress) error { coin := c.GetOriginalCoin(ctx) switch c.coinType { @@ -83,8 +90,8 @@ func (c lockableCoin) Lock(ctx sdk.Context, fromAddr sdk.AccAddress) error { } } -// Unlock unlocks the given coin to the given address -func (c lockableCoin) Unlock(ctx sdk.Context, toAddr sdk.AccAddress) error { +// UnlockTo unlocks the given coin to the given address +func (c lockableCoin) UnlockTo(ctx sdk.Context, toAddr sdk.AccAddress) error { coin := c.GetOriginalCoin(ctx) switch c.coinType { diff --git a/x/nexus/keeper/lockable_coin_test.go b/x/nexus/keeper/lockable_coin_test.go index 70aa344c2..7c0dc5146 100644 --- a/x/nexus/keeper/lockable_coin_test.go +++ b/x/nexus/keeper/lockable_coin_test.go @@ -131,7 +131,7 @@ func TestLockableCoin(t *testing.T) { Run(t) }) - t.Run("Lock", func(t *testing.T) { + t.Run("LockFrom", func(t *testing.T) { givenKeeper. When2(whenCoinIsICS20). Then("should lock the coin", func(t *testing.T) { @@ -140,7 +140,7 @@ func TestLockableCoin(t *testing.T) { lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) fromAddr := rand.AccAddr() - err := lockableCoin.Lock(ctx, fromAddr) + err := lockableCoin.LockFrom(ctx, fromAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsCalls(), 1) @@ -158,7 +158,7 @@ func TestLockableCoin(t *testing.T) { lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) fromAddr := rand.AccAddr() - err := lockableCoin.Lock(ctx, fromAddr) + err := lockableCoin.LockFrom(ctx, fromAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsCalls(), 1) @@ -179,7 +179,7 @@ func TestLockableCoin(t *testing.T) { lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) fromAddr := rand.AccAddr() - err := lockableCoin.Lock(ctx, fromAddr) + err := lockableCoin.LockFrom(ctx, fromAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsFromAccountToModuleCalls(), 1) @@ -193,7 +193,7 @@ func TestLockableCoin(t *testing.T) { Run(t) }) - t.Run("Unlock", func(t *testing.T) { + t.Run("UnlockTo", func(t *testing.T) { givenKeeper. When2(whenCoinIsICS20). Then("should unlock the coin", func(t *testing.T) { @@ -202,7 +202,7 @@ func TestLockableCoin(t *testing.T) { lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) toAddr := rand.AccAddr() - err := lockableCoin.Unlock(ctx, toAddr) + err := lockableCoin.UnlockTo(ctx, toAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsCalls(), 1) @@ -220,7 +220,7 @@ func TestLockableCoin(t *testing.T) { lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) toAddr := rand.AccAddr() - err := lockableCoin.Unlock(ctx, toAddr) + err := lockableCoin.UnlockTo(ctx, toAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsCalls(), 1) @@ -241,7 +241,7 @@ func TestLockableCoin(t *testing.T) { lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) toAddr := rand.AccAddr() - err := lockableCoin.Unlock(ctx, toAddr) + err := lockableCoin.UnlockTo(ctx, toAddr) assert.NoError(t, err) assert.Len(t, bank.MintCoinsCalls(), 1) From 987862a07df573595e750661871adfbd4667713b Mon Sep 17 00:00:00 2001 From: Haiyi Zhong Date: Sat, 5 Oct 2024 02:21:55 +0800 Subject: [PATCH 09/11] revert migration --- x/nexus/keeper/migrate.go | 18 ++++---- x/nexus/keeper/migrate_test.go | 79 ++++++++++++++++++---------------- x/nexus/module.go | 4 +- 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/x/nexus/keeper/migrate.go b/x/nexus/keeper/migrate.go index 3c191deb8..19a94133f 100644 --- a/x/nexus/keeper/migrate.go +++ b/x/nexus/keeper/migrate.go @@ -3,23 +3,23 @@ package keeper import ( sdk "github.com/cosmos/cosmos-sdk/types" - axelarnettypes "github.com/axelarnetwork/axelar-core/x/axelarnet/types" "github.com/axelarnetwork/axelar-core/x/nexus/types" ) -// Migrate7to8 returns the handler that performs in-place store migrations -func Migrate7to8(_ Keeper, bank types.BankKeeper, account types.AccountKeeper) func(ctx sdk.Context) error { +// Migrate6to7 returns the handler that performs in-place store migrations +func Migrate6to7(k Keeper) func(ctx sdk.Context) error { return func(ctx sdk.Context) error { - if err := sendCoinsFromAxelarnetToNexus(ctx, bank, account); err != nil { - return err - } + addModuleParamGateway(ctx, k) + addModuleParamEndBlockerLimit(ctx, k) return nil } } -func sendCoinsFromAxelarnetToNexus(ctx sdk.Context, bank types.BankKeeper, account types.AccountKeeper) error { - balances := bank.GetAllBalances(ctx, account.GetModuleAddress(axelarnettypes.ModuleName)) +func addModuleParamGateway(ctx sdk.Context, k Keeper) { + k.params.Set(ctx, types.KeyGateway, types.DefaultParams().Gateway) +} - return bank.SendCoinsFromModuleToModule(ctx, axelarnettypes.ModuleName, types.ModuleName, balances) +func addModuleParamEndBlockerLimit(ctx sdk.Context, k Keeper) { + k.params.Set(ctx, types.KeyEndBlockerLimit, types.DefaultParams().EndBlockerLimit) } diff --git a/x/nexus/keeper/migrate_test.go b/x/nexus/keeper/migrate_test.go index 2a2d8d4cf..702c033bc 100644 --- a/x/nexus/keeper/migrate_test.go +++ b/x/nexus/keeper/migrate_test.go @@ -11,50 +11,55 @@ import ( "github.com/axelarnetwork/axelar-core/app" "github.com/axelarnetwork/axelar-core/testutils/fake" - "github.com/axelarnetwork/axelar-core/testutils/rand" - axelarnettypes "github.com/axelarnetwork/axelar-core/x/axelarnet/types" "github.com/axelarnetwork/axelar-core/x/nexus/keeper" "github.com/axelarnetwork/axelar-core/x/nexus/types" - "github.com/axelarnetwork/axelar-core/x/nexus/types/mock" + . "github.com/axelarnetwork/utils/test" ) -func TestMigrate7to8(t *testing.T) { +func TestMigrate6to7(t *testing.T) { encCfg := app.MakeEncodingConfig() subspace := params.NewSubspace(encCfg.Codec, encCfg.Amino, sdk.NewKVStoreKey("nexusKey"), sdk.NewKVStoreKey("tNexusKey"), "nexus") k := keeper.NewKeeper(encCfg.Codec, sdk.NewKVStoreKey("nexus"), subspace) ctx := sdk.NewContext(fake.NewMultiStore(), tmproto.Header{}, false, log.TestingLogger()) - t.Run("sendCoinsFromAxelarnetToNexus", func(t *testing.T) { - bank := &mock.BankKeeperMock{} - account := &mock.AccountKeeperMock{} - balances := sdk.NewCoins(rand.Coin(), rand.Coin(), rand.Coin()) - axelarnetModuleAccount := rand.AccAddr() - nexusModuleAccount := rand.AccAddr() - - account.GetModuleAddressFunc = func(name string) sdk.AccAddress { - switch name { - case axelarnettypes.ModuleName: - return axelarnetModuleAccount - case types.ModuleName: - return nexusModuleAccount - default: - return sdk.AccAddress{} - } - } - bank.GetAllBalancesFunc = func(ctx sdk.Context, addr sdk.AccAddress) sdk.Coins { - if addr.Equals(axelarnetModuleAccount) { - return balances - } - return sdk.NewCoins() - } - bank.SendCoinsFromModuleToModuleFunc = func(ctx sdk.Context, sender, recipient string, coins sdk.Coins) error { return nil } - - err := keeper.Migrate7to8(k, bank, account)(ctx) - - assert.NoError(t, err) - assert.Len(t, bank.SendCoinsFromModuleToModuleCalls(), 1) - assert.Equal(t, axelarnettypes.ModuleName, bank.SendCoinsFromModuleToModuleCalls()[0].SenderModule) - assert.Equal(t, types.ModuleName, bank.SendCoinsFromModuleToModuleCalls()[0].RecipientModule) - assert.Equal(t, balances, bank.SendCoinsFromModuleToModuleCalls()[0].Amt) - }) + Given("subspace is setup with params before migration", func() { + subspace.Set(ctx, types.KeyChainActivationThreshold, types.DefaultParams().ChainActivationThreshold) + subspace.Set(ctx, types.KeyChainMaintainerMissingVoteThreshold, types.DefaultParams().ChainMaintainerMissingVoteThreshold) + subspace.Set(ctx, types.KeyChainMaintainerIncorrectVoteThreshold, types.DefaultParams().ChainMaintainerIncorrectVoteThreshold) + subspace.Set(ctx, types.KeyChainMaintainerCheckWindow, types.DefaultParams().ChainMaintainerCheckWindow) + }). + When("", func() {}). + Then("the migration should add the new param with the default value", func(t *testing.T) { + actualGateway := sdk.AccAddress{} + actualEndBlockerLimit := uint64(0) + + assert.PanicsWithError(t, "UnmarshalJSON cannot decode empty bytes", func() { + subspace.Get(ctx, types.KeyGateway, &actualGateway) + }) + assert.PanicsWithError(t, "UnmarshalJSON cannot decode empty bytes", func() { + subspace.Get(ctx, types.KeyEndBlockerLimit, &actualEndBlockerLimit) + }) + assert.PanicsWithError(t, "UnmarshalJSON cannot decode empty bytes", func() { + k.GetParams(ctx) + }) + + keeper.Migrate6to7(k)(ctx) + + assert.NotPanics(t, func() { + subspace.Get(ctx, types.KeyGateway, &actualGateway) + }) + assert.NotPanics(t, func() { + subspace.Get(ctx, types.KeyEndBlockerLimit, &actualEndBlockerLimit) + }) + assert.NotPanics(t, func() { + k.GetParams(ctx) + }) + + assert.Equal(t, types.DefaultParams().Gateway, actualGateway) + assert.Equal(t, types.DefaultParams().Gateway, k.GetParams(ctx).Gateway) + assert.Equal(t, types.DefaultParams().EndBlockerLimit, actualEndBlockerLimit) + assert.Equal(t, types.DefaultParams().EndBlockerLimit, k.GetParams(ctx).EndBlockerLimit) + }). + Run(t) + } diff --git a/x/nexus/module.go b/x/nexus/module.go index 0b5e7f657..ebe87f28a 100644 --- a/x/nexus/module.go +++ b/x/nexus/module.go @@ -120,7 +120,7 @@ func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServiceServer(grpc.ServerWithSDKErrors{Server: cfg.MsgServer(), Err: types.ErrNexus, Logger: am.keeper.Logger}, msgServer) types.RegisterQueryServiceServer(cfg.QueryServer(), keeper.NewGRPCQuerier(am.keeper, am.axelarnet)) - err := cfg.RegisterMigration(types.ModuleName, 7, keeper.Migrate7to8(am.keeper, am.bank, am.account)) + err := cfg.RegisterMigration(types.ModuleName, 6, keeper.Migrate6to7(am.keeper)) if err != nil { panic(err) } @@ -171,4 +171,4 @@ func (am AppModule) LegacyQuerierHandler(*codec.LegacyAmino) sdk.Querier { } // ConsensusVersion implements AppModule/ConsensusVersion. -func (AppModule) ConsensusVersion() uint64 { return 8 } +func (AppModule) ConsensusVersion() uint64 { return 7 } From 8b9ec93ba2b61968065d37c0fffb95a7014429b6 Mon Sep 17 00:00:00 2001 From: Haiyi Zhong Date: Sat, 5 Oct 2024 03:01:51 +0800 Subject: [PATCH 10/11] rename --- app/keepers.go | 4 +- x/axelarnet/keeper/message_route.go | 4 +- x/axelarnet/keeper/message_route_test.go | 26 ++--- x/axelarnet/keeper/msg_server.go | 14 +-- x/axelarnet/keeper/msg_server_test.go | 92 ++++++++-------- x/axelarnet/message_handler.go | 40 +++---- x/axelarnet/message_handler_test.go | 122 ++++++++++----------- x/axelarnet/module.go | 4 +- x/axelarnet/module_test.go | 28 ++--- x/axelarnet/types/expected_keepers.go | 2 +- x/axelarnet/types/mock/expected_keepers.go | 42 +++---- x/nexus/exported/mock/types.go | 118 ++++++++++---------- x/nexus/exported/types.go | 10 +- x/nexus/keeper/lockable_coin.go | 43 ++++---- x/nexus/keeper/lockable_coin_test.go | 80 +++++++------- 15 files changed, 315 insertions(+), 314 deletions(-) diff --git a/app/keepers.go b/app/keepers.go index 9254f0190..10adb3a28 100644 --- a/app/keepers.go +++ b/app/keepers.go @@ -444,11 +444,11 @@ func initBankKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepe GetKeeper[authkeeper.AccountKeeper](keepers), keepers.getSubspace(banktypes.ModuleName), maps.Filter(moduleAccountAddrs(moduleAccPerms), func(addr string, _ bool) bool { - // we do not rely on internal balance tracking for invariance checks in the axelarnet module + // we do not rely on internal balance tracking for invariance checks in the nexus module // (https://github.com/cosmos/cosmos-sdk/issues/12825 for more details on the purpose of the blocked list), // but the module address must be able to use ibc transfers, // so we exclude this address from the blocked list - return addr != authtypes.NewModuleAddress(axelarnetTypes.ModuleName).String() + return addr != authtypes.NewModuleAddress(nexusTypes.ModuleName).String() }), ) return &bankK diff --git a/x/axelarnet/keeper/message_route.go b/x/axelarnet/keeper/message_route.go index f0841418a..e479e7cec 100644 --- a/x/axelarnet/keeper/message_route.go +++ b/x/axelarnet/keeper/message_route.go @@ -77,12 +77,12 @@ func escrowAssetToMessageSender( return asset, bankK.SendCoins(ctx, sender, types.AxelarIBCAccount, sdk.NewCoins(asset)) case nexus.TypeGeneralMessageWithToken: - coin, err := nexusK.NewLockableCoin(ctx, ibcK, bankK, *msg.Asset) + coin, err := nexusK.NewLockableAsset(ctx, ibcK, bankK, *msg.Asset) if err != nil { return sdk.Coin{}, err } - return coin.GetOriginalCoin(ctx), coin.UnlockTo(ctx, types.AxelarIBCAccount) + return coin.GetCoin(ctx), coin.UnlockTo(ctx, types.AxelarIBCAccount) default: return sdk.Coin{}, fmt.Errorf("unrecognized message type") } diff --git a/x/axelarnet/keeper/message_route_test.go b/x/axelarnet/keeper/message_route_test.go index b8f3d4ce3..c72ac8032 100644 --- a/x/axelarnet/keeper/message_route_test.go +++ b/x/axelarnet/keeper/message_route_test.go @@ -83,12 +83,12 @@ func TestNewMessageRoute(t *testing.T) { msg nexus.GeneralMessage route nexus.MessageRoute - feegrantK *mock.FeegrantKeeperMock - ibcK *mock.IBCKeeperMock - bankK *mock.BankKeeperMock - nexusK *mock.NexusMock - stakingK *mock.StakingKeeperMock - lockableCoin *nexusmock.LockableCoinMock + feegrantK *mock.FeegrantKeeperMock + ibcK *mock.IBCKeeperMock + bankK *mock.BankKeeperMock + nexusK *mock.NexusMock + stakingK *mock.StakingKeeperMock + lockableAsset *nexusmock.LockableAssetMock ) givenMessageRoute := Given("the message route", func() { @@ -202,13 +202,13 @@ func TestNewMessageRoute(t *testing.T) { msg = randMsg(nexus.Processing, routingCtx.Payload, &coin) }). Then("should unlock from the corresponding account", func(t *testing.T) { - nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - lockableCoin = &nexusmock.LockableCoinMock{ - GetOriginalCoinFunc: func(ctx sdk.Context) sdk.Coin { return coin }, - UnlockToFunc: func(ctx sdk.Context, toAddr sdk.AccAddress) error { return nil }, + nexusK.NewLockableAssetFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + lockableAsset = &nexusmock.LockableAssetMock{ + GetCoinFunc: func(ctx sdk.Context) sdk.Coin { return coin }, + UnlockToFunc: func(ctx sdk.Context, toAddr sdk.AccAddress) error { return nil }, } - return lockableCoin, nil + return lockableAsset, nil } ibcK.SendMessageFunc = func(_ context.Context, _ nexus.CrossChainAddress, _ sdk.Coin, _, _ string) error { @@ -217,8 +217,8 @@ func TestNewMessageRoute(t *testing.T) { assert.NoError(t, route(ctx, routingCtx, msg)) - assert.Len(t, lockableCoin.UnlockToCalls(), 1) - assert.Equal(t, types.AxelarIBCAccount, lockableCoin.UnlockToCalls()[0].ToAddr) + assert.Len(t, lockableAsset.UnlockToCalls(), 1) + assert.Equal(t, types.AxelarIBCAccount, lockableAsset.UnlockToCalls()[0].ToAddr) assert.Len(t, ibcK.SendMessageCalls(), 1) assert.Equal(t, msg.Recipient, ibcK.SendMessageCalls()[0].Recipient) diff --git a/x/axelarnet/keeper/msg_server.go b/x/axelarnet/keeper/msg_server.go index ec71460bc..e6b7c6d16 100644 --- a/x/axelarnet/keeper/msg_server.go +++ b/x/axelarnet/keeper/msg_server.go @@ -79,7 +79,7 @@ func (s msgServer) CallContract(c context.Context, req *types.CallContractReques }) if req.Fee != nil { - normalizedCoin, err := s.nexus.NewLockableCoin(ctx, s.ibcK, s.bank, req.Fee.Amount) + normalizedCoin, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, req.Fee.Amount) if err != nil { return nil, sdkerrors.Wrap(err, "unrecognized fee denom") } @@ -93,7 +93,7 @@ func (s msgServer) CallContract(c context.Context, req *types.CallContractReques MessageID: msgID, Recipient: req.Fee.Recipient, Fee: req.Fee.Amount, - Asset: normalizedCoin.GetCoin().Denom, + Asset: normalizedCoin.GetAsset().Denom, } if req.Fee.RefundRecipient != nil { feePaidEvent.RefundRecipient = req.Fee.RefundRecipient.String() @@ -185,7 +185,7 @@ func (s msgServer) ConfirmDeposit(c context.Context, req *types.ConfirmDepositRe return nil, fmt.Errorf("recipient chain '%s' is not activated", recipient.Chain.Name) } - normalizedCoin, err := s.nexus.NewLockableCoin(ctx, s.ibcK, s.bank, coin) + normalizedCoin, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, coin) if err != nil { return nil, err } @@ -194,7 +194,7 @@ func (s msgServer) ConfirmDeposit(c context.Context, req *types.ConfirmDepositRe return nil, err } - transferID, err := s.nexus.EnqueueForTransfer(ctx, depositAddr, normalizedCoin.GetCoin()) + transferID, err := s.nexus.EnqueueForTransfer(ctx, depositAddr, normalizedCoin.GetAsset()) if err != nil { return nil, err } @@ -403,7 +403,7 @@ func (s msgServer) RouteIBCTransfers(c context.Context, _ *types.RouteIBCTransfe return nil, err } for _, p := range pendingTransfers { - coin, err := s.nexus.NewLockableCoin(ctx, s.ibcK, s.bank, p.Asset) + coin, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, p.Asset) if err != nil { s.Logger(ctx).Error(fmt.Sprintf("failed to route IBC transfer %s: %s", p.String(), err)) continue @@ -414,7 +414,7 @@ func (s msgServer) RouteIBCTransfers(c context.Context, _ *types.RouteIBCTransfe continue } - funcs.MustNoErr(s.EnqueueIBCTransfer(ctx, types.NewIBCTransfer(types.AxelarIBCAccount, p.Recipient.Address, coin.GetOriginalCoin(ctx), portID, channelID, p.ID))) + funcs.MustNoErr(s.EnqueueIBCTransfer(ctx, types.NewIBCTransfer(types.AxelarIBCAccount, p.Recipient.Address, coin.GetCoin(ctx), portID, channelID, p.ID))) s.nexus.ArchivePendingTransfer(ctx, p) } } @@ -499,7 +499,7 @@ func (s msgServer) RouteMessage(c context.Context, req *types.RouteMessageReques } func transfer(ctx sdk.Context, k Keeper, n types.Nexus, b types.BankKeeper, ibc types.IBCKeeper, recipient sdk.AccAddress, coin sdk.Coin) error { - c, err := n.NewLockableCoin(ctx, ibc, b, coin) + c, err := n.NewLockableAsset(ctx, ibc, b, coin) if err != nil { return err } diff --git a/x/axelarnet/keeper/msg_server_test.go b/x/axelarnet/keeper/msg_server_test.go index dee968cd8..9fc7250a3 100644 --- a/x/axelarnet/keeper/msg_server_test.go +++ b/x/axelarnet/keeper/msg_server_test.go @@ -222,9 +222,9 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { whenDepositAddressHasBalance. When2(recipientIsFound). When2(chainIsActivated). - When("fails to create a lockable coin", func() { - nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - return nil, fmt.Errorf("failed to create lockable coin") + When("fails to create a lockable asset", func() { + nexusK.NewLockableAssetFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + return nil, fmt.Errorf("failed to create lockable asset") } }). When2(confirmToken). @@ -233,9 +233,9 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { whenDepositAddressHasBalance. When2(recipientIsFound). When2(chainIsActivated). - When("suceeded to create a lockable coin but lock fails", func() { - nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - lockbleCoin := &nexusmock.LockableCoinMock{ + When("suceeded to create a lockable asset but lock fails", func() { + nexusK.NewLockableAssetFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + lockbleCoin := &nexusmock.LockableAssetMock{ LockFromFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("failed to lock coin") }, @@ -250,18 +250,18 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { whenDepositAddressHasBalance. When2(recipientIsFound). When2(chainIsActivated). - When("suceeded to create a lockable coin but lock succeeds", func() { - nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - lockbleCoin := &nexusmock.LockableCoinMock{ + When("succeeded to create a lockable asset but lock succeeds", func() { + nexusK.NewLockableAssetFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + lockableAsset := &nexusmock.LockableAssetMock{ LockFromFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil }, - GetCoinFunc: func() sdk.Coin { + GetAssetFunc: func() sdk.Coin { return sdk.NewCoin(req.Denom, sdk.NewInt(1e18)) }, } - return lockbleCoin, nil + return lockableAsset, nil } }). When2(enqueueTransferSucceeds). @@ -276,14 +276,14 @@ func TestHandleMsgConfirmDeposit(t *testing.T) { func TestHandleMsgExecutePendingTransfers(t *testing.T) { var ( - server types.MsgServiceServer - k keeper.Keeper - nexusK *mock.NexusMock - bankK *mock.BankKeeperMock - transferK *mock.IBCTransferKeeperMock - ctx sdk.Context - req *types.ExecutePendingTransfersRequest - lockableCoin *nexusmock.LockableCoinMock + server types.MsgServiceServer + k keeper.Keeper + nexusK *mock.NexusMock + bankK *mock.BankKeeperMock + transferK *mock.IBCTransferKeeperMock + ctx sdk.Context + req *types.ExecutePendingTransfersRequest + lockableAsset *nexusmock.LockableAssetMock ) givenMsgServer := Given("an axelarnet msg server", func() { @@ -313,14 +313,14 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { }) unlocksCoinSucceeds := When("unlock coins succeeds", func() { - lockableCoin = &nexusmock.LockableCoinMock{ + lockableAsset = &nexusmock.LockableAssetMock{ UnlockToFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil }, } - nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - return lockableCoin, nil + nexusK.NewLockableAssetFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + return lockableAsset, nil } }) @@ -347,13 +347,13 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { whenHasPendingTransfers. When("unlock coins fails", func() { - lockableCoin = &nexusmock.LockableCoinMock{ + lockableAsset = &nexusmock.LockableAssetMock{ UnlockToFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("failed to unlock coin") }, } - nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - return lockableCoin, nil + nexusK.NewLockableAssetFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + return lockableAsset, nil } }). When2(requestIsMade). @@ -372,7 +372,7 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { assert.NoError(t, err) assert.Len(t, nexusK.ArchivePendingTransferCalls(), 1) - assert.Len(t, lockableCoin.UnlockToCalls(), 1) + assert.Len(t, lockableAsset.UnlockToCalls(), 1) }), When("has many pending transfers", func() { @@ -390,7 +390,7 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { assert.NoError(t, err) assert.Len(t, nexusK.ArchivePendingTransferCalls(), transferLimit) - assert.Len(t, lockableCoin.UnlockToCalls(), transferLimit) + assert.Len(t, lockableAsset.UnlockToCalls(), transferLimit) }), ).Run(t) }) @@ -398,16 +398,16 @@ func TestHandleMsgExecutePendingTransfers(t *testing.T) { func TestHandleMsgRouteIBCTransfers(t *testing.T) { var ( - server types.MsgServiceServer - k keeper.Keeper - nexusK *mock.NexusMock - bankK *mock.BankKeeperMock - transferK *mock.IBCTransferKeeperMock - ctx sdk.Context - req *types.RouteIBCTransfersRequest - cosmosChains []types.CosmosChain - transfersNum int - lockableCoin *nexusmock.LockableCoinMock + server types.MsgServiceServer + k keeper.Keeper + nexusK *mock.NexusMock + bankK *mock.BankKeeperMock + transferK *mock.IBCTransferKeeperMock + ctx sdk.Context + req *types.RouteIBCTransfersRequest + cosmosChains []types.CosmosChain + transfersNum int + lockableAsset *nexusmock.LockableAssetMock ) givenMsgServer := Given("an axelarnet msg server", func() { @@ -494,17 +494,17 @@ func TestHandleMsgRouteIBCTransfers(t *testing.T) { whenHasPendingTranfers. When2(requestIsMade). When("unlock coin succeeds", func() { - lockableCoin = &nexusmock.LockableCoinMock{ + lockableAsset = &nexusmock.LockableAssetMock{ UnlockToFunc: func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil }, - GetOriginalCoinFunc: func(ctx sdk.Context) sdk.Coin { + GetCoinFunc: func(ctx sdk.Context) sdk.Coin { return sdk.NewCoin(rand.Denom(3, 10), sdk.NewInt(1e18)) }, } - nexusK.NewLockableCoinFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - return lockableCoin, nil + nexusK.NewLockableAssetFunc = func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + return lockableAsset, nil } }). Then("archive the transfer", func(t *testing.T) { @@ -512,7 +512,7 @@ func TestHandleMsgRouteIBCTransfers(t *testing.T) { assert.NoError(t, err) assert.Len(t, nexusK.ArchivePendingTransferCalls(), transfersNum, fmt.Sprintf("expected %d got %d", transfersNum, len(nexusK.ArchivePendingTransferCalls()))) - assert.Len(t, lockableCoin.UnlockToCalls(), transfersNum) + assert.Len(t, lockableAsset.UnlockToCalls(), transfersNum) }), ).Run(t) }) @@ -816,12 +816,12 @@ func TestHandleCallContract(t *testing.T) { ctx, k, _, _ = setup() k.InitGenesis(ctx, types.DefaultGenesisState()) nexusK = &mock.NexusMock{ - NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - lockableCoin := &nexusmock.LockableCoinMock{ - GetCoinFunc: func() sdk.Coin { return req.Fee.Amount }, + NewLockableAssetFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + lockableAsset := &nexusmock.LockableAssetMock{ + GetAssetFunc: func() sdk.Coin { return req.Fee.Amount }, } - return lockableCoin, nil + return lockableAsset, nil }, } ibcK := keeper.NewIBCKeeper(k, &mock.IBCTransferKeeperMock{}) diff --git a/x/axelarnet/message_handler.go b/x/axelarnet/message_handler.go index efd9a9e66..84bc45137 100644 --- a/x/axelarnet/message_handler.go +++ b/x/axelarnet/message_handler.go @@ -184,7 +184,7 @@ func OnRecvMessage(ctx sdk.Context, k keeper.Keeper, ibcK keeper.IBCKeeper, n ty return ack } -func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcPath string, msg Message, token nexus.LockableCoin) error { +func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcPath string, msg Message, token nexus.LockableAsset) error { // validate source chain srcChainName, srcChainFound := ibcK.GetChainNameByIBCPath(ctx, ibcPath) if !srcChainFound { @@ -197,7 +197,7 @@ func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcP } if msg.Fee != nil { - err := validateFee(ctx, n, token.GetCoin(), nexus.MessageType(msg.Type), srcChain, *msg.Fee) + err := validateFee(ctx, n, token.GetAsset(), nexus.MessageType(msg.Type), srcChain, *msg.Fee) if err != nil { return err } @@ -230,12 +230,12 @@ func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcP return fmt.Errorf("unrecognized destination chain %s", destChainName) } - if !n.IsAssetRegistered(ctx, srcChain, token.GetCoin().Denom) { - return fmt.Errorf("asset %s is not registered on chain %s", token.GetCoin().Denom, srcChain.Name) + if !n.IsAssetRegistered(ctx, srcChain, token.GetAsset().Denom) { + return fmt.Errorf("asset %s is not registered on chain %s", token.GetAsset().Denom, srcChain.Name) } - if !n.IsAssetRegistered(ctx, destChain, token.GetCoin().Denom) { - return fmt.Errorf("asset %s is not registered on chain %s", token.GetCoin().Denom, destChain.Name) + if !n.IsAssetRegistered(ctx, destChain, token.GetAsset().Denom) { + return fmt.Errorf("asset %s is not registered on chain %s", token.GetAsset().Denom, destChain.Name) } return nil default: @@ -243,7 +243,7 @@ func validateMessage(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, ibcP } } -func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableCoin) error { +func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableAsset) error { id, txID, nonce := n.GenerateMessageID(ctx) // ignore token for call contract @@ -284,7 +284,7 @@ func handleMessage(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK type return n.SetNewMessage(ctx, m) } -func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableCoin) error { +func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableAsset) error { id, txID, nonce := n.GenerateMessageID(ctx) token, err := deductFee(ctx, n, b, ibcK, msg.Fee, token, id) @@ -298,7 +298,7 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, destChain := funcs.MustOk(n.GetChain(ctx, nexus.ChainName(msg.DestinationChain))) recipient := nexus.CrossChainAddress{Chain: destChain, Address: msg.DestinationAddress} - coin := token.GetCoin() + coin := token.GetAsset() m := nexus.NewGeneralMessage( id, sourceAddress, @@ -317,13 +317,13 @@ func handleMessageWithToken(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ContractAddress: m.GetDestinationAddress(), PayloadHash: m.PayloadHash, Payload: msg.Payload, - Asset: token.GetCoin(), + Asset: token.GetAsset(), }) return n.SetNewMessage(ctx, m) } -func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableCoin) error { +func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossChainAddress, msg Message, token nexus.LockableAsset) error { destChain := funcs.MustOk(n.GetChain(ctx, nexus.ChainName(msg.DestinationChain))) crossChainAddr := nexus.CrossChainAddress{Chain: destChain, Address: msg.DestinationAddress} @@ -331,7 +331,7 @@ func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossCh return err } - transferID, err := n.EnqueueTransfer(ctx, sourceAddress.Chain, crossChainAddr, token.GetCoin()) + transferID, err := n.EnqueueTransfer(ctx, sourceAddress.Chain, crossChainAddr, token.GetAsset()) if err != nil { return err } @@ -342,7 +342,7 @@ func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossCh SourceChain: sourceAddress.Chain.Name, DestinationAddress: crossChainAddr.Address, DestinationChain: crossChainAddr.Chain.Name, - Asset: token.GetCoin(), + Asset: token.GetAsset(), }) return nil @@ -351,7 +351,7 @@ func handleTokenSent(ctx sdk.Context, n types.Nexus, sourceAddress nexus.CrossCh // extractTokenFromPacketData get normalized token from ICS20 packet // panic if unable to unmarshal packet data -func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, b types.BankKeeper, packet ibcexported.PacketI) (nexus.LockableCoin, error) { +func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types.Nexus, b types.BankKeeper, packet ibcexported.PacketI) (nexus.LockableAsset, error) { data := funcs.Must(types.ToICS20Packet(packet)) // parse the transfer amount @@ -389,24 +389,24 @@ func extractTokenFromPacketData(ctx sdk.Context, ibcK keeper.IBCKeeper, n types. denom = denomTrace.IBCDenom() } - return n.NewLockableCoin(ctx, ibcK, b, sdk.NewCoin(denom, amount)) + return n.NewLockableAsset(ctx, ibcK, b, sdk.NewCoin(denom, amount)) } // deductFee pays the fee and returns the updated transfer amount with the fee deducted -func deductFee(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, fee *Fee, token nexus.LockableCoin, msgID string) (nexus.LockableCoin, error) { +func deductFee(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IBCKeeper, fee *Fee, token nexus.LockableAsset, msgID string) (nexus.LockableAsset, error) { if fee == nil { return token, nil } feeAmount := funcs.MustOk(sdk.NewIntFromString(fee.Amount)) - feeCoin := sdk.NewCoin(token.GetOriginalCoin(ctx).Denom, feeAmount) + feeCoin := sdk.NewCoin(token.GetCoin(ctx).Denom, feeAmount) recipient := funcs.Must(sdk.AccAddressFromBech32(fee.Recipient)) feePaidEvent := types.FeePaid{ MessageID: msgID, Recipient: recipient, Fee: feeCoin, - Asset: token.GetCoin().Denom, + Asset: token.GetAsset().Denom, } if fee.RefundRecipient != nil { feePaidEvent.RefundRecipient = *fee.RefundRecipient @@ -414,9 +414,9 @@ func deductFee(ctx sdk.Context, n types.Nexus, b types.BankKeeper, ibcK types.IB events.Emit(ctx, &feePaidEvent) // subtract fee from transfer value - coinAfterFee := token.GetOriginalCoin(ctx).Sub(feeCoin) + coinAfterFee := token.GetCoin(ctx).Sub(feeCoin) - return funcs.Must(n.NewLockableCoin(ctx, ibcK, b, coinAfterFee)), b.SendCoins(ctx, types.AxelarIBCAccount, recipient, sdk.NewCoins(feeCoin)) + return funcs.Must(n.NewLockableAsset(ctx, ibcK, b, coinAfterFee)), b.SendCoins(ctx, types.AxelarIBCAccount, recipient, sdk.NewCoins(feeCoin)) } // validateReceiver rejects uppercase GMP account address diff --git a/x/axelarnet/message_handler_test.go b/x/axelarnet/message_handler_test.go index 42a7d5087..fdde40074 100644 --- a/x/axelarnet/message_handler_test.go +++ b/x/axelarnet/message_handler_test.go @@ -38,15 +38,15 @@ import ( func TestHandleMessage(t *testing.T) { var ( - ctx sdk.Context - k keeper.Keeper - packet ibcchanneltypes.Packet - b *mock.BankKeeperMock - n *mock.NexusMock - channelK *mock.ChannelKeeperMock - ibcK keeper.IBCKeeper - r axelarnet.RateLimiter - lockableCoin *nexusmock.LockableCoinMock + ctx sdk.Context + k keeper.Keeper + packet ibcchanneltypes.Packet + b *mock.BankKeeperMock + n *mock.NexusMock + channelK *mock.ChannelKeeperMock + ibcK keeper.IBCKeeper + r axelarnet.RateLimiter + lockableAsset *nexusmock.LockableAssetMock ics20Packet ibctransfertypes.FungibleTokenPacketData message axelarnet.Message @@ -77,13 +77,13 @@ func TestHandleMessage(t *testing.T) { })) channelK.SendPacketFunc = func(sdk.Context, *captypes.Capability, ibcexported.PacketI) error { return nil } n = &mock.NexusMock{ - NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - lockableCoin = &nexusmock.LockableCoinMock{ - GetCoinFunc: func() sdk.Coin { return coin }, - GetOriginalCoinFunc: func(_ sdk.Context) sdk.Coin { return coin }, + NewLockableAssetFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + lockableAsset = &nexusmock.LockableAssetMock{ + GetAssetFunc: func() sdk.Coin { return coin }, + GetCoinFunc: func(_ sdk.Context) sdk.Coin { return coin }, } - return lockableCoin, nil + return lockableAsset, nil }, SetNewMessageFunc: func(ctx sdk.Context, msg nexus.GeneralMessage) error { genMsg = msg @@ -434,15 +434,15 @@ func TestHandleMessage(t *testing.T) { func TestHandleMessageWithToken(t *testing.T) { var ( - ctx sdk.Context - k keeper.Keeper - packet ibcchanneltypes.Packet - b *mock.BankKeeperMock - n *mock.NexusMock - channelK *mock.ChannelKeeperMock - ibcK keeper.IBCKeeper - r axelarnet.RateLimiter - lockableCoin *nexusmock.LockableCoinMock + ctx sdk.Context + k keeper.Keeper + packet ibcchanneltypes.Packet + b *mock.BankKeeperMock + n *mock.NexusMock + channelK *mock.ChannelKeeperMock + ibcK keeper.IBCKeeper + r axelarnet.RateLimiter + lockableAsset *nexusmock.LockableAssetMock denom string amount string @@ -491,13 +491,13 @@ func TestHandleMessageWithToken(t *testing.T) { })) channelK.SendPacketFunc = func(sdk.Context, *captypes.Capability, ibcexported.PacketI) error { return nil } - lockableCoin = &nexusmock.LockableCoinMock{ - GetCoinFunc: func() sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, - GetOriginalCoinFunc: func(_ sdk.Context) sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, + lockableAsset = &nexusmock.LockableAssetMock{ + GetAssetFunc: func() sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, + GetCoinFunc: func(_ sdk.Context) sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, } n = &mock.NexusMock{ - NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - return lockableCoin, nil + NewLockableAssetFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + return lockableAsset, nil }, SetNewMessageFunc: func(ctx sdk.Context, msg nexus.GeneralMessage) error { genMsg = msg @@ -600,12 +600,12 @@ func TestHandleMessageWithToken(t *testing.T) { lockCoin := func(success bool) func() { if success { return func() { - lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + lockableAsset.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } } } return func() { - lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + lockableAsset.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } } } @@ -677,24 +677,24 @@ func TestHandleMessageWithToken(t *testing.T) { Then("should return ack success", func(t *testing.T) { assert.True(t, axelarnet.OnRecvMessage(ctx, k, ibcK, n, b, r, packet).Success()) assert.Equal(t, genMsg.Status, nexus.Approved) - assert.Len(t, n.NewLockableCoinCalls(), 2) - assert.Equal(t, n.NewLockableCoinCalls()[0].Coin.Amount, funcs.MustOk(sdk.NewIntFromString(amount))) - assert.Equal(t, n.NewLockableCoinCalls()[1].Coin.Amount, sdk.OneInt()) + assert.Len(t, n.NewLockableAssetCalls(), 2) + assert.Equal(t, n.NewLockableAssetCalls()[0].Coin.Amount, funcs.MustOk(sdk.NewIntFromString(amount))) + assert.Equal(t, n.NewLockableAssetCalls()[1].Coin.Amount, sdk.OneInt()) }). Run(t) } func TestHandleSendToken(t *testing.T) { var ( - ctx sdk.Context - k keeper.Keeper - packet ibcchanneltypes.Packet - b *mock.BankKeeperMock - n *mock.NexusMock - channelK *mock.ChannelKeeperMock - ibcK keeper.IBCKeeper - r axelarnet.RateLimiter - lockableCoin *nexusmock.LockableCoinMock + ctx sdk.Context + k keeper.Keeper + packet ibcchanneltypes.Packet + b *mock.BankKeeperMock + n *mock.NexusMock + channelK *mock.ChannelKeeperMock + ibcK keeper.IBCKeeper + r axelarnet.RateLimiter + lockableAsset *nexusmock.LockableAssetMock denom string amount string @@ -739,13 +739,13 @@ func TestHandleSendToken(t *testing.T) { })) channelK.SendPacketFunc = func(sdk.Context, *captypes.Capability, ibcexported.PacketI) error { return nil } - lockableCoin = &nexusmock.LockableCoinMock{ - GetCoinFunc: func() sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, - GetOriginalCoinFunc: func(_ sdk.Context) sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, + lockableAsset = &nexusmock.LockableAssetMock{ + GetAssetFunc: func() sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, + GetCoinFunc: func(_ sdk.Context) sdk.Coin { return sdk.NewCoin(denom, funcs.MustOk(sdk.NewIntFromString(amount))) }, } n = &mock.NexusMock{ - NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - return lockableCoin, nil + NewLockableAssetFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + return lockableAsset, nil }, SetNewMessageFunc: func(sdk.Context, nexus.GeneralMessage) error { return nil }, GetChainFunc: func(ctx sdk.Context, chain nexus.ChainName) (nexus.Chain, bool) { @@ -835,12 +835,12 @@ func TestHandleSendToken(t *testing.T) { lockCoin := func(success bool) func() { if success { return func() { - lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + lockableAsset.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } } } return func() { - lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + lockableAsset.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } } } @@ -882,15 +882,15 @@ func TestHandleSendToken(t *testing.T) { func TestTokenAndDestChainNotFound(t *testing.T) { var ( - ctx sdk.Context - k keeper.Keeper - packet ibcchanneltypes.Packet - b *mock.BankKeeperMock - n *mock.NexusMock - channelK *mock.ChannelKeeperMock - ibcK keeper.IBCKeeper - r axelarnet.RateLimiter - lockableCoin *nexusmock.LockableCoinMock + ctx sdk.Context + k keeper.Keeper + packet ibcchanneltypes.Packet + b *mock.BankKeeperMock + n *mock.NexusMock + channelK *mock.ChannelKeeperMock + ibcK keeper.IBCKeeper + r axelarnet.RateLimiter + lockableAsset *nexusmock.LockableAssetMock ics20Packet ibctransfertypes.FungibleTokenPacketData gmpWithToken axelarnet.Message @@ -927,10 +927,10 @@ func TestTokenAndDestChainNotFound(t *testing.T) { AddrPrefix: "cosmos", })) channelK.SendPacketFunc = func(sdk.Context, *captypes.Capability, ibcexported.PacketI) error { return nil } - lockableCoin = &nexusmock.LockableCoinMock{} + lockableAsset = &nexusmock.LockableAssetMock{} n = &mock.NexusMock{ - NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - return lockableCoin, nil + NewLockableAssetFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + return lockableAsset, nil }, SetNewMessageFunc: func(ctx sdk.Context, msg nexus.GeneralMessage) error { return nil diff --git a/x/axelarnet/module.go b/x/axelarnet/module.go index 304865c0a..9f5eaa26e 100644 --- a/x/axelarnet/module.go +++ b/x/axelarnet/module.go @@ -342,7 +342,7 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed cross chain transfer transferID, ok := getSeqIDMapping(ctx, m.keeper, port, channel, sequence) if ok { - coin, err := m.nexus.NewLockableCoin(ctx, m.ibcK, m.bank, funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)).Token) + coin, err := m.nexus.NewLockableAsset(ctx, m.ibcK, m.bank, funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)).Token) if err != nil { return err } @@ -368,7 +368,7 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed general message messageID, ok := getSeqMessageIDMapping(ctx, m.keeper, port, channel, sequence) if ok { - coin, err := m.nexus.NewLockableCoin(ctx, m.ibcK, m.bank, extractTokenFromAckOrTimeoutPacket(packet)) + coin, err := m.nexus.NewLockableAsset(ctx, m.ibcK, m.bank, extractTokenFromAckOrTimeoutPacket(packet)) if err != nil { return err } diff --git a/x/axelarnet/module_test.go b/x/axelarnet/module_test.go index 0f6b53060..280d66bfe 100644 --- a/x/axelarnet/module_test.go +++ b/x/axelarnet/module_test.go @@ -36,12 +36,12 @@ import ( func TestIBCModule(t *testing.T) { var ( - ctx sdk.Context - ibcModule axelarnet.AxelarnetIBCModule - k keeper.Keeper - n *mock.NexusMock - bankK *mock.BankKeeperMock - lockableCoin *nexusmock.LockableCoinMock + ctx sdk.Context + ibcModule axelarnet.AxelarnetIBCModule + k keeper.Keeper + n *mock.NexusMock + bankK *mock.BankKeeperMock + lockableAsset *nexusmock.LockableAssetMock ack channeltypes.Acknowledgement transfer types.IBCTransfer @@ -89,10 +89,10 @@ func TestIBCModule(t *testing.T) { transferSubspace := params.NewSubspace(encCfg.Codec, encCfg.Amino, sdk.NewKVStoreKey(ibctransfertypes.StoreKey), sdk.NewKVStoreKey("tTrasferKey"), ibctransfertypes.ModuleName) transferK := ibctransferkeeper.NewKeeper(encCfg.Codec, sdk.NewKVStoreKey("transfer"), transferSubspace, &mock.ChannelKeeperMock{}, &mock.ChannelKeeperMock{}, &mock.PortKeeperMock{}, accountK, bankK, scopedTransferK) - lockableCoin = &nexusmock.LockableCoinMock{} + lockableAsset = &nexusmock.LockableAssetMock{} n = &mock.NexusMock{ - NewLockableCoinFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) { - return lockableCoin, nil + NewLockableAssetFunc: func(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) { + return lockableAsset, nil }, } ibcModule = axelarnet.NewAxelarnetIBCModule(ibcTransfer.NewIBCModule(transferK), ibcK, axelarnet.NewRateLimiter(&k, n), n, bankK) @@ -169,12 +169,12 @@ func TestIBCModule(t *testing.T) { lockCoin := func(success bool) func() { if success { return func() { - lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } + lockableAsset.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return nil } } } return func() { - lockableCoin.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } + lockableAsset.LockFromFunc = func(ctx sdk.Context, fromAddr sdk.AccAddress) error { return fmt.Errorf("lock coin failed") } } } @@ -196,7 +196,7 @@ func TestIBCModule(t *testing.T) { Then("should set transfer to failed", func(t *testing.T) { transfer := funcs.MustOk(k.GetTransfer(ctx, transfer.ID)) assert.Equal(t, types.TransferFailed, transfer.Status) - assert.Len(t, lockableCoin.LockFromCalls(), 1) + assert.Len(t, lockableAsset.LockFromCalls(), 1) }), whenPendingTransfersExist. @@ -219,7 +219,7 @@ func TestIBCModule(t *testing.T) { Then("should set transfer to failed", func(t *testing.T) { transfer := funcs.MustOk(k.GetTransfer(ctx, transfer.ID)) assert.Equal(t, types.TransferFailed, transfer.Status) - assert.Len(t, lockableCoin.LockFromCalls(), 1) + assert.Len(t, lockableAsset.LockFromCalls(), 1) }), whenPendingTransfersExist. @@ -235,7 +235,7 @@ func TestIBCModule(t *testing.T) { When2(whenOnAck). Then("should set message to failed", func(t *testing.T) { assert.Equal(t, nexus.Failed, message.Status) - assert.Len(t, lockableCoin.LockFromCalls(), 1) + assert.Len(t, lockableAsset.LockFromCalls(), 1) }), ).Run(t) } diff --git a/x/axelarnet/types/expected_keepers.go b/x/axelarnet/types/expected_keepers.go index c8c38c823..f490243af 100644 --- a/x/axelarnet/types/expected_keepers.go +++ b/x/axelarnet/types/expected_keepers.go @@ -87,7 +87,7 @@ type Nexus interface { SetMessageFailed(ctx sdk.Context, id string) error GenerateMessageID(ctx sdk.Context) (string, []byte, uint64) ValidateAddress(ctx sdk.Context, address nexus.CrossChainAddress) error - NewLockableCoin(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableCoin, error) + NewLockableAsset(ctx sdk.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin sdk.Coin) (nexus.LockableAsset, error) } // BankKeeper defines the expected interface contract the vesting module requires diff --git a/x/axelarnet/types/mock/expected_keepers.go b/x/axelarnet/types/mock/expected_keepers.go index 40eff4531..9c8be2a2b 100644 --- a/x/axelarnet/types/mock/expected_keepers.go +++ b/x/axelarnet/types/mock/expected_keepers.go @@ -751,8 +751,8 @@ var _ axelarnettypes.Nexus = &NexusMock{} // LoggerFunc: func(ctx cosmossdktypes.Context) log.Logger { // panic("mock out the Logger method") // }, -// NewLockableCoinFunc: func(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableCoin, error) { -// panic("mock out the NewLockableCoin method") +// NewLockableAssetFunc: func(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableAsset, error) { +// panic("mock out the NewLockableAsset method") // }, // RateLimitTransferFunc: func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, asset cosmossdktypes.Coin, direction github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferDirection) error { // panic("mock out the RateLimitTransfer method") @@ -887,8 +887,8 @@ type NexusMock struct { // LoggerFunc mocks the Logger method. LoggerFunc func(ctx cosmossdktypes.Context) log.Logger - // NewLockableCoinFunc mocks the NewLockableCoin method. - NewLockableCoinFunc func(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableCoin, error) + // NewLockableAssetFunc mocks the NewLockableAsset method. + NewLockableAssetFunc func(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableAsset, error) // RateLimitTransferFunc mocks the RateLimitTransfer method. RateLimitTransferFunc func(ctx cosmossdktypes.Context, chain github_com_axelarnetwork_axelar_core_x_nexus_exported.ChainName, asset cosmossdktypes.Coin, direction github_com_axelarnetwork_axelar_core_x_nexus_exported.TransferDirection) error @@ -1134,8 +1134,8 @@ type NexusMock struct { // Ctx is the ctx argument value. Ctx cosmossdktypes.Context } - // NewLockableCoin holds details about calls to the NewLockableCoin method. - NewLockableCoin []struct { + // NewLockableAsset holds details about calls to the NewLockableAsset method. + NewLockableAsset []struct { // Ctx is the ctx argument value. Ctx cosmossdktypes.Context // Ibc is the ibc argument value. @@ -1286,7 +1286,7 @@ type NexusMock struct { lockIsWasmConnectionActivated sync.RWMutex lockLinkAddresses sync.RWMutex lockLogger sync.RWMutex - lockNewLockableCoin sync.RWMutex + lockNewLockableAsset sync.RWMutex lockRateLimitTransfer sync.RWMutex lockRegisterAsset sync.RWMutex lockRegisterFee sync.RWMutex @@ -2346,10 +2346,10 @@ func (mock *NexusMock) LoggerCalls() []struct { return calls } -// NewLockableCoin calls NewLockableCoinFunc. -func (mock *NexusMock) NewLockableCoin(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableCoin, error) { - if mock.NewLockableCoinFunc == nil { - panic("NexusMock.NewLockableCoinFunc: method is nil but Nexus.NewLockableCoin was just called") +// NewLockableAsset calls NewLockableAssetFunc. +func (mock *NexusMock) NewLockableAsset(ctx cosmossdktypes.Context, ibc nexustypes.IBCKeeper, bank nexustypes.BankKeeper, coin cosmossdktypes.Coin) (github_com_axelarnetwork_axelar_core_x_nexus_exported.LockableAsset, error) { + if mock.NewLockableAssetFunc == nil { + panic("NexusMock.NewLockableAssetFunc: method is nil but Nexus.NewLockableAsset was just called") } callInfo := struct { Ctx cosmossdktypes.Context @@ -2362,17 +2362,17 @@ func (mock *NexusMock) NewLockableCoin(ctx cosmossdktypes.Context, ibc nexustype Bank: bank, Coin: coin, } - mock.lockNewLockableCoin.Lock() - mock.calls.NewLockableCoin = append(mock.calls.NewLockableCoin, callInfo) - mock.lockNewLockableCoin.Unlock() - return mock.NewLockableCoinFunc(ctx, ibc, bank, coin) + mock.lockNewLockableAsset.Lock() + mock.calls.NewLockableAsset = append(mock.calls.NewLockableAsset, callInfo) + mock.lockNewLockableAsset.Unlock() + return mock.NewLockableAssetFunc(ctx, ibc, bank, coin) } -// NewLockableCoinCalls gets all the calls that were made to NewLockableCoin. +// NewLockableAssetCalls gets all the calls that were made to NewLockableAsset. // Check the length with: // -// len(mockedNexus.NewLockableCoinCalls()) -func (mock *NexusMock) NewLockableCoinCalls() []struct { +// len(mockedNexus.NewLockableAssetCalls()) +func (mock *NexusMock) NewLockableAssetCalls() []struct { Ctx cosmossdktypes.Context Ibc nexustypes.IBCKeeper Bank nexustypes.BankKeeper @@ -2384,9 +2384,9 @@ func (mock *NexusMock) NewLockableCoinCalls() []struct { Bank nexustypes.BankKeeper Coin cosmossdktypes.Coin } - mock.lockNewLockableCoin.RLock() - calls = mock.calls.NewLockableCoin - mock.lockNewLockableCoin.RUnlock() + mock.lockNewLockableAsset.RLock() + calls = mock.calls.NewLockableAsset + mock.lockNewLockableAsset.RUnlock() return calls } diff --git a/x/nexus/exported/mock/types.go b/x/nexus/exported/mock/types.go index 992726699..797aeb934 100644 --- a/x/nexus/exported/mock/types.go +++ b/x/nexus/exported/mock/types.go @@ -561,21 +561,21 @@ func (mock *MaintainerStateMock) UnmarshalCalls() []struct { return calls } -// Ensure, that LockableCoinMock does implement exported.LockableCoin. +// Ensure, that LockableAssetMock does implement exported.LockableAsset. // If this is not the case, regenerate this file with moq. -var _ exported.LockableCoin = &LockableCoinMock{} +var _ exported.LockableAsset = &LockableAssetMock{} -// LockableCoinMock is a mock implementation of exported.LockableCoin. +// LockableAssetMock is a mock implementation of exported.LockableAsset. // -// func TestSomethingThatUsesLockableCoin(t *testing.T) { +// func TestSomethingThatUsesLockableAsset(t *testing.T) { // -// // make and configure a mocked exported.LockableCoin -// mockedLockableCoin := &LockableCoinMock{ -// GetCoinFunc: func() types.Coin { -// panic("mock out the GetCoin method") +// // make and configure a mocked exported.LockableAsset +// mockedLockableAsset := &LockableAssetMock{ +// GetAssetFunc: func() types.Coin { +// panic("mock out the GetAsset method") // }, -// GetOriginalCoinFunc: func(ctx types.Context) types.Coin { -// panic("mock out the GetOriginalCoin method") +// GetCoinFunc: func(ctx types.Context) types.Coin { +// panic("mock out the GetCoin method") // }, // LockFromFunc: func(ctx types.Context, fromAddr types.AccAddress) error { // panic("mock out the LockFrom method") @@ -585,16 +585,16 @@ var _ exported.LockableCoin = &LockableCoinMock{} // }, // } // -// // use mockedLockableCoin in code that requires exported.LockableCoin +// // use mockedLockableAsset in code that requires exported.LockableAsset // // and then make assertions. // // } -type LockableCoinMock struct { - // GetCoinFunc mocks the GetCoin method. - GetCoinFunc func() types.Coin +type LockableAssetMock struct { + // GetAssetFunc mocks the GetAsset method. + GetAssetFunc func() types.Coin - // GetOriginalCoinFunc mocks the GetOriginalCoin method. - GetOriginalCoinFunc func(ctx types.Context) types.Coin + // GetCoinFunc mocks the GetCoin method. + GetCoinFunc func(ctx types.Context) types.Coin // LockFromFunc mocks the LockFrom method. LockFromFunc func(ctx types.Context, fromAddr types.AccAddress) error @@ -604,11 +604,11 @@ type LockableCoinMock struct { // calls tracks calls to the methods. calls struct { + // GetAsset holds details about calls to the GetAsset method. + GetAsset []struct { + } // GetCoin holds details about calls to the GetCoin method. GetCoin []struct { - } - // GetOriginalCoin holds details about calls to the GetOriginalCoin method. - GetOriginalCoin []struct { // Ctx is the ctx argument value. Ctx types.Context } @@ -627,75 +627,75 @@ type LockableCoinMock struct { ToAddr types.AccAddress } } - lockGetCoin sync.RWMutex - lockGetOriginalCoin sync.RWMutex - lockLockFrom sync.RWMutex - lockUnlockTo sync.RWMutex + lockGetAsset sync.RWMutex + lockGetCoin sync.RWMutex + lockLockFrom sync.RWMutex + lockUnlockTo sync.RWMutex } -// GetCoin calls GetCoinFunc. -func (mock *LockableCoinMock) GetCoin() types.Coin { - if mock.GetCoinFunc == nil { - panic("LockableCoinMock.GetCoinFunc: method is nil but LockableCoin.GetCoin was just called") +// GetAsset calls GetAssetFunc. +func (mock *LockableAssetMock) GetAsset() types.Coin { + if mock.GetAssetFunc == nil { + panic("LockableAssetMock.GetAssetFunc: method is nil but LockableAsset.GetAsset was just called") } callInfo := struct { }{} - mock.lockGetCoin.Lock() - mock.calls.GetCoin = append(mock.calls.GetCoin, callInfo) - mock.lockGetCoin.Unlock() - return mock.GetCoinFunc() + mock.lockGetAsset.Lock() + mock.calls.GetAsset = append(mock.calls.GetAsset, callInfo) + mock.lockGetAsset.Unlock() + return mock.GetAssetFunc() } -// GetCoinCalls gets all the calls that were made to GetCoin. +// GetAssetCalls gets all the calls that were made to GetAsset. // Check the length with: // -// len(mockedLockableCoin.GetCoinCalls()) -func (mock *LockableCoinMock) GetCoinCalls() []struct { +// len(mockedLockableAsset.GetAssetCalls()) +func (mock *LockableAssetMock) GetAssetCalls() []struct { } { var calls []struct { } - mock.lockGetCoin.RLock() - calls = mock.calls.GetCoin - mock.lockGetCoin.RUnlock() + mock.lockGetAsset.RLock() + calls = mock.calls.GetAsset + mock.lockGetAsset.RUnlock() return calls } -// GetOriginalCoin calls GetOriginalCoinFunc. -func (mock *LockableCoinMock) GetOriginalCoin(ctx types.Context) types.Coin { - if mock.GetOriginalCoinFunc == nil { - panic("LockableCoinMock.GetOriginalCoinFunc: method is nil but LockableCoin.GetOriginalCoin was just called") +// GetCoin calls GetCoinFunc. +func (mock *LockableAssetMock) GetCoin(ctx types.Context) types.Coin { + if mock.GetCoinFunc == nil { + panic("LockableAssetMock.GetCoinFunc: method is nil but LockableAsset.GetCoin was just called") } callInfo := struct { Ctx types.Context }{ Ctx: ctx, } - mock.lockGetOriginalCoin.Lock() - mock.calls.GetOriginalCoin = append(mock.calls.GetOriginalCoin, callInfo) - mock.lockGetOriginalCoin.Unlock() - return mock.GetOriginalCoinFunc(ctx) + mock.lockGetCoin.Lock() + mock.calls.GetCoin = append(mock.calls.GetCoin, callInfo) + mock.lockGetCoin.Unlock() + return mock.GetCoinFunc(ctx) } -// GetOriginalCoinCalls gets all the calls that were made to GetOriginalCoin. +// GetCoinCalls gets all the calls that were made to GetCoin. // Check the length with: // -// len(mockedLockableCoin.GetOriginalCoinCalls()) -func (mock *LockableCoinMock) GetOriginalCoinCalls() []struct { +// len(mockedLockableAsset.GetCoinCalls()) +func (mock *LockableAssetMock) GetCoinCalls() []struct { Ctx types.Context } { var calls []struct { Ctx types.Context } - mock.lockGetOriginalCoin.RLock() - calls = mock.calls.GetOriginalCoin - mock.lockGetOriginalCoin.RUnlock() + mock.lockGetCoin.RLock() + calls = mock.calls.GetCoin + mock.lockGetCoin.RUnlock() return calls } // LockFrom calls LockFromFunc. -func (mock *LockableCoinMock) LockFrom(ctx types.Context, fromAddr types.AccAddress) error { +func (mock *LockableAssetMock) LockFrom(ctx types.Context, fromAddr types.AccAddress) error { if mock.LockFromFunc == nil { - panic("LockableCoinMock.LockFromFunc: method is nil but LockableCoin.LockFrom was just called") + panic("LockableAssetMock.LockFromFunc: method is nil but LockableAsset.LockFrom was just called") } callInfo := struct { Ctx types.Context @@ -713,8 +713,8 @@ func (mock *LockableCoinMock) LockFrom(ctx types.Context, fromAddr types.AccAddr // LockFromCalls gets all the calls that were made to LockFrom. // Check the length with: // -// len(mockedLockableCoin.LockFromCalls()) -func (mock *LockableCoinMock) LockFromCalls() []struct { +// len(mockedLockableAsset.LockFromCalls()) +func (mock *LockableAssetMock) LockFromCalls() []struct { Ctx types.Context FromAddr types.AccAddress } { @@ -729,9 +729,9 @@ func (mock *LockableCoinMock) LockFromCalls() []struct { } // UnlockTo calls UnlockToFunc. -func (mock *LockableCoinMock) UnlockTo(ctx types.Context, toAddr types.AccAddress) error { +func (mock *LockableAssetMock) UnlockTo(ctx types.Context, toAddr types.AccAddress) error { if mock.UnlockToFunc == nil { - panic("LockableCoinMock.UnlockToFunc: method is nil but LockableCoin.UnlockTo was just called") + panic("LockableAssetMock.UnlockToFunc: method is nil but LockableAsset.UnlockTo was just called") } callInfo := struct { Ctx types.Context @@ -749,8 +749,8 @@ func (mock *LockableCoinMock) UnlockTo(ctx types.Context, toAddr types.AccAddres // UnlockToCalls gets all the calls that were made to UnlockTo. // Check the length with: // -// len(mockedLockableCoin.UnlockToCalls()) -func (mock *LockableCoinMock) UnlockToCalls() []struct { +// len(mockedLockableAsset.UnlockToCalls()) +func (mock *LockableAssetMock) UnlockToCalls() []struct { Ctx types.Context ToAddr types.AccAddress } { diff --git a/x/nexus/exported/types.go b/x/nexus/exported/types.go index 213e52fed..abaa5021e 100644 --- a/x/nexus/exported/types.go +++ b/x/nexus/exported/types.go @@ -19,12 +19,12 @@ import ( "github.com/axelarnetwork/utils/slices" ) -//go:generate moq -out ./mock/types.go -pkg mock . MaintainerState LockableCoin +//go:generate moq -out ./mock/types.go -pkg mock . MaintainerState LockableAsset -// LockableCoin defines a coin that can be locked and unlocked -type LockableCoin interface { - GetCoin() sdk.Coin - GetOriginalCoin(ctx sdk.Context) sdk.Coin +// LockableAsset defines a coin that can be locked and unlocked +type LockableAsset interface { + GetAsset() sdk.Coin + GetCoin(ctx sdk.Context) sdk.Coin LockFrom(ctx sdk.Context, fromAddr sdk.AccAddress) error UnlockTo(ctx sdk.Context, toAddr sdk.AccAddress) error } diff --git a/x/nexus/keeper/lockable_coin.go b/x/nexus/keeper/lockable_coin.go index ad0d88cb4..eb5a8e7e9 100644 --- a/x/nexus/keeper/lockable_coin.go +++ b/x/nexus/keeper/lockable_coin.go @@ -13,13 +13,13 @@ import ( "github.com/axelarnetwork/utils/funcs" ) -// NewLockableCoin creates a new lockable coin -func (k Keeper) NewLockableCoin(ctx sdk.Context, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (exported.LockableCoin, error) { - return newLockableCoin(ctx, k, ibc, bank, coin) +// NewLockableAsset creates a new lockable asset +func (k Keeper) NewLockableAsset(ctx sdk.Context, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (exported.LockableAsset, error) { + return newLockableAsset(ctx, k, ibc, bank, coin) } -// lockableCoin provides functionality to lock and release coins -type lockableCoin struct { +// lockableAsset provides functionality to lock and release coins +type lockableAsset struct { sdk.Coin coinType types.CoinType nexus types.Nexus @@ -27,13 +27,13 @@ type lockableCoin struct { bank types.BankKeeper } -// newLockableCoin creates a coin struct, assign a coin type and normalize the denom if it's a ICS20 token -func newLockableCoin(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (lockableCoin, error) { +// newLockableAsset creates a coin struct, assign a coin type and normalize the denom if it's a ICS20 token +func newLockableAsset(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, bank types.BankKeeper, coin sdk.Coin) (lockableAsset, error) { denom := coin.GetDenom() coinType, err := getCoinType(ctx, nexus, denom) if err != nil { - return lockableCoin{}, err + return lockableAsset{}, err } // If coin type is ICS20, we need to normalize it to convert from 'ibc/{hash}' @@ -41,13 +41,13 @@ func newLockableCoin(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, ba if coinType == types.ICS20 { denomTrace, err := ibc.ParseIBCDenom(ctx, denom) if err != nil { - return lockableCoin{}, err + return lockableAsset{}, err } coin = sdk.NewCoin(denomTrace.GetBaseDenom(), coin.Amount) } - c := lockableCoin{ + c := lockableAsset{ Coin: coin, coinType: coinType, nexus: nexus, @@ -57,28 +57,29 @@ func newLockableCoin(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, ba originalCoin, err := c.getOriginalCoin(ctx) if err != nil { - return lockableCoin{}, err + return lockableAsset{}, err } if originalCoin.GetDenom() != denom { - return lockableCoin{}, fmt.Errorf("denom mismatch, expected %s, got %s", denom, originalCoin.GetDenom()) + return lockableAsset{}, fmt.Errorf("denom mismatch, expected %s, got %s", denom, originalCoin.GetDenom()) } return c, nil } -func (c lockableCoin) GetCoin() sdk.Coin { +// GetAsset returns the coin in nexus registered denomination +func (c lockableAsset) GetAsset() sdk.Coin { return c.Coin } -// GetOriginalCoin returns the original coin -func (c lockableCoin) GetOriginalCoin(ctx sdk.Context) sdk.Coin { +// GetCoin returns the original sdk coin +func (c lockableAsset) GetCoin(ctx sdk.Context) sdk.Coin { // NOTE: must not fail since it's already checked in NewCoin return funcs.Must(c.getOriginalCoin(ctx)) } // LockFrom locks the given coin from the given address -func (c lockableCoin) LockFrom(ctx sdk.Context, fromAddr sdk.AccAddress) error { - coin := c.GetOriginalCoin(ctx) +func (c lockableAsset) LockFrom(ctx sdk.Context, fromAddr sdk.AccAddress) error { + coin := c.GetCoin(ctx) switch c.coinType { case types.ICS20, types.Native: @@ -91,8 +92,8 @@ func (c lockableCoin) LockFrom(ctx sdk.Context, fromAddr sdk.AccAddress) error { } // UnlockTo unlocks the given coin to the given address -func (c lockableCoin) UnlockTo(ctx sdk.Context, toAddr sdk.AccAddress) error { - coin := c.GetOriginalCoin(ctx) +func (c lockableAsset) UnlockTo(ctx sdk.Context, toAddr sdk.AccAddress) error { + coin := c.GetCoin(ctx) switch c.coinType { case types.ICS20, types.Native: @@ -104,7 +105,7 @@ func (c lockableCoin) UnlockTo(ctx sdk.Context, toAddr sdk.AccAddress) error { } } -func (c lockableCoin) getOriginalCoin(ctx sdk.Context) (sdk.Coin, error) { +func (c lockableAsset) getOriginalCoin(ctx sdk.Context) (sdk.Coin, error) { switch c.coinType { case types.ICS20: return c.toICS20(ctx) @@ -115,7 +116,7 @@ func (c lockableCoin) getOriginalCoin(ctx sdk.Context) (sdk.Coin, error) { } } -func (c lockableCoin) toICS20(ctx sdk.Context) (sdk.Coin, error) { +func (c lockableAsset) toICS20(ctx sdk.Context) (sdk.Coin, error) { if c.coinType != types.ICS20 { return sdk.Coin{}, fmt.Errorf("%s is not ICS20 token", c.GetDenom()) } diff --git a/x/nexus/keeper/lockable_coin_test.go b/x/nexus/keeper/lockable_coin_test.go index 7c0dc5146..d8a074ee0 100644 --- a/x/nexus/keeper/lockable_coin_test.go +++ b/x/nexus/keeper/lockable_coin_test.go @@ -21,7 +21,7 @@ import ( . "github.com/axelarnetwork/utils/test" ) -func TestLockableCoin(t *testing.T) { +func TestLockableAsset(t *testing.T) { var ( ctx sdk.Context nexus *mock.NexusMock @@ -93,40 +93,40 @@ func TestLockableCoin(t *testing.T) { coin = sdk.NewCoin(trace.IBCDenom(), sdk.NewInt(rand.PosI64())) }) - t.Run("NewLockableCoin, GetCoin and GetOriginalCoin", func(t *testing.T) { + t.Run("NewLockableAsset, GetAsset and GetCoin", func(t *testing.T) { givenKeeper. When2(whenCoinIsICS20). - Then("should create a new lockable coin of type ICS20", func(t *testing.T) { - lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin) + Then("should create a new lockable asset of type ICS20", func(t *testing.T) { + lockableAsset, err := newLockableAsset(ctx, nexus, ibc, bank, coin) assert.NoError(t, err) - assert.Equal(t, types.CoinType(types.ICS20), lockableCoin.coinType) - assert.Equal(t, sdk.NewCoin(trace.GetBaseDenom(), coin.Amount), lockableCoin.GetCoin()) - assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx)) + assert.Equal(t, types.CoinType(types.ICS20), lockableAsset.coinType) + assert.Equal(t, sdk.NewCoin(trace.GetBaseDenom(), coin.Amount), lockableAsset.GetAsset()) + assert.Equal(t, coin, lockableAsset.GetCoin(ctx)) }). Run(t) givenKeeper. When2(whenCoinIsNative). - Then("should create a new lockable coin of type native", func(t *testing.T) { - lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin) + Then("should create a new lockable asset of type native", func(t *testing.T) { + lockableAsset, err := newLockableAsset(ctx, nexus, ibc, bank, coin) assert.NoError(t, err) - assert.Equal(t, types.CoinType(types.Native), lockableCoin.coinType) - assert.Equal(t, coin, lockableCoin.GetCoin()) - assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx)) + assert.Equal(t, types.CoinType(types.Native), lockableAsset.coinType) + assert.Equal(t, coin, lockableAsset.GetAsset()) + assert.Equal(t, coin, lockableAsset.GetCoin(ctx)) }). Run(t) givenKeeper. When2(whenCoinIsExternal). - Then("should create a new lockable coin of type external", func(t *testing.T) { - lockableCoin, err := newLockableCoin(ctx, nexus, ibc, bank, coin) + Then("should create a new lockable asset of type external", func(t *testing.T) { + lockableAsset, err := newLockableAsset(ctx, nexus, ibc, bank, coin) assert.NoError(t, err) - assert.Equal(t, types.CoinType(types.External), lockableCoin.coinType) - assert.Equal(t, coin, lockableCoin.GetCoin()) - assert.Equal(t, coin, lockableCoin.GetOriginalCoin(ctx)) + assert.Equal(t, types.CoinType(types.External), lockableAsset.coinType) + assert.Equal(t, coin, lockableAsset.GetAsset()) + assert.Equal(t, coin, lockableAsset.GetCoin(ctx)) }). Run(t) }) @@ -137,16 +137,16 @@ func TestLockableCoin(t *testing.T) { Then("should lock the coin", func(t *testing.T) { bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil } - lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + lockableAsset := funcs.Must(newLockableAsset(ctx, nexus, ibc, bank, coin)) fromAddr := rand.AccAddr() - err := lockableCoin.LockFrom(ctx, fromAddr) + err := lockableAsset.LockFrom(ctx, fromAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsCalls(), 1) - assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt) + assert.Equal(t, sdk.NewCoins(lockableAsset.GetCoin(ctx)), bank.SendCoinsCalls()[0].Amt) assert.Equal(t, fromAddr, bank.SendCoinsCalls()[0].FromAddr) - assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].ToAddr) + assert.Equal(t, exported.GetEscrowAddress(lockableAsset.GetCoin(ctx).Denom), bank.SendCoinsCalls()[0].ToAddr) }). Run(t) @@ -155,16 +155,16 @@ func TestLockableCoin(t *testing.T) { Then("should lock the coin", func(t *testing.T) { bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil } - lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + lockableAsset := funcs.Must(newLockableAsset(ctx, nexus, ibc, bank, coin)) fromAddr := rand.AccAddr() - err := lockableCoin.LockFrom(ctx, fromAddr) + err := lockableAsset.LockFrom(ctx, fromAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsCalls(), 1) - assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt) + assert.Equal(t, sdk.NewCoins(lockableAsset.GetCoin(ctx)), bank.SendCoinsCalls()[0].Amt) assert.Equal(t, fromAddr, bank.SendCoinsCalls()[0].FromAddr) - assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].ToAddr) + assert.Equal(t, exported.GetEscrowAddress(lockableAsset.GetCoin(ctx).Denom), bank.SendCoinsCalls()[0].ToAddr) }). Run(t) @@ -176,19 +176,19 @@ func TestLockableCoin(t *testing.T) { } bank.BurnCoinsFunc = func(ctx sdk.Context, moduleName string, amt sdk.Coins) error { return nil } - lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + lockableAsset := funcs.Must(newLockableAsset(ctx, nexus, ibc, bank, coin)) fromAddr := rand.AccAddr() - err := lockableCoin.LockFrom(ctx, fromAddr) + err := lockableAsset.LockFrom(ctx, fromAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsFromAccountToModuleCalls(), 1) assert.Equal(t, fromAddr, bank.SendCoinsFromAccountToModuleCalls()[0].SenderAddr) assert.Equal(t, types.ModuleName, bank.SendCoinsFromAccountToModuleCalls()[0].RecipientModule) - assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsFromAccountToModuleCalls()[0].Amt) + assert.Equal(t, sdk.NewCoins(lockableAsset.GetCoin(ctx)), bank.SendCoinsFromAccountToModuleCalls()[0].Amt) assert.Len(t, bank.BurnCoinsCalls(), 1) assert.Equal(t, types.ModuleName, bank.BurnCoinsCalls()[0].ModuleName) - assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.BurnCoinsCalls()[0].Amt) + assert.Equal(t, sdk.NewCoins(lockableAsset.GetCoin(ctx)), bank.BurnCoinsCalls()[0].Amt) }). Run(t) }) @@ -199,15 +199,15 @@ func TestLockableCoin(t *testing.T) { Then("should unlock the coin", func(t *testing.T) { bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil } - lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + lockableAsset := funcs.Must(newLockableAsset(ctx, nexus, ibc, bank, coin)) toAddr := rand.AccAddr() - err := lockableCoin.UnlockTo(ctx, toAddr) + err := lockableAsset.UnlockTo(ctx, toAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsCalls(), 1) - assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt) - assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].FromAddr) + assert.Equal(t, sdk.NewCoins(lockableAsset.GetCoin(ctx)), bank.SendCoinsCalls()[0].Amt) + assert.Equal(t, exported.GetEscrowAddress(lockableAsset.GetCoin(ctx).Denom), bank.SendCoinsCalls()[0].FromAddr) assert.Equal(t, toAddr, bank.SendCoinsCalls()[0].ToAddr) }). Run(t) @@ -217,15 +217,15 @@ func TestLockableCoin(t *testing.T) { Then("should unlock the coin", func(t *testing.T) { bank.SendCoinsFunc = func(ctx sdk.Context, fromAddr, toAddr sdk.AccAddress, amt sdk.Coins) error { return nil } - lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + lockableAsset := funcs.Must(newLockableAsset(ctx, nexus, ibc, bank, coin)) toAddr := rand.AccAddr() - err := lockableCoin.UnlockTo(ctx, toAddr) + err := lockableAsset.UnlockTo(ctx, toAddr) assert.NoError(t, err) assert.Len(t, bank.SendCoinsCalls(), 1) - assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.SendCoinsCalls()[0].Amt) - assert.Equal(t, exported.GetEscrowAddress(lockableCoin.GetOriginalCoin(ctx).Denom), bank.SendCoinsCalls()[0].FromAddr) + assert.Equal(t, sdk.NewCoins(lockableAsset.GetCoin(ctx)), bank.SendCoinsCalls()[0].Amt) + assert.Equal(t, exported.GetEscrowAddress(lockableAsset.GetCoin(ctx).Denom), bank.SendCoinsCalls()[0].FromAddr) assert.Equal(t, toAddr, bank.SendCoinsCalls()[0].ToAddr) }). Run(t) @@ -238,15 +238,15 @@ func TestLockableCoin(t *testing.T) { return nil } - lockableCoin := funcs.Must(newLockableCoin(ctx, nexus, ibc, bank, coin)) + lockableAsset := funcs.Must(newLockableAsset(ctx, nexus, ibc, bank, coin)) toAddr := rand.AccAddr() - err := lockableCoin.UnlockTo(ctx, toAddr) + err := lockableAsset.UnlockTo(ctx, toAddr) assert.NoError(t, err) assert.Len(t, bank.MintCoinsCalls(), 1) assert.Equal(t, types.ModuleName, bank.MintCoinsCalls()[0].ModuleName) - assert.Equal(t, sdk.NewCoins(lockableCoin.GetOriginalCoin(ctx)), bank.MintCoinsCalls()[0].Amt) + assert.Equal(t, sdk.NewCoins(lockableAsset.GetCoin(ctx)), bank.MintCoinsCalls()[0].Amt) assert.Len(t, bank.SendCoinsFromModuleToAccountCalls(), 1) assert.Equal(t, types.ModuleName, bank.SendCoinsFromModuleToAccountCalls()[0].SenderModule) assert.Equal(t, toAddr, bank.SendCoinsFromModuleToAccountCalls()[0].RecipientAddr) From e6ef32bc118acae6daa455549eaee60edd9303e9 Mon Sep 17 00:00:00 2001 From: Haiyi Zhong Date: Sat, 5 Oct 2024 03:33:42 +0800 Subject: [PATCH 11/11] rename and comments --- app/keepers.go | 2 +- x/axelarnet/keeper/message_route.go | 4 ++-- x/axelarnet/keeper/msg_server.go | 20 ++++++++++---------- x/axelarnet/module.go | 8 ++++---- x/nexus/exported/types.go | 4 +++- x/nexus/keeper/lockable_coin.go | 10 +++++----- 6 files changed, 25 insertions(+), 23 deletions(-) diff --git a/app/keepers.go b/app/keepers.go index 10adb3a28..d26f25e94 100644 --- a/app/keepers.go +++ b/app/keepers.go @@ -446,7 +446,7 @@ func initBankKeeper(appCodec codec.Codec, keys map[string]*sdk.KVStoreKey, keepe maps.Filter(moduleAccountAddrs(moduleAccPerms), func(addr string, _ bool) bool { // we do not rely on internal balance tracking for invariance checks in the nexus module // (https://github.com/cosmos/cosmos-sdk/issues/12825 for more details on the purpose of the blocked list), - // but the module address must be able to use ibc transfers, + // but the nexus module account must be able to send or receive coins to mint/burn them for cross-chain transfers, // so we exclude this address from the blocked list return addr != authtypes.NewModuleAddress(nexusTypes.ModuleName).String() }), diff --git a/x/axelarnet/keeper/message_route.go b/x/axelarnet/keeper/message_route.go index e479e7cec..d6a39a4ed 100644 --- a/x/axelarnet/keeper/message_route.go +++ b/x/axelarnet/keeper/message_route.go @@ -77,12 +77,12 @@ func escrowAssetToMessageSender( return asset, bankK.SendCoins(ctx, sender, types.AxelarIBCAccount, sdk.NewCoins(asset)) case nexus.TypeGeneralMessageWithToken: - coin, err := nexusK.NewLockableAsset(ctx, ibcK, bankK, *msg.Asset) + lockableAsset, err := nexusK.NewLockableAsset(ctx, ibcK, bankK, *msg.Asset) if err != nil { return sdk.Coin{}, err } - return coin.GetCoin(ctx), coin.UnlockTo(ctx, types.AxelarIBCAccount) + return lockableAsset.GetCoin(ctx), lockableAsset.UnlockTo(ctx, types.AxelarIBCAccount) default: return sdk.Coin{}, fmt.Errorf("unrecognized message type") } diff --git a/x/axelarnet/keeper/msg_server.go b/x/axelarnet/keeper/msg_server.go index e6b7c6d16..01a0f8438 100644 --- a/x/axelarnet/keeper/msg_server.go +++ b/x/axelarnet/keeper/msg_server.go @@ -79,7 +79,7 @@ func (s msgServer) CallContract(c context.Context, req *types.CallContractReques }) if req.Fee != nil { - normalizedCoin, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, req.Fee.Amount) + lockableAsset, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, req.Fee.Amount) if err != nil { return nil, sdkerrors.Wrap(err, "unrecognized fee denom") } @@ -93,7 +93,7 @@ func (s msgServer) CallContract(c context.Context, req *types.CallContractReques MessageID: msgID, Recipient: req.Fee.Recipient, Fee: req.Fee.Amount, - Asset: normalizedCoin.GetAsset().Denom, + Asset: lockableAsset.GetAsset().Denom, } if req.Fee.RefundRecipient != nil { feePaidEvent.RefundRecipient = req.Fee.RefundRecipient.String() @@ -185,16 +185,16 @@ func (s msgServer) ConfirmDeposit(c context.Context, req *types.ConfirmDepositRe return nil, fmt.Errorf("recipient chain '%s' is not activated", recipient.Chain.Name) } - normalizedCoin, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, coin) + lockableAsset, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, coin) if err != nil { return nil, err } - if err := normalizedCoin.LockFrom(ctx, req.DepositAddress); err != nil { + if err := lockableAsset.LockFrom(ctx, req.DepositAddress); err != nil { return nil, err } - transferID, err := s.nexus.EnqueueForTransfer(ctx, depositAddr, normalizedCoin.GetAsset()) + transferID, err := s.nexus.EnqueueForTransfer(ctx, depositAddr, lockableAsset.GetAsset()) if err != nil { return nil, err } @@ -403,18 +403,18 @@ func (s msgServer) RouteIBCTransfers(c context.Context, _ *types.RouteIBCTransfe return nil, err } for _, p := range pendingTransfers { - coin, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, p.Asset) + lockableAsset, err := s.nexus.NewLockableAsset(ctx, s.ibcK, s.bank, p.Asset) if err != nil { s.Logger(ctx).Error(fmt.Sprintf("failed to route IBC transfer %s: %s", p.String(), err)) continue } - if err := coin.UnlockTo(ctx, types.AxelarIBCAccount); err != nil { + if err := lockableAsset.UnlockTo(ctx, types.AxelarIBCAccount); err != nil { s.Logger(ctx).Error(fmt.Sprintf("failed to route IBC transfer %s: %s", p.String(), err)) continue } - funcs.MustNoErr(s.EnqueueIBCTransfer(ctx, types.NewIBCTransfer(types.AxelarIBCAccount, p.Recipient.Address, coin.GetCoin(ctx), portID, channelID, p.ID))) + funcs.MustNoErr(s.EnqueueIBCTransfer(ctx, types.NewIBCTransfer(types.AxelarIBCAccount, p.Recipient.Address, lockableAsset.GetCoin(ctx), portID, channelID, p.ID))) s.nexus.ArchivePendingTransfer(ctx, p) } } @@ -499,12 +499,12 @@ func (s msgServer) RouteMessage(c context.Context, req *types.RouteMessageReques } func transfer(ctx sdk.Context, k Keeper, n types.Nexus, b types.BankKeeper, ibc types.IBCKeeper, recipient sdk.AccAddress, coin sdk.Coin) error { - c, err := n.NewLockableAsset(ctx, ibc, b, coin) + lockableAsset, err := n.NewLockableAsset(ctx, ibc, b, coin) if err != nil { return err } - if err := c.UnlockTo(ctx, recipient); err != nil { + if err := lockableAsset.UnlockTo(ctx, recipient); err != nil { return err } diff --git a/x/axelarnet/module.go b/x/axelarnet/module.go index 9f5eaa26e..4eaf299e6 100644 --- a/x/axelarnet/module.go +++ b/x/axelarnet/module.go @@ -342,12 +342,12 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed cross chain transfer transferID, ok := getSeqIDMapping(ctx, m.keeper, port, channel, sequence) if ok { - coin, err := m.nexus.NewLockableAsset(ctx, m.ibcK, m.bank, funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)).Token) + lockableAsset, err := m.nexus.NewLockableAsset(ctx, m.ibcK, m.bank, funcs.MustOk(m.keeper.GetTransfer(ctx, transferID)).Token) if err != nil { return err } - err = coin.LockFrom(ctx, types.AxelarIBCAccount) + err = lockableAsset.LockFrom(ctx, types.AxelarIBCAccount) if err != nil { return err } @@ -368,12 +368,12 @@ func (m AxelarnetIBCModule) setRoutedPacketFailed(ctx sdk.Context, packet channe // check if the packet is Axelar routed general message messageID, ok := getSeqMessageIDMapping(ctx, m.keeper, port, channel, sequence) if ok { - coin, err := m.nexus.NewLockableAsset(ctx, m.ibcK, m.bank, extractTokenFromAckOrTimeoutPacket(packet)) + lockableAsset, err := m.nexus.NewLockableAsset(ctx, m.ibcK, m.bank, extractTokenFromAckOrTimeoutPacket(packet)) if err != nil { return err } - err = coin.LockFrom(ctx, types.AxelarIBCAccount) + err = lockableAsset.LockFrom(ctx, types.AxelarIBCAccount) if err != nil { return err } diff --git a/x/nexus/exported/types.go b/x/nexus/exported/types.go index abaa5021e..57a83c8d5 100644 --- a/x/nexus/exported/types.go +++ b/x/nexus/exported/types.go @@ -21,9 +21,11 @@ import ( //go:generate moq -out ./mock/types.go -pkg mock . MaintainerState LockableAsset -// LockableAsset defines a coin that can be locked and unlocked +// LockableAsset defines a nexus registered asset that can be locked and unlocked type LockableAsset interface { + // GetAsset returns a sdk.Coin using the nexus registered asset as the denom GetAsset() sdk.Coin + // GetCoin returns a sdk.Coin with the actual denom used by x/bank (e.g. ICS20 coins) GetCoin(ctx sdk.Context) sdk.Coin LockFrom(ctx sdk.Context, fromAddr sdk.AccAddress) error UnlockTo(ctx sdk.Context, toAddr sdk.AccAddress) error diff --git a/x/nexus/keeper/lockable_coin.go b/x/nexus/keeper/lockable_coin.go index eb5a8e7e9..02c246142 100644 --- a/x/nexus/keeper/lockable_coin.go +++ b/x/nexus/keeper/lockable_coin.go @@ -55,7 +55,7 @@ func newLockableAsset(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, b bank: bank, } - originalCoin, err := c.getOriginalCoin(ctx) + originalCoin, err := c.getCoin(ctx) if err != nil { return lockableAsset{}, err } @@ -66,15 +66,15 @@ func newLockableAsset(ctx sdk.Context, nexus types.Nexus, ibc types.IBCKeeper, b return c, nil } -// GetAsset returns the coin in nexus registered denomination +// GetAsset returns a sdk.Coin using the nexus registered asset as the denom func (c lockableAsset) GetAsset() sdk.Coin { return c.Coin } -// GetCoin returns the original sdk coin +// GetCoin returns a sdk.Coin with the actual denom used by x/bank (e.g. ICS20 coins) func (c lockableAsset) GetCoin(ctx sdk.Context) sdk.Coin { // NOTE: must not fail since it's already checked in NewCoin - return funcs.Must(c.getOriginalCoin(ctx)) + return funcs.Must(c.getCoin(ctx)) } // LockFrom locks the given coin from the given address @@ -105,7 +105,7 @@ func (c lockableAsset) UnlockTo(ctx sdk.Context, toAddr sdk.AccAddress) error { } } -func (c lockableAsset) getOriginalCoin(ctx sdk.Context) (sdk.Coin, error) { +func (c lockableAsset) getCoin(ctx sdk.Context) (sdk.Coin, error) { switch c.coinType { case types.ICS20: return c.toICS20(ctx)