From 33f7fc213cff062843e801b3ea85655fae331ee5 Mon Sep 17 00:00:00 2001 From: skosito Date: Mon, 1 Apr 2024 23:02:28 +0200 Subject: [PATCH] Add more tests --- x/crosschain/keeper/foreign_coins_test.go | 20 + .../grpc_query_last_zeta_height_test.go | 2 +- .../keeper/grpc_query_out_tx_tracker_test.go | 10 + x/crosschain/keeper/params_test.go | 34 ++ x/crosschain/keeper/verify_proof_test.go | 393 ++++++++++++++++++ x/crosschain/keeper/zeta_accounting_test.go | 13 +- 6 files changed, 470 insertions(+), 2 deletions(-) create mode 100644 x/crosschain/keeper/foreign_coins_test.go create mode 100644 x/crosschain/keeper/params_test.go create mode 100644 x/crosschain/keeper/verify_proof_test.go diff --git a/x/crosschain/keeper/foreign_coins_test.go b/x/crosschain/keeper/foreign_coins_test.go new file mode 100644 index 0000000000..5d145b08f1 --- /dev/null +++ b/x/crosschain/keeper/foreign_coins_test.go @@ -0,0 +1,20 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" +) + +func TestKeeper_GetAllForeignCoins(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + fc := sample.ForeignCoins(t, sample.EthAddress().Hex()) + fc.ForeignChainId = 101 + k.GetFungibleKeeper().SetForeignCoins(ctx, fc) + + res, err := k.GetAllForeignCoins(ctx) + require.NoError(t, err) + require.Equal(t, 1, len(res)) +} diff --git a/x/crosschain/keeper/grpc_query_last_zeta_height_test.go b/x/crosschain/keeper/grpc_query_last_zeta_height_test.go index bea312c3d0..b34a96be20 100644 --- a/x/crosschain/keeper/grpc_query_last_zeta_height_test.go +++ b/x/crosschain/keeper/grpc_query_last_zeta_height_test.go @@ -19,7 +19,7 @@ func TestKeeper_LastZetaHeight(t *testing.T) { t.Run("should error if height less than zero", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) ctx = ctx.WithBlockHeight(-1) - res, err := k.LastZetaHeight(ctx, nil) + res, err := k.LastZetaHeight(ctx, &types.QueryLastZetaHeightRequest{}) require.Error(t, err) require.Nil(t, res) }) diff --git a/x/crosschain/keeper/grpc_query_out_tx_tracker_test.go b/x/crosschain/keeper/grpc_query_out_tx_tracker_test.go index 40a80ac016..c0c5db7e9b 100644 --- a/x/crosschain/keeper/grpc_query_out_tx_tracker_test.go +++ b/x/crosschain/keeper/grpc_query_out_tx_tracker_test.go @@ -61,6 +61,16 @@ func TestKeeper_OutTxTracker(t *testing.T) { require.Nil(t, res) }) + t.Run("should return if not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + res, err := k.OutTxTracker(ctx, &types.QueryGetOutTxTrackerRequest{ + ChainID: 1, + Nonce: 1, + }) + require.Error(t, err) + require.Nil(t, res) + }) + t.Run("should return if req is not nil", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) k.SetOutTxTracker(ctx, types.OutTxTracker{ diff --git a/x/crosschain/keeper/params_test.go b/x/crosschain/keeper/params_test.go new file mode 100644 index 0000000000..b4a03efb80 --- /dev/null +++ b/x/crosschain/keeper/params_test.go @@ -0,0 +1,34 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/x/crosschain/types" +) + +func TestKeeper_GetParams(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + params := k.GetParams(ctx) + // TODO: there is no get params method? + k.SetParams(ctx, types.Params{Enabled: false}) + require.Equal(t, types.NewParams(), params) + require.True(t, params.Enabled) +} + +func TestKeeper_QueryParams(t *testing.T) { + t.Run("should error if req is nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + res, err := k.Params(ctx, nil) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return params", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + res, err := k.Params(ctx, &types.QueryParamsRequest{}) + require.NoError(t, err) + require.True(t, res.Params.Enabled) + }) +} diff --git a/x/crosschain/keeper/verify_proof_test.go b/x/crosschain/keeper/verify_proof_test.go new file mode 100644 index 0000000000..62d47773b9 --- /dev/null +++ b/x/crosschain/keeper/verify_proof_test.go @@ -0,0 +1,393 @@ +package keeper_test + +import ( + "errors" + "math/big" + "testing" + + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/coin" + "github.com/zeta-chain/zetacore/pkg/proofs" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/crosschain/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" +) + +func TestKeeper_VerifyProof(t *testing.T) { + t.Run("should error if crosschain flags not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetCrosschainFlags", mock.Anything).Return(observertypes.CrosschainFlags{}, false) + + res, err := k.VerifyProof(ctx, &proofs.Proof{}, 5, sample.Hash().String(), 1) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if BlockHeaderVerificationFlags nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetCrosschainFlags", mock.Anything).Return(observertypes.CrosschainFlags{ + BlockHeaderVerificationFlags: nil, + }, true) + + res, err := k.VerifyProof(ctx, &proofs.Proof{}, 5, sample.Hash().String(), 1) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if verification not enabled for btc chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetCrosschainFlags", mock.Anything).Return(observertypes.CrosschainFlags{ + BlockHeaderVerificationFlags: &observertypes.BlockHeaderVerificationFlags{ + IsBtcTypeChainEnabled: false, + }, + }, true) + + res, err := k.VerifyProof(ctx, &proofs.Proof{}, 18444, sample.Hash().String(), 1) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if verification not enabled for evm chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetCrosschainFlags", mock.Anything).Return(observertypes.CrosschainFlags{ + BlockHeaderVerificationFlags: &observertypes.BlockHeaderVerificationFlags{ + IsEthTypeChainEnabled: false, + }, + }, true) + + res, err := k.VerifyProof(ctx, &proofs.Proof{}, 5, sample.Hash().String(), 1) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if block header-based verification not supported", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetCrosschainFlags", mock.Anything).Return(observertypes.CrosschainFlags{ + BlockHeaderVerificationFlags: &observertypes.BlockHeaderVerificationFlags{ + IsEthTypeChainEnabled: false, + }, + }, true) + + res, err := k.VerifyProof(ctx, &proofs.Proof{}, 101, sample.Hash().String(), 1) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if blockhash invalid", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetCrosschainFlags", mock.Anything).Return(observertypes.CrosschainFlags{ + BlockHeaderVerificationFlags: &observertypes.BlockHeaderVerificationFlags{ + IsBtcTypeChainEnabled: true, + }, + }, true) + + res, err := k.VerifyProof(ctx, &proofs.Proof{}, 18444, "invalid", 1) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if block header not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetCrosschainFlags", mock.Anything).Return(observertypes.CrosschainFlags{ + BlockHeaderVerificationFlags: &observertypes.BlockHeaderVerificationFlags{ + IsEthTypeChainEnabled: true, + }, + }, true) + + observerMock.On("GetBlockHeader", mock.Anything, mock.Anything).Return(proofs.BlockHeader{}, false) + + res, err := k.VerifyProof(ctx, &proofs.Proof{}, 5, sample.Hash().String(), 1) + require.Error(t, err) + require.Nil(t, res) + }) + // TODO: // https://github.com/zeta-chain/node/issues/1875 add more tests +} + +func TestKeeper_VerifyEVMInTxBody(t *testing.T) { + to := sample.EthAddress() + tx := ethtypes.NewTx(ðtypes.DynamicFeeTx{ + ChainID: big.NewInt(5), + Nonce: 1, + GasTipCap: nil, + GasFeeCap: nil, + Gas: 21000, + To: &to, + Value: big.NewInt(5), + Data: nil, + }) + t.Run("should error if msg tx hash not correct", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: "0x0", + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should error if msg chain id not correct", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: 1, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should error if not supported coin type", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_Cmd, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should error for cointype_zeta if chain params not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything).Return(&observertypes.ChainParams{}, false) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_Zeta, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should error for cointype_zeta if tx.to wrong", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything).Return(&observertypes.ChainParams{ + ConnectorContractAddress: sample.EthAddress().Hex(), + }, true) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_Zeta, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should not error for cointype_zeta", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything).Return(&observertypes.ChainParams{ + ConnectorContractAddress: to.Hex(), + }, true) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_Zeta, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.NoError(t, err) + }) + + t.Run("should error for cointype_erc20 if chain params not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything).Return(&observertypes.ChainParams{}, false) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_ERC20, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should error for cointype_erc20 if tx.to wrong", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything).Return(&observertypes.ChainParams{ + Erc20CustodyContractAddress: sample.EthAddress().Hex(), + }, true) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_ERC20, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should not error for cointype_erc20", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetChainParamsByChainID", mock.Anything, mock.Anything).Return(&observertypes.ChainParams{ + Erc20CustodyContractAddress: to.Hex(), + }, true) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_ERC20, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.NoError(t, err) + }) + + t.Run("should error for cointype_gas if tss address not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetTssAddress", mock.Anything, mock.Anything).Return(&observertypes.QueryGetTssAddressResponse{}, errors.New("err")) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_Gas, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should error for cointype_gas if tss eth address is empty", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetTssAddress", mock.Anything, mock.Anything).Return(&observertypes.QueryGetTssAddressResponse{ + Eth: "0x", + }, nil) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_Gas, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should error for cointype_gas if tss eth address is wrong", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetTssAddress", mock.Anything, mock.Anything).Return(&observertypes.QueryGetTssAddressResponse{ + Eth: sample.EthAddress().Hex(), + }, nil) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_Gas, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.Error(t, err) + }) + + t.Run("should not error for cointype_gas", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, keepertest.CrosschainMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetCrosschainObserverMock(t, k) + observerMock.On("GetTssAddress", mock.Anything, mock.Anything).Return(&observertypes.QueryGetTssAddressResponse{ + Eth: to.Hex(), + }, nil) + + txBytes, err := tx.MarshalBinary() + require.NoError(t, err) + msg := &types.MsgAddToInTxTracker{ + TxHash: tx.Hash().Hex(), + ChainId: tx.ChainId().Int64(), + CoinType: coin.CoinType_Gas, + } + + err = k.VerifyEVMInTxBody(ctx, msg, txBytes) + require.NoError(t, err) + }) +} diff --git a/x/crosschain/keeper/zeta_accounting_test.go b/x/crosschain/keeper/zeta_accounting_test.go index 8802fe7666..7a3eee1223 100644 --- a/x/crosschain/keeper/zeta_accounting_test.go +++ b/x/crosschain/keeper/zeta_accounting_test.go @@ -11,7 +11,6 @@ import ( ) func TestKeeper_AddZetaAccounting(t *testing.T) { - t.Run("should add aborted zeta amount", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) originalAmount := sdkmath.NewUint(rand.Uint64()) @@ -28,6 +27,18 @@ func TestKeeper_AddZetaAccounting(t *testing.T) { require.Equal(t, originalAmount.Add(addAmount), val.AbortedZetaAmount) }) + t.Run("should add aborted zeta amount if accounting not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + originalAmount := sdkmath.NewUint(0) + _, found := k.GetZetaAccounting(ctx) + require.False(t, found) + addAmount := sdkmath.NewUint(rand.Uint64()) + k.AddZetaAbortedAmount(ctx, addAmount) + val, found := k.GetZetaAccounting(ctx) + require.True(t, found) + require.Equal(t, originalAmount.Add(addAmount), val.AbortedZetaAmount) + }) + t.Run("cant find aborted amount", func(t *testing.T) { k, ctx, _, _ := keepertest.CrosschainKeeper(t) val, found := k.GetZetaAccounting(ctx)