diff --git a/testutil/keeper/crosschain.go b/testutil/keeper/crosschain.go index 04bbcf7ac9..3fb8f81823 100644 --- a/testutil/keeper/crosschain.go +++ b/testutil/keeper/crosschain.go @@ -198,13 +198,13 @@ func MockGetSupportedChainFromChainID(m *crosschainmocks.CrosschainObserverKeepe Return(senderChain).Once() } -func MockGetRevertGasLimitForERC20(m *crosschainmocks.CrosschainFungibleKeeper, asset string, senderChain chains.Chain) { +func MockGetRevertGasLimitForERC20(m *crosschainmocks.CrosschainFungibleKeeper, asset string, senderChain chains.Chain, returnVal int64) { m.On("GetForeignCoinFromAsset", mock.Anything, asset, senderChain.ChainId). Return(fungibletypes.ForeignCoins{ Zrc20ContractAddress: sample.EthAddress().String(), }, true).Once() m.On("QueryGasLimit", mock.Anything, mock.Anything). - Return(big.NewInt(100), nil).Once() + Return(big.NewInt(returnVal), nil).Once() } func MockPayGasAndUpdateCCTX(m *crosschainmocks.CrosschainFungibleKeeper, m2 *crosschainmocks.CrosschainObserverKeeper, ctx sdk.Context, k keeper.Keeper, senderChain chains.Chain, asset string) { diff --git a/x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go b/x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go index 4c59da3d86..010486017d 100644 --- a/x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go +++ b/x/crosschain/keeper/msg_server_add_to_outtx_tracker_test.go @@ -15,7 +15,6 @@ import ( func getEthereumChainID() int64 { return 5 // Goerli - } // setEnabledChain sets the chain as enabled in chain params diff --git a/x/crosschain/keeper/msg_server_gas_price_voter.go b/x/crosschain/keeper/msg_server_gas_price_voter.go index 308f895f59..52532c206f 100644 --- a/x/crosschain/keeper/msg_server_gas_price_voter.go +++ b/x/crosschain/keeper/msg_server_gas_price_voter.go @@ -25,14 +25,11 @@ func (k msgServer) GasPriceVoter(goCtx context.Context, msg *types.MsgGasPriceVo chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.ChainId) if chain == nil { - return nil, observertypes.ErrSupportedChains + return nil, cosmoserrors.Wrap(types.ErrUnsupportedChain, fmt.Sprintf("ChainID : %d ", msg.ChainId)) } if ok := k.zetaObserverKeeper.IsNonTombstonedObserver(ctx, msg.Creator); !ok { return nil, observertypes.ErrNotObserver } - if chain == nil { - return nil, cosmoserrors.Wrap(types.ErrUnsupportedChain, fmt.Sprintf("ChainID : %d ", msg.ChainId)) - } gasPrice, isFound := k.GetGasPrice(ctx, chain.ChainId) if !isFound { diff --git a/x/crosschain/keeper/msg_server_gas_price_voter_test.go b/x/crosschain/keeper/msg_server_gas_price_voter_test.go new file mode 100644 index 0000000000..50c11dbaa9 --- /dev/null +++ b/x/crosschain/keeper/msg_server_gas_price_voter_test.go @@ -0,0 +1,204 @@ +package keeper_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/chains" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/crosschain/keeper" + "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestMsgServer_GasPriceVoter(t *testing.T) { + t.Run("should error if unsupported chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(nil) + + msgServer := keeper.NewMsgServerImpl(*k) + + res, err := msgServer.GasPriceVoter(ctx, &types.MsgGasPriceVoter{ + ChainId: 5, + }) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if not non tombstoned observer", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{}) + observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(false) + + msgServer := keeper.NewMsgServerImpl(*k) + + res, err := msgServer.GasPriceVoter(ctx, &types.MsgGasPriceVoter{ + ChainId: 5, + }) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if gas price not found and set gas price in fungible keeper fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + UseFungibleMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{ + ChainId: 5, + }) + observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + fungibleMock.On("SetGasPrice", mock.Anything, mock.Anything, mock.Anything).Return(uint64(0), errors.New("err")) + msgServer := keeper.NewMsgServerImpl(*k) + + res, err := msgServer.GasPriceVoter(ctx, &types.MsgGasPriceVoter{ + ChainId: 5, + }) + require.Error(t, err) + require.Nil(t, res) + _, found := k.GetGasPrice(ctx, 5) + require.True(t, found) + }) + + t.Run("should not error if gas price not found and set gas price in fungible keeper succeeds", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + UseFungibleMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{ + ChainId: 5, + }) + observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + fungibleMock.On("SetGasPrice", mock.Anything, mock.Anything, mock.Anything).Return(uint64(1), nil) + msgServer := keeper.NewMsgServerImpl(*k) + creator := sample.AccAddress() + res, err := msgServer.GasPriceVoter(ctx, &types.MsgGasPriceVoter{ + Creator: creator, + ChainId: 5, + Price: 1, + BlockNumber: 1, + }) + require.NoError(t, err) + require.Empty(t, res) + gp, found := k.GetGasPrice(ctx, 5) + require.True(t, found) + require.Equal(t, types.GasPrice{ + Creator: creator, + Index: "5", + ChainId: 5, + Signers: []string{creator}, + BlockNums: []uint64{1}, + Prices: []uint64{1}, + MedianIndex: 0, + }, gp) + }) + + t.Run("should not error if gas price found and msg.creator in signers", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + UseFungibleMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{ + ChainId: 5, + }) + observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + fungibleMock.On("SetGasPrice", mock.Anything, mock.Anything, mock.Anything).Return(uint64(1), nil) + msgServer := keeper.NewMsgServerImpl(*k) + + creator := sample.AccAddress() + k.SetGasPrice(ctx, types.GasPrice{ + Creator: creator, + ChainId: 5, + Signers: []string{creator}, + BlockNums: []uint64{1}, + Prices: []uint64{1}, + }) + + res, err := msgServer.GasPriceVoter(ctx, &types.MsgGasPriceVoter{ + Creator: creator, + ChainId: 5, + BlockNumber: 2, + Price: 2, + }) + require.NoError(t, err) + require.Empty(t, res) + gp, found := k.GetGasPrice(ctx, 5) + require.True(t, found) + require.Equal(t, types.GasPrice{ + Creator: creator, + Index: "", + ChainId: 5, + Signers: []string{creator}, + BlockNums: []uint64{2}, + Prices: []uint64{2}, + MedianIndex: 0, + }, gp) + }) + + t.Run("should not error if gas price found and msg.creator not in signers", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + UseFungibleMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetSupportedChainFromChainID", mock.Anything, mock.Anything).Return(&chains.Chain{ + ChainId: 5, + }) + observerMock.On("IsNonTombstonedObserver", mock.Anything, mock.Anything).Return(true) + + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + fungibleMock.On("SetGasPrice", mock.Anything, mock.Anything, mock.Anything).Return(uint64(1), nil) + msgServer := keeper.NewMsgServerImpl(*k) + + creator := sample.AccAddress() + k.SetGasPrice(ctx, types.GasPrice{ + Creator: creator, + ChainId: 5, + BlockNums: []uint64{1}, + Prices: []uint64{1}, + }) + + res, err := msgServer.GasPriceVoter(ctx, &types.MsgGasPriceVoter{ + Creator: creator, + ChainId: 5, + BlockNumber: 2, + Price: 2, + }) + require.NoError(t, err) + require.Empty(t, res) + gp, found := k.GetGasPrice(ctx, 5) + require.True(t, found) + require.Equal(t, types.GasPrice{ + Creator: creator, + Index: "", + ChainId: 5, + Signers: []string{creator}, + BlockNums: []uint64{1, 2}, + Prices: []uint64{1, 2}, + MedianIndex: 1, + }, gp) + }) +} diff --git a/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go b/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go index 511e703acd..fa9884f25a 100644 --- a/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go +++ b/x/crosschain/keeper/msg_server_vote_outbound_tx_test.go @@ -198,7 +198,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { keepertest.MockGetOutBound(observerMock, ctx) // Successfully mock ProcessOutbound - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) _ = keepertest.MockUpdateNonce(observerMock, *senderChain) @@ -257,7 +257,7 @@ func TestKeeper_VoteOnObservedOutboundTx(t *testing.T) { keepertest.MockGetOutBound(observerMock, ctx) // Mock Failed ProcessOutbound - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) observerMock.On("GetChainNonces", mock.Anything, senderChain.ChainName.String()). Return(observertypes.ChainNonces{}, false) diff --git a/x/crosschain/keeper/process_inbound_test.go b/x/crosschain/keeper/process_inbound_test.go index 4b53f817de..1f8c48ccc2 100644 --- a/x/crosschain/keeper/process_inbound_test.go +++ b/x/crosschain/keeper/process_inbound_test.go @@ -152,7 +152,43 @@ func TestKeeper_ProcessZEVMDeposit(t *testing.T) { keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) + + // mock unsuccessful PayGasInERC20AndUpdateCctx + observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). + Return(nil).Once() + + // call ProcessZEVMDeposit + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + k.ProcessZEVMDeposit(ctx, cctx) + require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) + require.Equal(t, fmt.Sprintf("deposit revert message: %s err : %s", errDeposit, observertypes.ErrSupportedChains), cctx.CctxStatus.StatusMessage) + }) + + t.Run("uunable to process zevm deposit HandleEVMDeposit revert fails at PayGasInERC20AndUpdateCctx with gas limit is 0", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + // Setup expected calls + errDeposit := fmt.Errorf("deposit failed") + keepertest.MockRevertForHandleEVMDeposit(fungibleMock, receiver, amount, senderChain.ChainId, errDeposit) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + + // Mock successful GetSupportedChainFromChainID + keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) + + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 0) // mock unsuccessful PayGasInERC20AndUpdateCctx observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). @@ -188,7 +224,7 @@ func TestKeeper_ProcessZEVMDeposit(t *testing.T) { keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) // mock successful PayGasAndUpdateCctx keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) @@ -227,7 +263,7 @@ func TestKeeper_ProcessZEVMDeposit(t *testing.T) { keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) // mock successful PayGasAndUpdateCctx keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) @@ -265,7 +301,7 @@ func TestKeeper_ProcessZEVMDeposit(t *testing.T) { keepertest.MockGetSupportedChainFromChainID(observerMock, senderChain) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) // call ProcessZEVMDeposit cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) @@ -296,9 +332,9 @@ func TestKeeper_ProcessCrosschainMsgPassing(t *testing.T) { // mock successful UpdateNonce updatedNonce := keepertest.MockUpdateNonce(observerMock, *receiverChain) - // call ProcessCrosschainMsgPassing + // call ProcessInbound cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) - k.ProcessCrosschainMsgPassing(ctx, cctx) + k.ProcessInbound(ctx, cctx) require.Equal(t, types.CctxStatus_PendingOutbound, cctx.CctxStatus.Status) require.Equal(t, updatedNonce, cctx.GetCurrentOutTxParam().OutboundTxTssNonce) }) @@ -346,9 +382,9 @@ func TestKeeper_ProcessCrosschainMsgPassing(t *testing.T) { observerMock.On("GetChainNonces", mock.Anything, receiverChain.ChainName.String()). Return(observertypes.ChainNonces{}, false) - // call ProcessCrosschainMsgPassing + // call ProcessInbound cctx := GetERC20Cctx(t, receiver, *receiverChain, "", amount) - k.ProcessCrosschainMsgPassing(ctx, cctx) + k.ProcessInbound(ctx, cctx) require.Equal(t, types.CctxStatus_Aborted, cctx.CctxStatus.Status) require.Contains(t, cctx.CctxStatus.StatusMessage, "cannot find receiver chain nonce") }) diff --git a/x/crosschain/keeper/process_outbound_test.go b/x/crosschain/keeper/process_outbound_test.go index 23877e14f7..3cf1d3a02d 100644 --- a/x/crosschain/keeper/process_outbound_test.go +++ b/x/crosschain/keeper/process_outbound_test.go @@ -67,7 +67,7 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { asset := "" // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) // mock successful PayGasAndUpdateCctx keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) @@ -82,7 +82,38 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingRevert) require.Equal(t, types.TxFinalizationStatus_NotFinalized, cctx.GetCurrentOutTxParam().TxFinalizationStatus) require.Equal(t, types.TxFinalizationStatus_Executed, cctx.OutboundTxParams[0].TxFinalizationStatus) + }) + + t.Run("successfully process failed outbound set to pending revert if gas limit is 0", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseFungibleMock: true, + UseObserverMock: true, + }) + + // Setup mock data + fungibleMock := keepertest.GetCrosschainFungibleMock(t, k) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + receiver := sample.EthAddress() + amount := big.NewInt(42) + senderChain := getValidEthChain(t) + asset := "" + + // mock successful GetRevertGasLimit for ERC20 + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 0) + + // mock successful PayGasAndUpdateCctx + keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) + // mock successful UpdateNonce + _ = keepertest.MockUpdateNonce(observerMock, *senderChain) + + cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + err := k.ProcessFailedOutbound(ctx, cctx, sample.String()) + require.NoError(t, err) + require.Equal(t, cctx.CctxStatus.Status, types.CctxStatus_PendingRevert) + require.Equal(t, types.TxFinalizationStatus_NotFinalized, cctx.GetCurrentOutTxParam().TxFinalizationStatus) + require.Equal(t, types.TxFinalizationStatus_Executed, cctx.OutboundTxParams[0].TxFinalizationStatus) }) t.Run("unable to process revert when update nonce fails", func(t *testing.T) { @@ -100,7 +131,7 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { asset := "" // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) // mock successful PayGasAndUpdateCctx keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) @@ -131,7 +162,7 @@ func TestKeeper_ProcessFailedOutbound(t *testing.T) { asset := "" // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) // mock successful PayGasAndUpdateCctx observerMock.On("GetSupportedChainFromChainID", mock.Anything, senderChain.ChainId). @@ -201,6 +232,15 @@ func TestKeeper_ProcessOutbound(t *testing.T) { require.Equal(t, cctx.GetCurrentOutTxParam().TxFinalizationStatus, types.TxFinalizationStatus_Executed) }) + t.Run("do not process if cctx invalid", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + cctx := GetERC20Cctx(t, sample.EthAddress(), chains.GoerliChain(), "", big.NewInt(42)) + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound + cctx.InboundTxParams = nil + err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) + require.Error(t, err) + }) + t.Run("do not process outbound on error, no new outbound created", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ UseFungibleMock: true, @@ -244,12 +284,16 @@ func TestKeeper_ProcessOutbound(t *testing.T) { cctx := GetERC20Cctx(t, receiver, *senderChain, asset, amount) cctx.OutboundTxParams = append(cctx.OutboundTxParams, sample.OutboundTxParams(sample.Rand())) + cctx.OutboundTxParams[1].ReceiverChainId = 5 + cctx.OutboundTxParams[1].OutboundTxBallotIndex = "" + cctx.OutboundTxParams[1].OutboundTxHash = "" + cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) err := k.ProcessOutbound(ctx, cctx, observertypes.BallotStatus_BallotFinalized_FailureObservation, sample.String()) - require.ErrorContains(t, err, "cannot revert a revert") + require.Error(t, err) }) t.Run("successfully revert a outbound and create a new revert tx", func(t *testing.T) { @@ -270,7 +314,7 @@ func TestKeeper_ProcessOutbound(t *testing.T) { cctx.CctxStatus.Status = types.CctxStatus_PendingOutbound oldOutTxParamsLen := len(cctx.OutboundTxParams) // mock successful GetRevertGasLimit for ERC20 - keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain) + keepertest.MockGetRevertGasLimitForERC20(fungibleMock, asset, *senderChain, 100) // mock successful PayGasAndUpdateCctx keepertest.MockPayGasAndUpdateCCTX(fungibleMock, observerMock, ctx, *k, *senderChain, asset) diff --git a/x/crosschain/keeper/processs_outbound.go b/x/crosschain/keeper/processs_outbound.go index b10df821cc..8f1d5a89eb 100644 --- a/x/crosschain/keeper/processs_outbound.go +++ b/x/crosschain/keeper/processs_outbound.go @@ -103,7 +103,11 @@ func (k Keeper) ProcessFailedOutbound(ctx sdk.Context, cctx *types.CrossChainTx, // The state is committed only if the individual steps are successful func (k Keeper) ProcessOutbound(ctx sdk.Context, cctx *types.CrossChainTx, ballotStatus observertypes.BallotStatus, valueReceived string) error { tmpCtx, commit := ctx.CacheContext() - err := func() error { + err := cctx.Validate() + if err != nil { + return err + } + err = func() error { switch ballotStatus { case observertypes.BallotStatus_BallotFinalized_SuccessObservation: k.ProcessSuccessfulOutbound(tmpCtx, cctx, valueReceived) @@ -118,10 +122,6 @@ func (k Keeper) ProcessOutbound(ctx sdk.Context, cctx *types.CrossChainTx, ballo if err != nil { return err } - err = cctx.Validate() - if err != nil { - return err - } commit() return nil }