From 131a774b06d39e8c1a7884d34f4d962f9edff626 Mon Sep 17 00:00:00 2001 From: skosito Date: Fri, 5 Apr 2024 06:50:26 +0100 Subject: [PATCH 1/3] test: improve fungible module coverage (#1985) * Add more tests for fungible module * Changelog * Try out codecov issue * Revert * Add more tests * PR comments --- changelog.md | 1 + testutil/keeper/mocks/observer/staking.go | 5 - x/fungible/keeper/deposits_test.go | 17 + x/fungible/keeper/evm.go | 43 +- x/fungible/keeper/evm_hooks.go | 6 +- x/fungible/keeper/evm_hooks_test.go | 3 +- x/fungible/keeper/evm_test.go | 643 +++++++++++++++++- x/fungible/keeper/gas_coin_and_pool.go | 1 - x/fungible/keeper/gas_coin_and_pool_test.go | 301 +++++++- x/fungible/keeper/gas_stability_pool_test.go | 17 + .../keeper/grpc_query_code_hash_test.go | 7 + .../grpc_query_gas_stability_pool_test.go | 142 ++++ .../keeper/grpc_query_system_contract_test.go | 40 ++ .../msg_server_deploy_system_contract_test.go | 132 +++- .../msg_server_update_system_contract_test.go | 5 + ...g_server_update_zrc20_withdraw_fee_test.go | 7 +- x/fungible/types/zrc20_test.go | 15 + x/observer/keeper/hooks_test.go | 30 +- x/observer/keeper/utils_test.go | 40 +- x/observer/types/expected_keepers.go | 1 - 20 files changed, 1352 insertions(+), 104 deletions(-) create mode 100644 x/fungible/keeper/grpc_query_gas_stability_pool_test.go create mode 100644 x/fungible/keeper/grpc_query_system_contract_test.go create mode 100644 x/fungible/types/zrc20_test.go diff --git a/changelog.md b/changelog.md index 4dde927265..f847d51c33 100644 --- a/changelog.md +++ b/changelog.md @@ -56,6 +56,7 @@ * [1961](https://github.com/zeta-chain/node/pull/1961) - improve observer module coverage * [1967](https://github.com/zeta-chain/node/pull/1967) - improve crosschain module coverage * [1955](https://github.com/zeta-chain/node/pull/1955) - improve emissions module coverage +* [1985](https://github.com/zeta-chain/node/pull/1985) - improve fungible module coverage ### Fixes diff --git a/testutil/keeper/mocks/observer/staking.go b/testutil/keeper/mocks/observer/staking.go index 72bf99599f..90007b6c35 100644 --- a/testutil/keeper/mocks/observer/staking.go +++ b/testutil/keeper/mocks/observer/staking.go @@ -71,11 +71,6 @@ func (_m *ObserverStakingKeeper) GetValidator(ctx types.Context, addr types.ValA return r0, r1 } -// SetDelegation provides a mock function with given fields: ctx, delegation -func (_m *ObserverStakingKeeper) SetDelegation(ctx types.Context, delegation stakingtypes.Delegation) { - _m.Called(ctx, delegation) -} - // SetValidator provides a mock function with given fields: ctx, validator func (_m *ObserverStakingKeeper) SetValidator(ctx types.Context, validator stakingtypes.Validator) { _m.Called(ctx, validator) diff --git a/x/fungible/keeper/deposits_test.go b/x/fungible/keeper/deposits_test.go index 858a8130ce..dc69febd24 100644 --- a/x/fungible/keeper/deposits_test.go +++ b/x/fungible/keeper/deposits_test.go @@ -6,7 +6,9 @@ import ( "cosmossdk.io/math" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/cmd/zetacored/config" "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/coin" "github.com/zeta-chain/zetacore/testutil/contracts" @@ -352,3 +354,18 @@ func TestKeeper_ZRC20DepositAndCallContract(t *testing.T) { require.EqualValues(t, int64(0), balance.Int64()) }) } + +func TestKeeper_DepositCoinZeta(t *testing.T) { + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + to := sample.EthAddress() + amount := big.NewInt(1) + zetaToAddress := sdk.AccAddress(to.Bytes()) + + b := sdkk.BankKeeper.GetBalance(ctx, zetaToAddress, config.BaseDenom) + require.Equal(t, int64(0), b.Amount.Int64()) + + err := k.DepositCoinZeta(ctx, to, amount) + require.NoError(t, err) + b = sdkk.BankKeeper.GetBalance(ctx, zetaToAddress, config.BaseDenom) + require.Equal(t, amount.Int64(), b.Amount.Int64()) +} diff --git a/x/fungible/keeper/evm.go b/x/fungible/keeper/evm.go index 313a1301aa..427849f19c 100644 --- a/x/fungible/keeper/evm.go +++ b/x/fungible/keeper/evm.go @@ -54,7 +54,7 @@ func (k Keeper) DeployContract(ctx sdk.Context, metadata *bind.MetaData, ctorArg } if len(metadata.Bin) <= 2 { - return common.Address{}, cosmoserrors.Wrapf(types.ErrABIGet, "metadata Bin field too short: %s", err.Error()) + return common.Address{}, cosmoserrors.Wrapf(types.ErrABIGet, "metadata Bin field too short") } bin, err := hex.DecodeString(metadata.Bin[2:]) @@ -98,10 +98,6 @@ func (k Keeper) DeployZRC20Contract( if chain == nil { return common.Address{}, cosmoserrors.Wrapf(zetaObserverTypes.ErrSupportedChains, "chain %d not found", chainID) } - chainStr := chain.ChainName.String() - if chain == nil { - return common.Address{}, cosmoserrors.Wrapf(zetaObserverTypes.ErrSupportedChains, "chain %s not found", chainStr) - } // Check if Contract has already been deployed for Asset _, found := k.GetForeignCoinFromAsset(ctx, erc20Contract, chainID) if found { @@ -309,43 +305,6 @@ func (k Keeper) DepositZRC20AndCallContract(ctx sdk.Context, ) } -// QueryWithdrawGasFee returns the gas fee for a withdrawal transaction associated with a given zrc20 -func (k Keeper) QueryWithdrawGasFee(ctx sdk.Context, contract common.Address) (*big.Int, error) { - zrc20ABI, err := zrc20.ZRC20MetaData.GetAbi() - if err != nil { - return nil, err - } - res, err := k.CallEVM( - ctx, - *zrc20ABI, - types.ModuleAddressEVM, - contract, - BigIntZero, - nil, - false, - false, - "withdrawGasFee", - ) - if err != nil { - return nil, err - } - - unpacked, err := zrc20ABI.Unpack("withdrawGasFee", res.Ret) - if err != nil { - return nil, err - } - if len(unpacked) < 2 { - return nil, fmt.Errorf("expect 2 returned values, got %d", len(unpacked)) - } - - GasFee, ok := unpacked[1].(*big.Int) - if !ok { - return nil, errors.New("can't read returned value as big.Int") - } - - return GasFee, nil -} - // QueryProtocolFlatFee returns the protocol flat fee associated with a given zrc20 func (k Keeper) QueryProtocolFlatFee(ctx sdk.Context, contract common.Address) (*big.Int, error) { zrc20ABI, err := zrc20.ZRC20MetaData.GetAbi() diff --git a/x/fungible/keeper/evm_hooks.go b/x/fungible/keeper/evm_hooks.go index 80d4303089..4e3894290c 100644 --- a/x/fungible/keeper/evm_hooks.go +++ b/x/fungible/keeper/evm_hooks.go @@ -22,12 +22,12 @@ func (k Keeper) EVMHooks() EVMHooks { // PostTxProcessing is a wrapper for calling the EVM PostTxProcessing hook on the module keeper func (h EVMHooks) PostTxProcessing(ctx sdk.Context, _ core.Message, receipt *ethtypes.Receipt) error { - return h.k.CheckPausedZRC20(ctx, receipt) + return h.k.checkPausedZRC20(ctx, receipt) } -// CheckPausedZRC20 checks the events of the receipt +// checkPausedZRC20 checks the events of the receipt // if an event is emitted from a paused ZRC20 contract it will revert the transaction -func (k Keeper) CheckPausedZRC20(ctx sdk.Context, receipt *ethtypes.Receipt) error { +func (k Keeper) checkPausedZRC20(ctx sdk.Context, receipt *ethtypes.Receipt) error { if receipt == nil { return nil } diff --git a/x/fungible/keeper/evm_hooks_test.go b/x/fungible/keeper/evm_hooks_test.go index 696fbbd9cd..70bc486c0d 100644 --- a/x/fungible/keeper/evm_hooks_test.go +++ b/x/fungible/keeper/evm_hooks_test.go @@ -123,7 +123,8 @@ func TestKeeper_CheckPausedZRC20(t *testing.T) { assertPaused(addrPausedZRC20.Hex()) // process test - err := k.CheckPausedZRC20(ctx, tc.receipt) + h := k.EVMHooks() + err := h.PostTxProcessing(ctx, nil, tc.receipt) if tc.wantErr { require.ErrorIs(t, err, types.ErrPausedZRC20) } else { diff --git a/x/fungible/keeper/evm_test.go b/x/fungible/keeper/evm_test.go index 8d52742c0c..753d82e7e6 100644 --- a/x/fungible/keeper/evm_test.go +++ b/x/fungible/keeper/evm_test.go @@ -6,16 +6,20 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" evmtypes "github.com/evmos/ethermint/x/evm/types" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/systemcontract.sol" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/wzeta.sol" + zrc20 "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol" "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/coin" "github.com/zeta-chain/zetacore/server/config" "github.com/zeta-chain/zetacore/testutil/contracts" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" testkeeper "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/testutil/sample" fungiblekeeper "github.com/zeta-chain/zetacore/x/fungible/keeper" @@ -169,6 +173,71 @@ func assertExampleBarValue( } func TestKeeper_DeployZRC20Contract(t *testing.T) { + t.Run("should error if chain not found", func(t *testing.T) { + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + + addr, err := k.DeployZRC20Contract( + ctx, + "foo", + "bar", + 8, + 987, + coin.CoinType_Gas, + "foobar", + big.NewInt(1000), + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if system contracts not deployed", func(t *testing.T) { + k, ctx, _, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + + addr, err := k.DeployZRC20Contract( + ctx, + "foo", + "bar", + 8, + chainID, + coin.CoinType_Gas, + "foobar", + big.NewInt(1000), + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if deploy contract fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + chainID := getValidChainID(t) + mockFailedContractDeployment(ctx, t, k) + + addr, err := k.DeployZRC20Contract( + ctx, + "foo", + "bar", + 8, + chainID, + coin.CoinType_Gas, + "foobar", + big.NewInt(1000), + ) + require.Error(t, err) + require.Empty(t, addr) + }) + t.Run("can deploy the zrc20 contract", func(t *testing.T) { k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) @@ -225,7 +294,61 @@ func TestKeeper_DeployZRC20Contract(t *testing.T) { }) } -func TestKeeper_DeploySystemContract(t *testing.T) { +func TestKeeper_DeploySystemContracts(t *testing.T) { + t.Run("system contract deployment should error if deploy contract fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + wzeta, uniswapV2Factory, uniswapV2Router, _, _ := deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + mockFailedContractDeployment(ctx, t, k) + + res, err := k.DeploySystemContract(ctx, wzeta, uniswapV2Factory, uniswapV2Router) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("router deployment should error if deploy contract fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockFailedContractDeployment(ctx, t, k) + + res, err := k.DeployUniswapV2Router02(ctx, sample.EthAddress(), sample.EthAddress()) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("wzeta deployment should error if deploy contract fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockFailedContractDeployment(ctx, t, k) + + res, err := k.DeployWZETA(ctx) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("connector deployment should error if deploy contract fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockFailedContractDeployment(ctx, t, k) + + res, err := k.DeployConnectorZEVM(ctx, sample.EthAddress()) + require.Error(t, err) + require.Empty(t, res) + }) + t.Run("can deploy the system contracts", func(t *testing.T) { k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) @@ -280,6 +403,32 @@ func TestKeeper_DeploySystemContract(t *testing.T) { } func TestKeeper_DepositZRC20AndCallContract(t *testing.T) { + t.Run("should error if system contracts not deployed", func(t *testing.T) { + k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + + example, err := k.DeployContract(ctx, contracts.ExampleMetaData) + require.NoError(t, err) + assertContractDeployment(t, sdkk.EvmKeeper, ctx, example) + + res, err := k.DepositZRC20AndCallContract( + ctx, + systemcontract.ZContext{ + Origin: sample.EthAddress().Bytes(), + Sender: sample.EthAddress(), + ChainID: big.NewInt(chainID), + }, + sample.EthAddress(), + example, + big.NewInt(42), + []byte(""), + ) + require.Error(t, err) + require.Nil(t, res) + }) + t.Run("should deposit and call the contract", func(t *testing.T) { k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) @@ -685,3 +834,495 @@ func TestKeeper_CallEVMWithData(t *testing.T) { require.ErrorIs(t, err, sample.ErrSample) }) } + +func TestKeeper_DeployContract(t *testing.T) { + t.Run("should error if pack ctor args fails", func(t *testing.T) { + k, ctx, _, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + addr, err := k.DeployContract(ctx, zrc20.ZRC20MetaData, "") + require.ErrorIs(t, err, types.ErrABIGet) + require.Empty(t, addr) + }) + + t.Run("should error if metadata bin empty", func(t *testing.T) { + k, ctx, _, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + metadata := &bind.MetaData{ + ABI: wzeta.WETH9MetaData.ABI, + Bin: "", + } + addr, err := k.DeployContract(ctx, metadata) + require.ErrorIs(t, err, types.ErrABIGet) + require.Empty(t, addr) + }) + + t.Run("should error if metadata cant be decoded", func(t *testing.T) { + k, ctx, _, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + metadata := &bind.MetaData{ + ABI: wzeta.WETH9MetaData.ABI, + Bin: "0x1", + } + addr, err := k.DeployContract(ctx, metadata) + require.ErrorIs(t, err, types.ErrABIPack) + require.Empty(t, addr) + }) + + t.Run("should error if module acc not set up", func(t *testing.T) { + k, ctx, _, _ := testkeeper.FungibleKeeper(t) + addr, err := k.DeployContract(ctx, wzeta.WETH9MetaData) + require.Error(t, err) + require.Empty(t, addr) + }) +} + +func TestKeeper_QueryProtocolFlatFee(t *testing.T) { + t.Run("should error if evm call fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + mockEVMKeeper.MockEVMFailCallOnce() + + res, err := k.QueryProtocolFlatFee(ctx, sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if unpack fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: []byte{}}) + + res, err := k.QueryProtocolFlatFee(ctx, sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return fee", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc20ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + fee := big.NewInt(42) + protocolFlatFee, err := zrc20ABI.Methods["PROTOCOL_FLAT_FEE"].Outputs.Pack(fee) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: protocolFlatFee}) + + res, err := k.QueryProtocolFlatFee(ctx, sample.EthAddress()) + require.NoError(t, err) + require.Equal(t, fee, res) + }) +} + +func TestKeeper_QueryGasLimit(t *testing.T) { + t.Run("should error if evm call fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + mockEVMKeeper.MockEVMFailCallOnce() + + res, err := k.QueryGasLimit(ctx, sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if unpack fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: []byte{}}) + + res, err := k.QueryGasLimit(ctx, sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return gas limit", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc20ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + limit := big.NewInt(42) + gasLimit, err := zrc20ABI.Methods["GAS_LIMIT"].Outputs.Pack(limit) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: gasLimit}) + + res, err := k.QueryGasLimit(ctx, sample.EthAddress()) + require.NoError(t, err) + require.Equal(t, limit, res) + }) +} + +func TestKeeper_QueryChainIDFromContract(t *testing.T) { + t.Run("should error if evm call fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + mockEVMKeeper.MockEVMFailCallOnce() + + res, err := k.QueryChainIDFromContract(ctx, sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if unpack fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: []byte{}}) + + res, err := k.QueryChainIDFromContract(ctx, sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return chain id", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc20ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + chainId := big.NewInt(42) + chainIdFromContract, err := zrc20ABI.Methods["GAS_LIMIT"].Outputs.Pack(chainId) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: chainIdFromContract}) + + res, err := k.QueryChainIDFromContract(ctx, sample.EthAddress()) + require.NoError(t, err) + require.Equal(t, chainId, res) + }) +} + +func TestKeeper_TotalSupplyZRC4(t *testing.T) { + t.Run("should error if evm call fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + mockEVMKeeper.MockEVMFailCallOnce() + + res, err := k.TotalSupplyZRC4(ctx, sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if unpack fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: []byte{}}) + + res, err := k.TotalSupplyZRC4(ctx, sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return total supply", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc20ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + supply := big.NewInt(42) + supplyFromContract, err := zrc20ABI.Methods["GAS_LIMIT"].Outputs.Pack(supply) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: supplyFromContract}) + + res, err := k.TotalSupplyZRC4(ctx, sample.EthAddress()) + require.NoError(t, err) + require.Equal(t, supply, res) + }) +} + +func TestKeeper_BalanceOfZRC4(t *testing.T) { + t.Run("should error if evm call fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + mockEVMKeeper.MockEVMFailCallOnce() + + res, err := k.BalanceOfZRC4(ctx, sample.EthAddress(), sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if unpack fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: []byte{}}) + + res, err := k.BalanceOfZRC4(ctx, sample.EthAddress(), sample.EthAddress()) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return balance", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc20ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + balance := big.NewInt(42) + balanceFromContract, err := zrc20ABI.Methods["GAS_LIMIT"].Outputs.Pack(balance) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: balanceFromContract}) + + res, err := k.BalanceOfZRC4(ctx, sample.EthAddress(), sample.EthAddress()) + require.NoError(t, err) + require.Equal(t, balance, res) + }) +} + +func TestKeeper_QueryZRC20Data(t *testing.T) { + t.Run("should error if evm call fails for name", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + mockEVMKeeper.MockEVMFailCallOnce() + + res, err := k.QueryZRC20Data(ctx, sample.EthAddress()) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("should error if unpack fails for name", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: []byte{}}) + + res, err := k.QueryZRC20Data(ctx, sample.EthAddress()) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("should error if evm call fails for symbol", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc4ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + name, err := zrc4ABI.Methods["name"].Outputs.Pack("name") + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: name}) + + mockEVMKeeper.MockEVMFailCallOnce() + + res, err := k.QueryZRC20Data(ctx, sample.EthAddress()) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("should error if unpack for symbol", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc4ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + name, err := zrc4ABI.Methods["name"].Outputs.Pack("name") + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: name}) + + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: []byte{}}) + + res, err := k.QueryZRC20Data(ctx, sample.EthAddress()) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("should error if evm call fails for decimals", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc4ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + name, err := zrc4ABI.Methods["name"].Outputs.Pack("name") + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: name}) + + symbol, err := zrc4ABI.Methods["symbol"].Outputs.Pack("symbol") + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: symbol}) + + mockEVMKeeper.MockEVMFailCallOnce() + + res, err := k.QueryZRC20Data(ctx, sample.EthAddress()) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("should error if unpack fails for decimals", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc4ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + name, err := zrc4ABI.Methods["name"].Outputs.Pack("name") + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: name}) + + symbol, err := zrc4ABI.Methods["symbol"].Outputs.Pack("symbol") + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: symbol}) + + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: []byte{}}) + + res, err := k.QueryZRC20Data(ctx, sample.EthAddress()) + require.Error(t, err) + require.Empty(t, res) + }) + + t.Run("should return zrc20 data", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + + zrc4ABI, err := zrc20.ZRC20MetaData.GetAbi() + require.NoError(t, err) + name, err := zrc4ABI.Methods["name"].Outputs.Pack("name") + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: name}) + + symbol, err := zrc4ABI.Methods["symbol"].Outputs.Pack("symbol") + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: symbol}) + + decimals, err := zrc4ABI.Methods["decimals"].Outputs.Pack(uint8(8)) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: decimals}) + + res, err := k.QueryZRC20Data(ctx, sample.EthAddress()) + require.NoError(t, err) + require.Equal(t, uint8(8), res.Decimals) + require.Equal(t, "name", res.Name) + require.Equal(t, "symbol", res.Symbol) + }) +} diff --git a/x/fungible/keeper/gas_coin_and_pool.go b/x/fungible/keeper/gas_coin_and_pool.go index 6b06cd8cec..60cc436965 100644 --- a/x/fungible/keeper/gas_coin_and_pool.go +++ b/x/fungible/keeper/gas_coin_and_pool.go @@ -125,7 +125,6 @@ func (k Keeper) SetupChainGasCoinAndPool( err = routerABI.UnpackIntoInterface(&[]interface{}{AmountToken, AmountETH, Liquidity}, "addLiquidityETH", res.Ret) if err != nil { return ethcommon.Address{}, cosmoserrors.Wrapf(err, "failed to UnpackIntoInterface addLiquidityETH") - } ctx.EventManager().EmitEvent( sdk.NewEvent(sdk.EventTypeMessage, diff --git a/x/fungible/keeper/gas_coin_and_pool_test.go b/x/fungible/keeper/gas_coin_and_pool_test.go index 9935f11ee6..9ee6a9d17f 100644 --- a/x/fungible/keeper/gas_coin_and_pool_test.go +++ b/x/fungible/keeper/gas_coin_and_pool_test.go @@ -1,18 +1,23 @@ package keeper_test import ( + "errors" "math/big" "testing" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/ethereum/go-ethereum/common" evmkeeper "github.com/evmos/ethermint/x/evm/keeper" + evmtypes "github.com/evmos/ethermint/x/evm/types" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" + "github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/systemcontract.sol" uniswapv2router02 "github.com/zeta-chain/protocol-contracts/pkg/uniswap/v2-periphery/contracts/uniswapv2router02.sol" "github.com/zeta-chain/zetacore/cmd/zetacored/config" - testkeeper "github.com/zeta-chain/zetacore/testutil/keeper" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" fungiblekeeper "github.com/zeta-chain/zetacore/x/fungible/keeper" "github.com/zeta-chain/zetacore/x/fungible/types" ) @@ -134,7 +139,7 @@ func setupZRC20Pool( func TestKeeper_SetupChainGasCoinAndPool(t *testing.T) { t.Run("can setup a new chain gas coin", func(t *testing.T) { - k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) + k, ctx, sdkk, _ := keepertest.FungibleKeeper(t) _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) chainID := getValidChainID(t) @@ -149,4 +154,296 @@ func TestKeeper_SetupChainGasCoinAndPool(t *testing.T) { require.NoError(t, err) require.Equal(t, zrc20, found) }) + + t.Run("should error if system contracts not deployed", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if mint coins fails", func(t *testing.T) { + k, ctx, sdkk, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseBankMock: true, + }) + bankMock := keepertest.GetFungibleBankMock(t, k) + bankMock.On("MintCoins", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(errors.New("err")) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if set gas coin fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + + // deployZrc20 success + mockSuccessfulContractDeployment(ctx, t, k) + + // setGasCoin fail + mockEVMKeeper.MockEVMFailCallOnce() + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if deposit zrc20 fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + + // deployZrc20 success + mockSuccessfulContractDeployment(ctx, t, k) + + // setGasCoin success + mockEVMKeeper.MockEVMSuccessCallOnce() + + // depositZrc20 fails + mockEVMKeeper.MockEVMFailCallOnce() + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if set gas pool call fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + + // deployZrc20 success + mockSuccessfulContractDeployment(ctx, t, k) + + // setGasCoin success + // depositZrc20 success + mockEVMKeeper.MockEVMSuccessCallTimes(2) + + // set gas pool call fail + mockEVMKeeper.MockEVMFailCallOnce() + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if get uniswap router fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + + // deployZrc20 success + mockSuccessfulContractDeployment(ctx, t, k) + + // setGasCoin success + // depositZrc20 success + // set gas pool call success + mockEVMKeeper.MockEVMSuccessCallTimes(3) + + // get uniswap router fails + mockEVMKeeper.MockEVMFailCallOnce() + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if approve fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + + // deployZrc20 success + mockSuccessfulContractDeployment(ctx, t, k) + + // setGasCoin success + // depositZrc20 success + // set gas pool call success + mockEVMKeeper.MockEVMSuccessCallTimes(3) + + // get uniswap router success + sysABI, err := systemcontract.SystemContractMetaData.GetAbi() + require.NoError(t, err) + routerAddr, err := sysABI.Methods["uniswapv2Router02Address"].Outputs.Pack(sample.EthAddress()) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: routerAddr}) + + // get approve fails + mockEVMKeeper.MockEVMFailCallOnce() + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if add liquidity fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + + // deployZrc20 success + mockSuccessfulContractDeployment(ctx, t, k) + + // setGasCoin success + // depositZrc20 success + // set gas pool call success + mockEVMKeeper.MockEVMSuccessCallTimes(3) + + // get uniswap router success + sysABI, err := systemcontract.SystemContractMetaData.GetAbi() + require.NoError(t, err) + routerAddr, err := sysABI.Methods["uniswapv2Router02Address"].Outputs.Pack(sample.EthAddress()) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: routerAddr}) + + // get approve success + mockEVMKeeper.MockEVMSuccessCallOnce() + + // add liquidity fails + mockEVMKeeper.MockEVMFailCallOnce() + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) + + t.Run("should error if add liquidity fails to unpack", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseEVMMock: true, + }) + k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + deploySystemContractsWithMockEvmKeeper(t, ctx, k, mockEVMKeeper) + + // deployZrc20 success + mockSuccessfulContractDeployment(ctx, t, k) + + // setGasCoin success + // depositZrc20 success + // set gas pool call success + mockEVMKeeper.MockEVMSuccessCallTimes(3) + + // get uniswap router success + sysABI, err := systemcontract.SystemContractMetaData.GetAbi() + require.NoError(t, err) + routerAddr, err := sysABI.Methods["uniswapv2Router02Address"].Outputs.Pack(sample.EthAddress()) + require.NoError(t, err) + mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: routerAddr}) + + // get approve success + mockEVMKeeper.MockEVMSuccessCallOnce() + + // add liquidity success + mockEVMKeeper.MockEVMSuccessCallOnce() + + addr, err := k.SetupChainGasCoinAndPool( + ctx, + chainID, + "test", + "test", + 8, + nil, + ) + require.Error(t, err) + require.Empty(t, addr) + }) } diff --git a/x/fungible/keeper/gas_stability_pool_test.go b/x/fungible/keeper/gas_stability_pool_test.go index 1c9bbc7b12..d05e9aee19 100644 --- a/x/fungible/keeper/gas_stability_pool_test.go +++ b/x/fungible/keeper/gas_stability_pool_test.go @@ -34,6 +34,23 @@ func TestKeeper_EnsureGasStabilityPoolAccountCreated(t *testing.T) { } func TestKeeper_FundGasStabilityPool(t *testing.T) { + t.Run("should error if system contracts not deployed", func(t *testing.T) { + k, ctx, _, _ := testkeeper.FungibleKeeper(t) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + chainID := getValidChainID(t) + + balance, err := k.GetGasStabilityPoolBalance(ctx, chainID) + require.Error(t, err) + require.Nil(t, balance) + + err = k.FundGasStabilityPool(ctx, chainID, big.NewInt(100)) + require.Error(t, err) + + err = k.WithdrawFromGasStabilityPool(ctx, chainID, big.NewInt(50)) + require.Error(t, err) + }) + t.Run("can fund the gas stability pool and withdraw", func(t *testing.T) { k, ctx, sdkk, _ := testkeeper.FungibleKeeper(t) _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) diff --git a/x/fungible/keeper/grpc_query_code_hash_test.go b/x/fungible/keeper/grpc_query_code_hash_test.go index e2359dc530..5a31f5c736 100644 --- a/x/fungible/keeper/grpc_query_code_hash_test.go +++ b/x/fungible/keeper/grpc_query_code_hash_test.go @@ -11,6 +11,13 @@ import ( ) func TestKeeper_CodeHash(t *testing.T) { + t.Run("should error if req is nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + res, err := k.CodeHash(ctx, nil) + require.Error(t, err) + require.Nil(t, res) + }) + t.Run("should return code hash", func(t *testing.T) { k, ctx, sdkk, _ := keepertest.FungibleKeeper(t) k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) diff --git a/x/fungible/keeper/grpc_query_gas_stability_pool_test.go b/x/fungible/keeper/grpc_query_gas_stability_pool_test.go new file mode 100644 index 0000000000..7dfe91d530 --- /dev/null +++ b/x/fungible/keeper/grpc_query_gas_stability_pool_test.go @@ -0,0 +1,142 @@ +package keeper_test + +import ( + "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/x/fungible/types" +) + +func TestKeeper_GasStabilityPoolAddress(t *testing.T) { + t.Run("should error if req is nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + res, err := k.GasStabilityPoolAddress(ctx, nil) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return if req is not nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + res, err := k.GasStabilityPoolAddress(ctx, &types.QueryGetGasStabilityPoolAddress{}) + require.NoError(t, err) + require.Equal(t, &types.QueryGetGasStabilityPoolAddressResponse{ + CosmosAddress: types.GasStabilityPoolAddress().String(), + EvmAddress: types.GasStabilityPoolAddressEVM().String(), + }, res) + }) +} + +func TestKeeper_GasStabilityPoolBalance(t *testing.T) { + t.Run("should error if req is nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + res, err := k.GasStabilityPoolBalance(ctx, nil) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if system contracts not deployed", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + chainID := 5 + + res, err := k.GasStabilityPoolBalance(ctx, &types.QueryGetGasStabilityPoolBalance{ + ChainId: int64(chainID), + }) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return balance", func(t *testing.T) { + k, ctx, sdkk, _ := keepertest.FungibleKeeper(t) + chainID := 5 + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + setupGasCoin(t, ctx, k, sdkk.EvmKeeper, int64(chainID), "foobar", "foobar") + + res, err := k.GasStabilityPoolBalance(ctx, &types.QueryGetGasStabilityPoolBalance{ + ChainId: int64(chainID), + }) + require.NoError(t, err) + require.Equal(t, "0", res.Balance) + }) + +} + +func TestKeeper_GasStabilityPoolBalanceAll(t *testing.T) { + t.Run("should error if req is nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + res, err := k.GasStabilityPoolBalanceAll(ctx, nil) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return empty balances if no supported chains", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetFungibleObserverMock(t, k) + observerMock.On("GetSupportedChains", mock.Anything).Return([]*chains.Chain{}) + + res, err := k.GasStabilityPoolBalanceAll(ctx, &types.QueryAllGasStabilityPoolBalance{}) + require.NoError(t, err) + require.Empty(t, res.Balances) + }) + + t.Run("should error if chain is nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetFungibleObserverMock(t, k) + observerMock.On("GetSupportedChains", mock.Anything).Return([]*chains.Chain{nil}) + + res, err := k.GasStabilityPoolBalanceAll(ctx, &types.QueryAllGasStabilityPoolBalance{}) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if system contracts not deployed", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseObserverMock: true, + }) + observerMock := keepertest.GetFungibleObserverMock(t, k) + chainID := 5 + observerMock.On("GetSupportedChains", mock.Anything).Return([]*chains.Chain{ + { + ChainName: chains.ChainName(chainID), + ChainId: int64(chainID), + }, + }) + + res, err := k.GasStabilityPoolBalanceAll(ctx, &types.QueryAllGasStabilityPoolBalance{}) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return balances", func(t *testing.T) { + k, ctx, sdkk, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseObserverMock: true, + }) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + + observerMock := keepertest.GetFungibleObserverMock(t, k) + chainID := 5 + observerMock.On("GetSupportedChains", mock.Anything).Return([]*chains.Chain{ + { + ChainName: chains.ChainName(chainID), + ChainId: int64(chainID), + }, + }) + + deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) + setupGasCoin(t, ctx, k, sdkk.EvmKeeper, int64(chainID), "foobar", "foobar") + + res, err := k.GasStabilityPoolBalanceAll(ctx, &types.QueryAllGasStabilityPoolBalance{}) + require.NoError(t, err) + require.Len(t, res.Balances, 1) + require.Equal(t, int64(chainID), res.Balances[0].ChainId) + require.Equal(t, "0", res.Balances[0].Balance) + }) +} diff --git a/x/fungible/keeper/grpc_query_system_contract_test.go b/x/fungible/keeper/grpc_query_system_contract_test.go new file mode 100644 index 0000000000..849e2c87de --- /dev/null +++ b/x/fungible/keeper/grpc_query_system_contract_test.go @@ -0,0 +1,40 @@ +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" + "github.com/zeta-chain/zetacore/x/fungible/types" +) + +func TestKeeper_SystemContract(t *testing.T) { + t.Run("should error if req is nil", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + res, err := k.SystemContract(ctx, nil) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should error if system contract not found", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + res, err := k.SystemContract(ctx, &types.QueryGetSystemContractRequest{}) + require.Error(t, err) + require.Nil(t, res) + }) + + t.Run("should return system contract if found", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeper(t) + sc := types.SystemContract{ + SystemContract: sample.EthAddress().Hex(), + ConnectorZevm: sample.EthAddress().Hex(), + } + k.SetSystemContract(ctx, sc) + res, err := k.SystemContract(ctx, &types.QueryGetSystemContractRequest{}) + require.NoError(t, err) + require.Equal(t, &types.QueryGetSystemContractResponse{ + SystemContract: sc, + }, res) + }) +} diff --git a/x/fungible/keeper/msg_server_deploy_system_contract_test.go b/x/fungible/keeper/msg_server_deploy_system_contract_test.go index 168fe6ca65..06cb2d29cd 100644 --- a/x/fungible/keeper/msg_server_deploy_system_contract_test.go +++ b/x/fungible/keeper/msg_server_deploy_system_contract_test.go @@ -1,10 +1,12 @@ package keeper_test import ( - "errors" + "context" + "math/big" "testing" ethcommon "github.com/ethereum/go-ethereum/common" + evmtypes "github.com/evmos/ethermint/x/evm/types" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" keepertest "github.com/zeta-chain/zetacore/testutil/keeper" @@ -53,7 +55,7 @@ func TestMsgServer_DeploySystemContracts(t *testing.T) { require.ErrorIs(t, err, authoritytypes.ErrUnauthorized) }) - t.Run("should fail if contract deployment fails", func(t *testing.T) { + t.Run("should fail if uniswapv2factory contract deployment fails", func(t *testing.T) { k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ UseAuthorityMock: true, UseEVMMock: true, @@ -65,15 +67,129 @@ func TestMsgServer_DeploySystemContracts(t *testing.T) { authorityMock := keepertest.GetFungibleAuthorityMock(t, k) keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) - mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) - mockEVMKeeper.On( - "EstimateGas", - mock.Anything, - mock.Anything, - ).Return(nil, errors.New("failed to estimate gas")) + // mock failed uniswapv2factory deployment + mockFailedContractDeployment(ctx, t, k) _, err := msgServer.DeploySystemContracts(ctx, types.NewMsgDeploySystemContracts(admin)) require.Error(t, err) require.Contains(t, err.Error(), "failed to deploy") }) + + t.Run("should fail if wzeta contract deployment fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseAuthorityMock: true, + UseEVMMock: true, + }) + msgServer := keeper.NewMsgServerImpl(*k) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + admin := sample.AccAddress() + + authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) + + // mock successful uniswapv2factory deployment + mockSuccessfulContractDeployment(ctx, t, k) + // mock failed wzeta deployment deployment + mockFailedContractDeployment(ctx, t, k) + + _, err := msgServer.DeploySystemContracts(ctx, types.NewMsgDeploySystemContracts(admin)) + require.Error(t, err) + require.Contains(t, err.Error(), "failed to deploy") + }) + + t.Run("should fail if uniswapv2router deployment fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseAuthorityMock: true, + UseEVMMock: true, + }) + msgServer := keeper.NewMsgServerImpl(*k) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + admin := sample.AccAddress() + + authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) + + // mock successful uniswapv2factory and wzeta deployments + mockSuccessfulContractDeployment(ctx, t, k) + mockSuccessfulContractDeployment(ctx, t, k) + // mock failed uniswapv2router deployment + mockFailedContractDeployment(ctx, t, k) + + _, err := msgServer.DeploySystemContracts(ctx, types.NewMsgDeploySystemContracts(admin)) + require.Error(t, err) + require.Contains(t, err.Error(), "failed to deploy") + }) + + t.Run("should fail if connectorzevm deployment fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseAuthorityMock: true, + UseEVMMock: true, + }) + msgServer := keeper.NewMsgServerImpl(*k) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + admin := sample.AccAddress() + + authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) + + // mock successful uniswapv2factory, wzeta and uniswapv2router deployments + mockSuccessfulContractDeployment(ctx, t, k) + mockSuccessfulContractDeployment(ctx, t, k) + mockSuccessfulContractDeployment(ctx, t, k) + // mock failed connectorzevm deployment + mockFailedContractDeployment(ctx, t, k) + + _, err := msgServer.DeploySystemContracts(ctx, types.NewMsgDeploySystemContracts(admin)) + require.Error(t, err) + require.Contains(t, err.Error(), "failed to deploy") + }) + + t.Run("should fail if system contract deployment fails", func(t *testing.T) { + k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ + UseAuthorityMock: true, + UseEVMMock: true, + }) + msgServer := keeper.NewMsgServerImpl(*k) + _ = k.GetAuthKeeper().GetModuleAccount(ctx, types.ModuleName) + admin := sample.AccAddress() + + authorityMock := keepertest.GetFungibleAuthorityMock(t, k) + keepertest.MockIsAuthorized(&authorityMock.Mock, admin, authoritytypes.PolicyType_groupOperational, true) + + // mock successful uniswapv2factory, wzeta, uniswapv2router and connectorzevm deployments + mockSuccessfulContractDeployment(ctx, t, k) + mockSuccessfulContractDeployment(ctx, t, k) + mockSuccessfulContractDeployment(ctx, t, k) + mockSuccessfulContractDeployment(ctx, t, k) + // mock failed system contract deployment + mockFailedContractDeployment(ctx, t, k) + + _, err := msgServer.DeploySystemContracts(ctx, types.NewMsgDeploySystemContracts(admin)) + require.Error(t, err) + require.Contains(t, err.Error(), "failed to deploy") + }) +} + +func mockSuccessfulContractDeployment(ctx context.Context, t *testing.T, k *keeper.Keeper) { + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + mockEVMKeeper.On( + "EstimateGas", + mock.Anything, + mock.Anything, + ).Return(&evmtypes.EstimateGasResponse{Gas: 5}, nil) + mockEVMKeeper.MockEVMSuccessCallOnce() +} + +func mockFailedContractDeployment(ctx context.Context, t *testing.T, k *keeper.Keeper) { + mockEVMKeeper := keepertest.GetFungibleEVMMock(t, k) + mockEVMKeeper.On("WithChainID", mock.Anything).Maybe().Return(ctx) + mockEVMKeeper.On("ChainID").Maybe().Return(big.NewInt(1)) + mockEVMKeeper.On( + "EstimateGas", + mock.Anything, + mock.Anything, + ).Return(&evmtypes.EstimateGasResponse{Gas: 5}, nil) + mockEVMKeeper.MockEVMFailCallOnce() } diff --git a/x/fungible/keeper/msg_server_update_system_contract_test.go b/x/fungible/keeper/msg_server_update_system_contract_test.go index e64c5ea640..2d1cd30c56 100644 --- a/x/fungible/keeper/msg_server_update_system_contract_test.go +++ b/x/fungible/keeper/msg_server_update_system_contract_test.go @@ -53,6 +53,11 @@ func TestKeeper_UpdateSystemContract(t *testing.T) { wzeta, factory, router, _, oldSystemContract := deploySystemContracts(t, ctx, k, sdkk.EvmKeeper) gas1 := setupGasCoin(t, ctx, k, sdkk.EvmKeeper, chainID1, "foo", "foo") gas2 := setupGasCoin(t, ctx, k, sdkk.EvmKeeper, chainID2, "bar", "bar") + // this one should be skipped and not impact update + fc := types.ForeignCoins{ + Zrc20ContractAddress: "0x", + } + k.SetForeignCoins(ctx, fc) // deploy a new system contracts newSystemContract, err := k.DeployContract(ctx, systemcontract.SystemContractMetaData, wzeta, factory, router) diff --git a/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go b/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go index e832f69e24..bef609a10e 100644 --- a/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go +++ b/x/fungible/keeper/msg_server_update_zrc20_withdraw_fee_test.go @@ -227,7 +227,7 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { mockEVMKeeper.AssertExpectations(t) }) - t.Run("should fail if contract call for setting new protocol fee fails", func(t *testing.T) { + t.Run("should fail if query gas limit fails", func(t *testing.T) { k, ctx, _, _ := keepertest.FungibleKeeperWithMocks(t, keepertest.FungibleMockOptions{ UseEVMMock: true, UseAuthorityMock: true, @@ -259,11 +259,8 @@ func TestKeeper_UpdateZRC20WithdrawFee(t *testing.T) { require.NoError(t, err) mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: protocolFlatFee}) - gasLimit, err := zrc20ABI.Methods["GAS_LIMIT"].Outputs.Pack(big.NewInt(42)) + _, err = zrc20ABI.Methods["GAS_LIMIT"].Outputs.Pack(big.NewInt(42)) require.NoError(t, err) - mockEVMKeeper.MockEVMSuccessCallOnceWithReturn(&evmtypes.MsgEthereumTxResponse{Ret: gasLimit}) - - // this is the update call (commit == true) mockEVMKeeper.MockEVMFailCallOnce() _, err = msgServer.UpdateZRC20WithdrawFee(ctx, types.NewMsgUpdateZRC20WithdrawFee( diff --git a/x/fungible/types/zrc20_test.go b/x/fungible/types/zrc20_test.go new file mode 100644 index 0000000000..fcb248753f --- /dev/null +++ b/x/fungible/types/zrc20_test.go @@ -0,0 +1,15 @@ +package types_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/x/fungible/types" +) + +func TestNewZRC20Data(t *testing.T) { + zrc20 := types.NewZRC20Data("name", "symbol", 8) + require.Equal(t, "name", zrc20.Name) + require.Equal(t, "symbol", zrc20.Symbol) + require.Equal(t, uint8(8), zrc20.Decimals) +} diff --git a/x/observer/keeper/hooks_test.go b/x/observer/keeper/hooks_test.go index ec782663ee..0727b17c71 100644 --- a/x/observer/keeper/hooks_test.go +++ b/x/observer/keeper/hooks_test.go @@ -48,16 +48,16 @@ func TestKeeper_AfterValidatorRemoved(t *testing.T) { } func TestKeeper_AfterValidatorBeginUnbonding(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.DelegatorShares = sdk.NewDec(100) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) - k.GetStakingKeeper().SetDelegation(ctx, stakingtypes.Delegation{ + sdkk.StakingKeeper.SetDelegation(ctx, stakingtypes.Delegation{ DelegatorAddress: accAddressOfValidator.String(), ValidatorAddress: validator.GetOperator().String(), Shares: sdk.NewDec(10), @@ -78,16 +78,16 @@ func TestKeeper_AfterValidatorBeginUnbonding(t *testing.T) { func TestKeeper_AfterDelegationModified(t *testing.T) { t.Run("should not clean observer if not self delegation", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.DelegatorShares = sdk.NewDec(100) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) - k.GetStakingKeeper().SetDelegation(ctx, stakingtypes.Delegation{ + sdkk.StakingKeeper.SetDelegation(ctx, stakingtypes.Delegation{ DelegatorAddress: accAddressOfValidator.String(), ValidatorAddress: validator.GetOperator().String(), Shares: sdk.NewDec(10), @@ -108,16 +108,16 @@ func TestKeeper_AfterDelegationModified(t *testing.T) { }) t.Run("should clean observer if self delegation", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.DelegatorShares = sdk.NewDec(100) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) - k.GetStakingKeeper().SetDelegation(ctx, stakingtypes.Delegation{ + sdkk.StakingKeeper.SetDelegation(ctx, stakingtypes.Delegation{ DelegatorAddress: accAddressOfValidator.String(), ValidatorAddress: validator.GetOperator().String(), Shares: sdk.NewDec(10), @@ -150,12 +150,12 @@ func TestKeeper_BeforeValidatorSlashed(t *testing.T) { }) t.Run("should not error if observer set not found", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.DelegatorShares = sdk.NewDec(100) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) hooks := k.Hooks() err := hooks.BeforeValidatorSlashed(ctx, validator.GetOperator(), sdk.NewDec(1)) @@ -163,13 +163,13 @@ func TestKeeper_BeforeValidatorSlashed(t *testing.T) { }) t.Run("should remove from observer set", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.DelegatorShares = sdk.NewDec(100) validator.Tokens = sdk.NewInt(100) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) @@ -187,13 +187,13 @@ func TestKeeper_BeforeValidatorSlashed(t *testing.T) { }) t.Run("should not remove from observer set", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.DelegatorShares = sdk.NewDec(100) validator.Tokens = sdk.NewInt(1000000000000000000) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) diff --git a/x/observer/keeper/utils_test.go b/x/observer/keeper/utils_test.go index 4aedd8ad13..4551e1ca24 100644 --- a/x/observer/keeper/utils_test.go +++ b/x/observer/keeper/utils_test.go @@ -44,13 +44,13 @@ func getValidEthChainIDWithIndex(t *testing.T, index int) int64 { func TestKeeper_IsAuthorized(t *testing.T) { t.Run("authorized observer", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) // Set validator in the store validator := sample.Validator(t, r) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) consAddress, err := validator.GetConsAddr() require.NoError(t, err) k.GetSlashingKeeper().SetValidatorSigningInfo(ctx, consAddress, slashingtypes.ValidatorSigningInfo{ @@ -71,13 +71,13 @@ func TestKeeper_IsAuthorized(t *testing.T) { }) t.Run("not authorized for tombstoned observer", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) // Set validator in the store validator := sample.Validator(t, r) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) consAddress, err := validator.GetConsAddr() require.NoError(t, err) k.GetSlashingKeeper().SetValidatorSigningInfo(ctx, consAddress, slashingtypes.ValidatorSigningInfo{ @@ -144,11 +144,11 @@ func TestKeeper_CheckObserverSelfDelegation(t *testing.T) { }) t.Run("should error if delegation not found", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) @@ -157,16 +157,16 @@ func TestKeeper_CheckObserverSelfDelegation(t *testing.T) { }) t.Run("should remove from observer list if tokens less than min del", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.DelegatorShares = sdk.NewDec(100) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) - k.GetStakingKeeper().SetDelegation(ctx, stakingtypes.Delegation{ + sdkk.StakingKeeper.SetDelegation(ctx, stakingtypes.Delegation{ DelegatorAddress: accAddressOfValidator.String(), ValidatorAddress: validator.GetOperator().String(), Shares: sdk.NewDec(10), @@ -184,20 +184,20 @@ func TestKeeper_CheckObserverSelfDelegation(t *testing.T) { }) t.Run("should not remove from observer list if tokens gte than min del", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.DelegatorShares = sdk.NewDec(1) validator.Tokens = sdk.NewInt(1) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) minDelegation, err := types.GetMinObserverDelegationDec() require.NoError(t, err) - k.GetStakingKeeper().SetDelegation(ctx, stakingtypes.Delegation{ + sdkk.StakingKeeper.SetDelegation(ctx, stakingtypes.Delegation{ DelegatorAddress: accAddressOfValidator.String(), ValidatorAddress: validator.GetOperator().String(), Shares: minDelegation, @@ -235,11 +235,11 @@ func TestKeeper_IsOpeartorTombstoned(t *testing.T) { }) t.Run("should not error if validator found", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) @@ -266,11 +266,11 @@ func TestKeeper_IsValidator(t *testing.T) { }) t.Run("should err if validator not bonded", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) @@ -279,13 +279,13 @@ func TestKeeper_IsValidator(t *testing.T) { }) t.Run("should err if validator jailed", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.Status = stakingtypes.Bonded validator.Jailed = true - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) @@ -294,13 +294,13 @@ func TestKeeper_IsValidator(t *testing.T) { }) t.Run("should not err if validator not jailed and bonded", func(t *testing.T) { - k, ctx, _, _ := keepertest.ObserverKeeper(t) + k, ctx, sdkk, _ := keepertest.ObserverKeeper(t) r := rand.New(rand.NewSource(9)) validator := sample.Validator(t, r) validator.Status = stakingtypes.Bonded validator.Jailed = false - k.GetStakingKeeper().SetValidator(ctx, validator) + sdkk.StakingKeeper.SetValidator(ctx, validator) accAddressOfValidator, err := types.GetAccAddressFromOperatorAddress(validator.OperatorAddress) require.NoError(t, err) diff --git a/x/observer/types/expected_keepers.go b/x/observer/types/expected_keepers.go index 5f402c2689..ba1c9ab9c2 100644 --- a/x/observer/types/expected_keepers.go +++ b/x/observer/types/expected_keepers.go @@ -11,7 +11,6 @@ type StakingKeeper interface { GetValidator(ctx sdk.Context, addr sdk.ValAddress) (validator stakingtypes.Validator, found bool) GetDelegation(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress) (delegation stakingtypes.Delegation, found bool) SetValidator(ctx sdk.Context, validator stakingtypes.Validator) - SetDelegation(ctx sdk.Context, delegation stakingtypes.Delegation) } type SlashingKeeper interface { From bc3a88cb5e1f6125c4d64eb82136345520b3f7c6 Mon Sep 17 00:00:00 2001 From: kevinssgh <79858682+kevinssgh@users.noreply.github.com> Date: Fri, 5 Apr 2024 13:23:17 -0400 Subject: [PATCH 2/3] test: unit testing zetabridge package in zetaclient (#1941) * initial commit * setup query testing * add Test function signatures * added some test cases * updates * added test case * added some more tests * update more unit tests * update more unit tests * fix gosec issue * fix some package errors * Added mock sdk Client and some unit tests for transactions * Added stub for mock sdk client and some unit tests for transactions * added unit test for updateCoreContext * ran make generate * unit tested broadcast.go * fix lint errors * address comments * increase test coverage * moved sdk client flag to zetabridge struct --------- Co-authored-by: Lucas Bertrand --- changelog.md | 1 + go.mod | 55 +- go.sum | 109 +-- zetaclient/config/types.go | 1 + zetaclient/testutils/stub/keyring.go | 111 +++ zetaclient/testutils/stub/sdk_client.go | 68 ++ zetaclient/zetabridge/broadcast.go | 45 +- zetaclient/zetabridge/broadcast_test.go | 112 ++- zetaclient/zetabridge/query_test.go | 883 +++++++++++++++++++++++ zetaclient/zetabridge/tx.go | 14 +- zetaclient/zetabridge/tx_test.go | 389 ++++++++++ zetaclient/zetabridge/zetacore_bridge.go | 45 +- 12 files changed, 1717 insertions(+), 116 deletions(-) create mode 100644 zetaclient/testutils/stub/keyring.go create mode 100644 zetaclient/testutils/stub/sdk_client.go create mode 100644 zetaclient/zetabridge/query_test.go diff --git a/changelog.md b/changelog.md index f847d51c33..73e8e04e28 100644 --- a/changelog.md +++ b/changelog.md @@ -56,6 +56,7 @@ * [1961](https://github.com/zeta-chain/node/pull/1961) - improve observer module coverage * [1967](https://github.com/zeta-chain/node/pull/1967) - improve crosschain module coverage * [1955](https://github.com/zeta-chain/node/pull/1955) - improve emissions module coverage +* [1941](https://github.com/zeta-chain/node/pull/1941) - add unit tests for zetabridge package * [1985](https://github.com/zeta-chain/node/pull/1985) - improve fungible module coverage ### Fixes diff --git a/go.mod b/go.mod index 9560f12c9e..245536d185 100644 --- a/go.mod +++ b/go.mod @@ -21,8 +21,8 @@ require ( github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/tendermint v0.34.28 github.com/tendermint/tm-db v0.6.7 - google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e // indirect - google.golang.org/grpc v1.56.3 + google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 // indirect + google.golang.org/grpc v1.60.1 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c ) @@ -45,7 +45,7 @@ require ( github.com/zeta-chain/go-tss v0.1.1-0.20240208222330-f3be0d4a0d98 github.com/zeta-chain/keystone/keys v0.0.0-20231105174229-903bc9405da2 github.com/zeta-chain/protocol-contracts v1.0.2-athens3.0.20230816152528-db7d2bf9144b - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc + google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f gopkg.in/yaml.v2 v2.4.0 ) @@ -61,11 +61,13 @@ require ( github.com/binance-chain/tss-lib v0.0.0-20201118045712-70b2cb4bf916 github.com/nanmu42/etherscan-api v1.10.0 github.com/onrik/ethrpc v1.2.0 + go.nhat.io/grpcmock v0.25.0 ) require ( github.com/DataDog/zstd v1.5.2 // indirect github.com/agl/ed25519 v0.0.0-20200225211852-fd4d107ace12 // indirect + github.com/bool64/shared v0.1.5 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cockroachdb/errors v1.9.1 // indirect @@ -82,9 +84,11 @@ require ( github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/golang/glog v1.1.0 // indirect + github.com/golang/glog v1.1.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/iancoleman/orderedmap v0.3.0 // indirect github.com/ipfs/boxo v0.10.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.0 // indirect @@ -99,28 +103,35 @@ require ( github.com/quic-go/webtransport-go v0.5.3 // indirect github.com/rjeczalik/notify v0.9.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/sergi/go-diff v1.3.1 // indirect + github.com/swaggest/assertjson v1.9.0 // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/thales-e-security/pool v0.0.2 // indirect github.com/tidwall/gjson v1.14.4 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/sjson v1.2.5 // indirect + github.com/yudai/gojsondiff v1.0.0 // indirect + github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect go.etcd.io/bbolt v1.3.7 // indirect + go.nhat.io/matcher/v2 v2.0.0 // indirect + go.nhat.io/wait v0.1.0 // indirect go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect go.opentelemetry.io/otel/trace v1.16.0 // indirect go.uber.org/dig v1.17.0 // indirect go.uber.org/fx v1.19.2 // indirect + golang.org/x/time v0.5.0 // indirect gonum.org/v1/gonum v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect ) require ( - cloud.google.com/go v0.110.0 // indirect - cloud.google.com/go/compute v1.19.1 // indirect + cloud.google.com/go v0.110.10 // indirect + cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.13.0 // indirect - cloud.google.com/go/storage v1.28.1 // indirect + cloud.google.com/go/iam v1.1.5 // indirect + cloud.google.com/go/storage v1.35.1 // indirect filippo.io/edwards25519 v1.0.0-rc.1 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/ChainSafe/go-schnorrkel v1.0.0 // indirect @@ -183,15 +194,15 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/google/orderedcode v0.0.1 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect - github.com/googleapis/gax-go/v2 v2.7.1 // indirect + github.com/google/uuid v1.4.0 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/websocket v1.5.0 - github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect @@ -283,11 +294,11 @@ require ( github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/spf13/afero v1.9.3 // indirect + github.com/spf13/afero v1.11.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/viper v1.15.0 github.com/status-im/keycard-go v0.2.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.1 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/tendermint/btcd v0.1.1 // indirect github.com/tendermint/go-amino v0.16.0 // indirect @@ -307,17 +318,17 @@ require ( golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.17.0 - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sync v0.2.0 + golang.org/x/net v0.19.0 + golang.org/x/oauth2 v0.15.0 // indirect + golang.org/x/sync v0.5.0 golang.org/x/sys v0.15.0 // indirect golang.org/x/term v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.9.1 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.114.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.30.0 + google.golang.org/api v0.152.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.31.0 gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 96e3c53ae9..256540ef43 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,8 @@ cloud.google.com/go v0.102.1/go.mod h1:XZ77E9qnTEnrgEOvr4xzfdX5TRo7fB4T2F4O6+34h cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRYtA= cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= -cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys= -cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.10 h1:LXy9GEO+timppncPIAZoOj3l58LIU9k+kn48AN7IO3Y= +cloud.google.com/go v0.110.10/go.mod h1:v1OoFqYxiBkUrruItNM3eT4lLByNjxmJSV/xDKJNnic= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accesscontextmanager v1.3.0/go.mod h1:TgCBehyr5gNMz7ZaH9xubp+CE8dkrszb4oK9CWyvD4o= @@ -134,8 +134,8 @@ cloud.google.com/go/compute v1.12.1/go.mod h1:e8yNOBcBONZU1vJKCvCoDw/4JQsA0dpM4x cloud.google.com/go/compute v1.13.0/go.mod h1:5aPTS0cUNMIc1CE546K+Th6weJUNQErARyZtRXDJ8GE= cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.15.1/go.mod h1:bjjoF/NtFUrkD/urWfdHaKuOPDR5nWIs63rR+SXhcpA= -cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= -cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZEXYonfTBHHFPO/4UU= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= @@ -226,8 +226,8 @@ cloud.google.com/go/iam v0.5.0/go.mod h1:wPU9Vt0P4UmCux7mqtRu6jcpPAb74cP1fh50J3Q cloud.google.com/go/iam v0.6.0/go.mod h1:+1AH33ueBne5MzYccyMHtEKqLE4/kJOibtffMHDMFMc= cloud.google.com/go/iam v0.7.0/go.mod h1:H5Br8wRaDGNc8XP3keLc4unfUUZeyH3Sfl9XpQEYOeg= cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/iam v0.13.0 h1:+CmB+K0J/33d0zSQ9SlFWUeCCEn5XJA0ZMZ3pHE9u8k= -cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= cloud.google.com/go/iap v1.4.0/go.mod h1:RGFwRJdihTINIe4wZ2iCP0zF/qu18ZwyKxrhMhygBEc= cloud.google.com/go/iap v1.5.0/go.mod h1:UH/CGgKd4KyohZL5Pt0jSKE4m3FR51qg6FKQ/z/Ix9A= cloud.google.com/go/ids v1.1.0/go.mod h1:WIuwCaYVOzHIj2OhN9HAwvW+DBdmUAdcWlFxRl+KubM= @@ -246,7 +246,6 @@ cloud.google.com/go/lifesciences v0.6.0/go.mod h1:ddj6tSX/7BOnhxCSd3ZcETvtNr8NZ6 cloud.google.com/go/logging v1.6.1/go.mod h1:5ZO0mHHbvm8gEmeEUHrmDlTDSu5imF6MUP9OfilNXBw= cloud.google.com/go/longrunning v0.1.1/go.mod h1:UUFxuDWkv22EuY93jjmDMFT5GPQKeFVJBIF6QlTqdsE= cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/managedidentities v1.3.0/go.mod h1:UzlW3cBOiPrzucO5qWkNkh0w33KFtBJU281hacNvsdE= cloud.google.com/go/managedidentities v1.4.0/go.mod h1:NWSBYbEMgqmbZsLIyKvxrYbtqOsxY1ZrGM+9RgDqInM= cloud.google.com/go/maps v0.1.0/go.mod h1:BQM97WGyfw9FWEmQMpZ5T6cpovXXSd1cGmFma94eubI= @@ -371,8 +370,8 @@ cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3f cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= cloud.google.com/go/storage v1.23.0/go.mod h1:vOEEDNFnciUMhBeT6hsJIn3ieU5cFRmzeLgDvXzfIXc= cloud.google.com/go/storage v1.27.0/go.mod h1:x9DOL8TK/ygDUMieqwfhdpQryTeEkhGKMi80i/iqR2s= -cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI= -cloud.google.com/go/storage v1.28.1/go.mod h1:Qnisd4CqDdo6BGs2AD5LLnEsmSQ80wQ5ogcBBKhU86Y= +cloud.google.com/go/storage v1.35.1 h1:B59ahL//eDfx2IIKFBeT5Atm9wnNmj3+8xG/W4WB//w= +cloud.google.com/go/storage v1.35.1/go.mod h1:M6M/3V/D3KpzMTJyPOR/HU6n2Si5QdaXYEsng2xgOs8= cloud.google.com/go/storagetransfer v1.5.0/go.mod h1:dxNzUopWy7RQevYFHewchb29POFv3/AaBgnhqzqiK0w= cloud.google.com/go/storagetransfer v1.6.0/go.mod h1:y77xm4CQV/ZhFZH75PLEXY0ROiS7Gh6pSKrM8dJyg6I= cloud.google.com/go/talent v1.1.0/go.mod h1:Vl4pt9jiHKvOgF9KoZo6Kob9oV4lwd/ZD5Cto54zDRw= @@ -730,6 +729,9 @@ github.com/bombsimon/wsl/v2 v2.2.0/go.mod h1:Azh8c3XGEJl9LyX0/sFC+CKMc7Ssgua0g+6 github.com/bombsimon/wsl/v3 v3.0.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bombsimon/wsl/v3 v3.1.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/bool64/dev v0.2.29 h1:x+syGyh+0eWtOzQ1ItvLzOGIWyNWnyjXpHIcpF2HvL4= +github.com/bool64/shared v0.1.5 h1:fp3eUhBsrSjNCQPcSdQqZxxh9bBwrYiZ+zOKFkM0/2E= +github.com/bool64/shared v0.1.5/go.mod h1:081yz68YC9jeFB3+Bbmno2RFWvGKv1lPKkMP6MHJlPs= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= github.com/breml/bidichk v0.2.3/go.mod h1:8u2C6DnAy0g2cEq+k/A2+tr9O1s+vHGxWn0LTc70T2A= github.com/breml/errchkjson v0.3.0/go.mod h1:9Cogkyv9gcT8HREpzi3TiqBxCqDzo8awa92zSDFcofU= @@ -1448,8 +1450,8 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGw github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -1545,8 +1547,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.0.0-20191010200024-a3d713f9b7f8/go.mod h1:KyKXa9ciM8+lgMXwOVsXi7UxGrsf9mM61Mzs+xKUrKE= github.com/google/go-containerregistry v0.1.2/go.mod h1:GPivBPgdAyd2SU+vf6EpsgOtWDuPqjW0hJZt4rNdTZ4= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= @@ -1595,6 +1598,8 @@ github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9S github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= @@ -1603,15 +1608,16 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= github.com/google/wire v0.4.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg= -github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k= -github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= @@ -1625,8 +1631,8 @@ github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK github.com/googleapis/gax-go/v2 v2.5.1/go.mod h1:h6B0KMMFNtI2ddbGJn3T3ZbwkeT6yqEF02fYlzkUCyo= github.com/googleapis/gax-go/v2 v2.6.0/go.mod h1:1mjbznJAPHFpesgE5ucqfYEscaz5kMdcIDwU/6+DDoY= github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/googleapis/gax-go/v2 v2.7.1 h1:gF4c0zjUP2H/s/hEGyLA3I0fA2ZWjzYiONAD6cvPr8A= -github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= @@ -1683,8 +1689,9 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.0/go.mod h1:mJzapYve32yjrKlk9GbyCZHuPgZsrbyIbyKhSzOpg6s= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= +github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= @@ -1804,6 +1811,8 @@ github.com/huin/goupnp v1.2.0/go.mod h1:gnGPsThkYa7bFi/KWmEysQRf48l2dvR5bxr2OFck github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= github.com/hydrogen18/memlistener v0.0.0-20141126152155-54553eb933fb/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE= +github.com/iancoleman/orderedmap v0.3.0 h1:5cbR2grmZR/DiVt+VJopEhtVs9YGInGIxAoMJn+Ichc= +github.com/iancoleman/orderedmap v0.3.0/go.mod h1:XuLcCUkdL5owUCQeF2Ue9uuw1EptkJDkXXS7VoV7XGE= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -2697,6 +2706,8 @@ github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfP github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= +github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= github.com/serialx/hashring v0.0.0-20190422032157-8b2912629002/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc= @@ -2771,8 +2782,8 @@ github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY52 github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= -github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= -github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= @@ -2827,8 +2838,9 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.1 h1:4VhoImhV/Bm0ToFkXFi8hXNXwpDRZ/ynw3amt82mzq0= +github.com/stretchr/objx v0.5.1/go.mod h1:/iHQpkQwBD6DLUmQ4pE+s1TXdob1mORJ4/UFdrifcy0= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v0.0.0-20170130113145-4d4bfba8f1d1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -2854,6 +2866,8 @@ github.com/subosito/gotenv v1.4.0/go.mod h1:mZd6rFysKEcUhUHXJk0C/08wAgyDBFuwEYL7 github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/swaggest/assertjson v1.9.0 h1:dKu0BfJkIxv/xe//mkCrK5yZbs79jL7OVf9Ija7o2xQ= +github.com/swaggest/assertjson v1.9.0/go.mod h1:b+ZKX2VRiUjxfUIal0HDN85W0nHPAYUbYH5WkkSsFsU= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -3020,8 +3034,11 @@ github.com/yagipy/maintidx v1.0.0/go.mod h1:0qNf/I/CCZXSMhsRsrEPDZ+DkekpKLXAJfsT github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI= github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= github.com/yeya24/promlinter v0.2.0/go.mod h1:u54lkmBOZrpEbQQ6gox2zWKKLKu2SGe+2KOiextY+IA= +github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= +github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3IfnEUduWvb9is428/nNb5L3U01M= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcmawg5bI= github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZkTdatxwunjIkc= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -3079,6 +3096,13 @@ go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVd go.etcd.io/gofail v0.1.0/go.mod h1:VZBCXYGZhHAinaBiiqYvuDynvahNsAyLFwB3kEHKz1M= go.mozilla.org/mozlog v0.0.0-20170222151521-4bb13139d403/go.mod h1:jHoPAGnDrCy6kaI2tAze5Prf0Nr0w/oNkROt2lw3n3o= go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.nhat.io/aferomock v0.4.0 h1:gs3nJzIqAezglUuaPfautAmZwulwRWLcfSSzdK4YCC0= +go.nhat.io/grpcmock v0.25.0 h1:zk03vvA60w7UrnurZbqL4wxnjmJz1Kuyb7ig2MF+n4c= +go.nhat.io/grpcmock v0.25.0/go.mod h1:5U694ASEFBkiZP7aPuz9kbbb/jphVlfpbOnocyht/rE= +go.nhat.io/matcher/v2 v2.0.0 h1:W+rbHi0hKuZHtOQH4U5g+KwyKyfVioIxrxjoGRcUETE= +go.nhat.io/matcher/v2 v2.0.0/go.mod h1:cL5oYp0M9A4L8jEGqjmUfy+k7AXVDddoVt6aYIL1r5g= +go.nhat.io/wait v0.1.0 h1:aQ4YDzaOgFbypiJ9c/eAfOIB1G25VOv7Gd2QS8uz1gw= +go.nhat.io/wait v0.1.0/go.mod h1:+ijMghc9/9zXi+HDcs49HNReprvXOZha2Q3jTOtqJrE= go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= go.opencensus.io v0.19.1/go.mod h1:gug0GbSHa8Pafr0d2urOSgoXHZ6x/RUlaiT0d9pqb4A= @@ -3175,6 +3199,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= @@ -3408,8 +3433,8 @@ golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180724155351-3d292e4d0cdc/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -3444,8 +3469,8 @@ golang.org/x/oauth2 v0.0.0-20221006150949-b44042a4b9c1/go.mod h1:h4gKUeWbJ4rQPri golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/oauth2 v0.1.0/go.mod h1:G9FE4dLTsbXUu90h/Pf85g4w1D+SSAgR+q46nJZ8M4A= golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -3465,8 +3490,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= -golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -3696,8 +3721,9 @@ golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= +golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -3926,8 +3952,8 @@ google.golang.org/api v0.99.0/go.mod h1:1YOf74vkVndF7pG6hIHuINsM7eWwpVTAfNMNiL91 google.golang.org/api v0.100.0/go.mod h1:ZE3Z2+ZOr87Rx7dqFsdRQkRBk36kDtp/h+QpHbB7a70= google.golang.org/api v0.102.0/go.mod h1:3VFl6/fzoA+qNuS1N1/VfXY4LjoXN/wzeIp7TweWwGo= google.golang.org/api v0.103.0/go.mod h1:hGtW6nK1AC+d9si/UBhw8Xli+QMOf6xyNAyJw4qU9w0= -google.golang.org/api v0.114.0 h1:1xQPji6cO2E2vLiI+C/XiFAnsn1WV3mjaEwGLhi3grE= -google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.152.0 h1:t0r1vPnfMc260S2Ci+en7kfCZaLOPs5KI0sVV/6jZrY= +google.golang.org/api v0.152.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -3937,8 +3963,9 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180518175338-11a468237815/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -4084,12 +4111,12 @@ google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZV google.golang.org/genproto v0.0.0-20221201164419-0e50fba7f41c/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= google.golang.org/genproto v0.0.0-20221202195650-67e5cbc046fd/go.mod h1:cTsE614GARnxrLsqKREzmNYJACSWWpAWdNMwnD7c2BE= google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3 h1:1hfbdAfFbkmpg41000wDVqr7jUpK/Yo+LPnIxxGzmkg= +google.golang.org/genproto v0.0.0-20231211222908-989df2bf70f3/go.mod h1:5RBcpGRxr25RbDzY5w+dmaqpSEvl8Gwl1x2CICf60ic= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f h1:2yNACc1O40tTnrsbk9Cv6oxiW8pxI/pXj0wRtdlYmgY= +google.golang.org/genproto/googleapis/api v0.0.0-20231120223509-83a465c0220f/go.mod h1:Uy9bTZJqmfrw2rIBxgGLnamc78euZULUBrLZ9XTITKI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -4144,8 +4171,8 @@ google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCD google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww= google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= -google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= -google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -4164,8 +4191,8 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/zetaclient/config/types.go b/zetaclient/config/types.go index ea861d46bb..b53bcc17dd 100644 --- a/zetaclient/config/types.go +++ b/zetaclient/config/types.go @@ -17,6 +17,7 @@ const ( KeyringBackendFile KeyringBackend = "file" ) +// ClientConfiguration is a subset of zetaclient config that is used by zetabridge type ClientConfiguration struct { ChainHost string `json:"chain_host" mapstructure:"chain_host"` ChainRPC string `json:"chain_rpc" mapstructure:"chain_rpc"` diff --git a/zetaclient/testutils/stub/keyring.go b/zetaclient/testutils/stub/keyring.go new file mode 100644 index 0000000000..819c2a6eed --- /dev/null +++ b/zetaclient/testutils/stub/keyring.go @@ -0,0 +1,111 @@ +package stub + +import ( + ckeys "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var TestKeyringPair cryptotypes.PrivKey + +func init() { + TestKeyringPair = cryptotypes.PrivKey(secp256k1.GenPrivKey()) +} + +type Keyring struct { +} + +var _ ckeys.Keyring = Keyring{} + +func NewKeyring() ckeys.Keyring { + return Keyring{} +} + +func (m Keyring) Backend() string { + return "" +} + +func (m Keyring) List() ([]*ckeys.Record, error) { + return nil, nil +} + +func (m Keyring) SupportedAlgorithms() (ckeys.SigningAlgoList, ckeys.SigningAlgoList) { + return nil, nil +} + +func (m Keyring) Key(_ string) (*ckeys.Record, error) { + return ckeys.NewLocalRecord("", TestKeyringPair, TestKeyringPair.PubKey()) +} + +func (m Keyring) KeyByAddress(_ sdk.Address) (*ckeys.Record, error) { + return nil, nil +} + +func (m Keyring) Delete(_ string) error { + return nil +} + +func (m Keyring) DeleteByAddress(_ sdk.Address) error { + return nil +} + +func (m Keyring) Rename(_ string, _ string) error { + return nil +} + +func (m Keyring) NewMnemonic(_ string, _ ckeys.Language, _, _ string, _ ckeys.SignatureAlgo) (*ckeys.Record, string, error) { + return nil, "", nil +} + +func (m Keyring) NewAccount(_, _, _, _ string, _ ckeys.SignatureAlgo) (*ckeys.Record, error) { + return nil, nil +} + +func (m Keyring) SaveLedgerKey(_ string, _ ckeys.SignatureAlgo, _ string, _, _, _ uint32) (*ckeys.Record, error) { + return nil, nil +} + +func (m Keyring) SaveOfflineKey(_ string, _ cryptotypes.PubKey) (*ckeys.Record, error) { + return nil, nil +} + +func (m Keyring) SaveMultisig(_ string, _ cryptotypes.PubKey) (*ckeys.Record, error) { + return nil, nil +} + +func (m Keyring) Sign(_ string, _ []byte) ([]byte, cryptotypes.PubKey, error) { + return nil, nil, nil +} + +func (m Keyring) SignByAddress(_ sdk.Address, _ []byte) ([]byte, cryptotypes.PubKey, error) { + return nil, nil, nil +} + +func (m Keyring) ImportPrivKey(_, _, _ string) error { + return nil +} + +func (m Keyring) ImportPubKey(_ string, _ string) error { + return nil +} + +func (m Keyring) ExportPubKeyArmor(_ string) (string, error) { + return "", nil +} + +func (m Keyring) ExportPubKeyArmorByAddress(_ sdk.Address) (string, error) { + return "", nil +} + +func (m Keyring) ExportPrivKeyArmor(_, _ string) (armor string, err error) { + return "", nil +} + +func (m Keyring) ExportPrivKeyArmorByAddress(_ sdk.Address, _ string) (armor string, err error) { + return "", nil +} + +func (m Keyring) MigrateAll() ([]*ckeys.Record, error) { + return nil, nil +} diff --git a/zetaclient/testutils/stub/sdk_client.go b/zetaclient/testutils/stub/sdk_client.go new file mode 100644 index 0000000000..c548aeb2e8 --- /dev/null +++ b/zetaclient/testutils/stub/sdk_client.go @@ -0,0 +1,68 @@ +package stub + +import ( + "context" + + abci "github.com/tendermint/tendermint/abci/types" + "github.com/tendermint/tendermint/libs/bytes" + "github.com/tendermint/tendermint/rpc/client/mock" + coretypes "github.com/tendermint/tendermint/rpc/core/types" + tmtypes "github.com/tendermint/tendermint/types" +) + +type SDKClient struct { + mock.Client + err error + code uint32 +} + +func (c SDKClient) BroadcastTxCommit(_ context.Context, _ tmtypes.Tx) (*coretypes.ResultBroadcastTxCommit, error) { + return nil, c.err +} + +func (c SDKClient) BroadcastTxAsync(_ context.Context, _ tmtypes.Tx) (*coretypes.ResultBroadcastTx, error) { + return nil, c.err +} + +func (c SDKClient) BroadcastTxSync(_ context.Context, _ tmtypes.Tx) (*coretypes.ResultBroadcastTx, error) { + log := "" + if c.err != nil { + log = c.err.Error() + } + return &coretypes.ResultBroadcastTx{ + Code: c.code, + Data: bytes.HexBytes{}, + Log: log, + Codespace: "", + Hash: bytes.HexBytes{}, + }, c.err +} + +func (c SDKClient) Tx(_ context.Context, _ []byte, _ bool) (*coretypes.ResultTx, error) { + return &coretypes.ResultTx{ + Hash: bytes.HexBytes{}, + Height: 0, + Index: 0, + TxResult: abci.ResponseDeliverTx{ + Log: "", + }, + Tx: []byte{}, + Proof: tmtypes.TxProof{}, + }, c.err +} + +func (c SDKClient) Block(_ context.Context, _ *int64) (*coretypes.ResultBlock, error) { + return &coretypes.ResultBlock{Block: &tmtypes.Block{ + Header: tmtypes.Header{}, + Data: tmtypes.Data{}, + Evidence: tmtypes.EvidenceData{}, + }}, c.err +} + +func NewSDKClientWithErr(err error, code uint32) *SDKClient { + return &SDKClient{ + Client: mock.Client{}, + err: err, + code: code, + } +} diff --git a/zetaclient/zetabridge/broadcast.go b/zetaclient/zetabridge/broadcast.go index 9c1e620474..58fddbd223 100644 --- a/zetaclient/zetabridge/broadcast.go +++ b/zetaclient/zetabridge/broadcast.go @@ -6,23 +6,24 @@ import ( "strconv" "strings" - "github.com/rs/zerolog/log" - - "github.com/zeta-chain/zetacore/zetaclient/authz" - "github.com/cosmos/cosmos-sdk/client" clienttx "github.com/cosmos/cosmos-sdk/client/tx" sdktypes "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/tx/signing" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/rs/zerolog/log" flag "github.com/spf13/pflag" rpchttp "github.com/tendermint/tendermint/rpc/client/http" "github.com/zeta-chain/zetacore/app/ante" "github.com/zeta-chain/zetacore/cmd/zetacored/config" + "github.com/zeta-chain/zetacore/zetaclient/authz" "github.com/zeta-chain/zetacore/zetaclient/hsm" ) +// BroadcastInterface defines the signature of the broadcast function used by zetabridge transactions +type BroadcastInterface = func(bridge *ZetaCoreBridge, gaslimit uint64, authzWrappedMsg sdktypes.Msg, authzSigner authz.Signer) (string, error) + const ( // DefaultBaseGasPrice is the default base gas price DefaultBaseGasPrice = 1_000_000 @@ -32,8 +33,17 @@ var ( // paying 50% more than the current base gas price to buffer for potential block-by-block // gas price increase due to EIP1559 feemarket on ZetaChain bufferMultiplier = sdktypes.MustNewDecFromStr("1.5") + + // Variable function used by transactions to broadcast a message to ZetaCore. This will create enough flexibility + // in the implementation to allow for more comprehensive unit testing. + zetaBridgeBroadcast BroadcastInterface = BroadcastToZetaCore ) +// BroadcastToZetaCore is the default broadcast function used to send transactions to Zeta Core +func BroadcastToZetaCore(bridge *ZetaCoreBridge, gasLimit uint64, authzWrappedMsg sdktypes.Msg, authzSigner authz.Signer) (string, error) { + return bridge.Broadcast(gasLimit, authzWrappedMsg, authzSigner) +} + // Broadcast Broadcasts tx to metachain. Returns txHash and error func (b *ZetaCoreBridge) Broadcast(gaslimit uint64, authzWrappedMsg sdktypes.Msg, authzSigner authz.Signer) (string, error) { b.broadcastLock.Lock() @@ -49,7 +59,7 @@ func (b *ZetaCoreBridge) Broadcast(gaslimit uint64, authzWrappedMsg sdktypes.Msg return "", err } if baseGasPrice == 0 { - baseGasPrice = DefaultBaseGasPrice // shoudn't happen, but just in case + baseGasPrice = DefaultBaseGasPrice // shouldn't happen, but just in case } reductionRate := sdktypes.MustNewDecFromStr(ante.GasPriceReductionRate) // multiply gas price by the system tx reduction rate @@ -163,17 +173,23 @@ func (b *ZetaCoreBridge) GetContext() (client.Context, error) { ctx = ctx.WithLegacyAmino(b.encodingCfg.Amino) ctx = ctx.WithAccountRetriever(authtypes.AccountRetriever{}) - remote := b.cfg.ChainRPC - if !strings.HasPrefix(b.cfg.ChainHost, "http") { - remote = fmt.Sprintf("tcp://%s", remote) - } + if b.enableMockSDKClient { + ctx = ctx.WithClient(b.mockSDKClient) + } else { + remote := b.cfg.ChainRPC + if !strings.HasPrefix(b.cfg.ChainHost, "http") { + remote = fmt.Sprintf("tcp://%s", remote) + } - ctx = ctx.WithNodeURI(remote) - wsClient, err := rpchttp.New(remote, "/websocket") - if err != nil { - return ctx, err + ctx = ctx.WithNodeURI(remote) + wsClient, err := rpchttp.New(remote, "/websocket") + if err != nil { + return ctx, err + } + + ctx = ctx.WithClient(wsClient) } - ctx = ctx.WithClient(wsClient) + return ctx, nil } @@ -200,6 +216,7 @@ func (b *ZetaCoreBridge) QueryTxResult(hash string) (*sdktypes.TxResponse, error } // HandleBroadcastError returns whether to retry in a few seconds, and whether to report via AddTxHashToOutTxTracker +// returns (bool retry, bool report) func HandleBroadcastError(err error, nonce, toChain, outTxHash string) (bool, bool) { if strings.Contains(err.Error(), "nonce too low") { log.Warn().Err(err).Msgf("nonce too low! this might be a unnecessary key-sign. increase re-try interval and awaits outTx confirmation") diff --git a/zetaclient/zetabridge/broadcast_test.go b/zetaclient/zetabridge/broadcast_test.go index a52ebb63eb..ce0aeaa57d 100644 --- a/zetaclient/zetabridge/broadcast_test.go +++ b/zetaclient/zetabridge/broadcast_test.go @@ -1,25 +1,111 @@ package zetabridge import ( - "fmt" - "regexp" + "encoding/hex" + "errors" + "net" + "testing" - . "gopkg.in/check.v1" + "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/chains" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + observerTypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/keys" + "github.com/zeta-chain/zetacore/zetaclient/testutils/stub" + "go.nhat.io/grpcmock" + "go.nhat.io/grpcmock/planner" ) -type BcastSuite struct { +func TestHandleBroadcastError(t *testing.T) { + type response struct { + retry bool + report bool + } + testCases := map[error]response{ + errors.New("nonce too low"): {retry: false, report: false}, + errors.New("replacement transaction underpriced"): {retry: false, report: false}, + errors.New("already known"): {retry: false, report: true}, + errors.New(""): {retry: true, report: false}, + } + for input, output := range testCases { + retry, report := HandleBroadcastError(input, "", "", "") + require.Equal(t, output.report, report) + require.Equal(t, output.retry, retry) + } } -var _ = Suite(&BcastSuite{}) +func TestBroadcast(t *testing.T) { + address := types.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + + //Setup server for multiple grpc calls + listener, err := net.Listen("tcp", "127.0.0.1:9090") + require.NoError(t, err) + server := grpcmock.MockUnstartedServer( + grpcmock.RegisterService(crosschaintypes.RegisterQueryServer), + grpcmock.RegisterService(feemarkettypes.RegisterQueryServer), + grpcmock.RegisterService(authtypes.RegisterQueryServer), + grpcmock.WithPlanner(planner.FirstMatch()), + grpcmock.WithListener(listener), + func(s *grpcmock.Server) { + method := "/zetachain.zetacore.crosschain.Query/LastZetaHeight" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(crosschaintypes.QueryLastZetaHeightRequest{}). + Return(crosschaintypes.QueryLastZetaHeightResponse{Height: 0}) + + method = "/ethermint.feemarket.v1.Query/Params" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(feemarkettypes.QueryParamsRequest{}). + Return(feemarkettypes.QueryParamsResponse{ + Params: feemarkettypes.Params{ + BaseFee: types.NewInt(23455), + }, + }) + }, + )(t) + + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + + t.Run("broadcast success", func(t *testing.T) { + zetabridge.EnableMockSDKClient(stub.NewSDKClientWithErr(nil, 0)) + blockHash, err := hex.DecodeString(ethBlockHash) + require.NoError(t, err) + msg := observerTypes.NewMsgAddBlockHeader(address.String(), chains.EthChain().ChainId, blockHash, 18495266, getHeaderData(t)) + authzMsg, authzSigner, err := zetabridge.WrapMessageWithAuthz(msg) + require.NoError(t, err) + _, err = BroadcastToZetaCore(zetabridge, 10000, authzMsg, authzSigner) + require.NoError(t, err) + }) + + t.Run("broadcast failed", func(t *testing.T) { + zetabridge.EnableMockSDKClient(stub.NewSDKClientWithErr(errors.New("account sequence mismatch, expected 5 got 4"), 32)) + blockHash, err := hex.DecodeString(ethBlockHash) + require.NoError(t, err) + msg := observerTypes.NewMsgAddBlockHeader(address.String(), chains.EthChain().ChainId, blockHash, 18495266, getHeaderData(t)) + authzMsg, authzSigner, err := zetabridge.WrapMessageWithAuthz(msg) + require.NoError(t, err) + _, err = BroadcastToZetaCore(zetabridge, 10000, authzMsg, authzSigner) + require.Error(t, err) + }) -func (s *BcastSuite) SetUpTest(c *C) { - fmt.Println("hello") } -func (s *BcastSuite) TestParsingSeqNumMismatch(c *C) { - err_msg := "fail to broadcast to zetabridge,code:32, log:account sequence mismatch, expected 386232, got 386230: incorrect account sequence" - re := regexp.MustCompile(`account sequence mismatch, expected ([0-9]*), got ([0-9]*)`) - fmt.Printf("%q\n", re.FindStringSubmatch(err_msg)) - err_msg2 := "hahah" - fmt.Printf("%q\n", re.FindStringSubmatch(err_msg2)) +func TestZetaCoreBridge_GetContext(t *testing.T) { + address := types.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + + _, err = zetabridge.GetContext() + require.NoError(t, err) + } diff --git a/zetaclient/zetabridge/query_test.go b/zetaclient/zetabridge/query_test.go new file mode 100644 index 0000000000..c5dabc31fd --- /dev/null +++ b/zetaclient/zetabridge/query_test.go @@ -0,0 +1,883 @@ +package zetabridge + +import ( + "net" + "testing" + + "github.com/cosmos/cosmos-sdk/client/grpc/tmservice" + "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" + "github.com/stretchr/testify/require" + tmtypes "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/zeta-chain/zetacore/cmd/zetacored/config" + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/pkg/coin" + crosschainTypes "github.com/zeta-chain/zetacore/x/crosschain/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/interfaces" + "github.com/zeta-chain/zetacore/zetaclient/keys" + "github.com/zeta-chain/zetacore/zetaclient/metrics" + "github.com/zeta-chain/zetacore/zetaclient/testutils/stub" + "go.nhat.io/grpcmock" + "go.nhat.io/grpcmock/planner" +) + +func setupMockServer(t *testing.T, serviceFunc any, method string, input any, expectedOutput any) *grpcmock.Server { + listener, err := net.Listen("tcp", "127.0.0.1:9090") + require.NoError(t, err) + + server := grpcmock.MockUnstartedServer( + grpcmock.RegisterService(serviceFunc), + grpcmock.WithPlanner(planner.FirstMatch()), + grpcmock.WithListener(listener), + func(s *grpcmock.Server) { + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(input). + Return(expectedOutput) + }, + )(t) + + return server +} + +func closeMockServer(t *testing.T, server *grpcmock.Server) { + err := server.Close() + require.NoError(t, err) +} + +func setupCoreBridge() (*ZetaCoreBridge, error) { + return NewZetaCoreBridge( + &keys.Keys{}, + "127.0.0.1", + "", + "zetachain_7000-1", + false, + &metrics.TelemetryServer{}) +} + +func TestZetaCoreBridge_GetBallot(t *testing.T) { + expectedOutput := observertypes.QueryBallotByIdentifierResponse{ + BallotIdentifier: "123", + Voters: nil, + ObservationType: 0, + BallotStatus: 0, + } + input := observertypes.QueryBallotByIdentifierRequest{BallotIdentifier: "123"} + method := "/zetachain.zetacore.observer.Query/BallotByIdentifier" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetBallotByID("123") + require.NoError(t, err) + require.Equal(t, expectedOutput, *resp) +} + +func TestZetaCoreBridge_GetCrosschainFlags(t *testing.T) { + expectedOutput := observertypes.QueryGetCrosschainFlagsResponse{CrosschainFlags: observertypes.CrosschainFlags{ + IsInboundEnabled: true, + IsOutboundEnabled: false, + GasPriceIncreaseFlags: nil, + BlockHeaderVerificationFlags: nil, + }} + input := observertypes.QueryGetCrosschainFlagsRequest{} + method := "/zetachain.zetacore.observer.Query/CrosschainFlags" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetCrosschainFlags() + require.NoError(t, err) + require.Equal(t, expectedOutput.CrosschainFlags, resp) +} + +func TestZetaCoreBridge_GetChainParamsForChainID(t *testing.T) { + expectedOutput := observertypes.QueryGetChainParamsForChainResponse{ChainParams: &observertypes.ChainParams{ + ChainId: 123, + }} + input := observertypes.QueryGetChainParamsForChainRequest{ChainId: 123} + method := "/zetachain.zetacore.observer.Query/GetChainParamsForChain" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetChainParamsForChainID(123) + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainParams, resp) +} + +func TestZetaCoreBridge_GetChainParams(t *testing.T) { + expectedOutput := observertypes.QueryGetChainParamsResponse{ChainParams: &observertypes.ChainParamsList{ + ChainParams: []*observertypes.ChainParams{ + { + ChainId: 123, + }, + }, + }} + input := observertypes.QueryGetChainParamsRequest{} + method := "/zetachain.zetacore.observer.Query/GetChainParams" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetChainParams() + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainParams.ChainParams, resp) +} + +func TestZetaCoreBridge_GetUpgradePlan(t *testing.T) { + expectedOutput := upgradetypes.QueryCurrentPlanResponse{ + Plan: &upgradetypes.Plan{ + Name: "big upgrade", + Height: 100, + }, + } + input := upgradetypes.QueryCurrentPlanRequest{} + method := "/cosmos.upgrade.v1beta1.Query/CurrentPlan" + server := setupMockServer(t, upgradetypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetUpgradePlan() + require.NoError(t, err) + require.Equal(t, expectedOutput.Plan, resp) +} + +func TestZetaCoreBridge_GetAllCctx(t *testing.T) { + expectedOutput := crosschainTypes.QueryAllCctxResponse{ + CrossChainTx: []*crosschainTypes.CrossChainTx{ + { + Index: "cross-chain4456", + }, + }, + Pagination: nil, + } + input := crosschainTypes.QueryAllCctxRequest{} + method := "/zetachain.zetacore.crosschain.Query/CctxAll" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetAllCctx() + require.NoError(t, err) + require.Equal(t, expectedOutput.CrossChainTx, resp) +} + +func TestZetaCoreBridge_GetCctxByHash(t *testing.T) { + expectedOutput := crosschainTypes.QueryGetCctxResponse{CrossChainTx: &crosschainTypes.CrossChainTx{ + Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3", + }} + input := crosschainTypes.QueryGetCctxRequest{Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3"} + method := "/zetachain.zetacore.crosschain.Query/Cctx" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetCctxByHash("9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3") + require.NoError(t, err) + require.Equal(t, expectedOutput.CrossChainTx, resp) +} + +func TestZetaCoreBridge_GetCctxByNonce(t *testing.T) { + expectedOutput := crosschainTypes.QueryGetCctxResponse{CrossChainTx: &crosschainTypes.CrossChainTx{ + Index: "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3", + }} + input := crosschainTypes.QueryGetCctxByNonceRequest{ + ChainID: 7000, + Nonce: 55, + } + method := "/zetachain.zetacore.crosschain.Query/CctxByNonce" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetCctxByNonce(7000, 55) + require.NoError(t, err) + require.Equal(t, expectedOutput.CrossChainTx, resp) +} + +func TestZetaCoreBridge_GetObserverList(t *testing.T) { + expectedOutput := observertypes.QueryObserverSetResponse{ + Observers: []string{ + "zeta19jr7nl82lrktge35f52x9g5y5prmvchmk40zhg", + "zeta1cxj07f3ju484ry2cnnhxl5tryyex7gev0yzxtj", + "zeta1hjct6q7npsspsg3dgvzk3sdf89spmlpf7rqmnw", + }, + } + input := observertypes.QueryObserverSet{} + method := "/zetachain.zetacore.observer.Query/ObserverSet" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetObserverList() + require.NoError(t, err) + require.Equal(t, expectedOutput.Observers, resp) +} + +func TestZetaCoreBridge_ListPendingCctx(t *testing.T) { + expectedOutput := crosschainTypes.QueryListCctxPendingResponse{ + CrossChainTx: []*crosschainTypes.CrossChainTx{ + { + Index: "cross-chain4456", + }, + }, + TotalPending: 1, + } + input := crosschainTypes.QueryListCctxPendingRequest{ChainId: 7000} + method := "/zetachain.zetacore.crosschain.Query/CctxListPending" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, totalPending, err := zetabridge.ListPendingCctx(7000) + require.NoError(t, err) + require.Equal(t, expectedOutput.CrossChainTx, resp) + require.Equal(t, expectedOutput.TotalPending, totalPending) +} + +func TestZetaCoreBridge_GetAbortedZetaAmount(t *testing.T) { + expectedOutput := crosschainTypes.QueryZetaAccountingResponse{AbortedZetaAmount: "1080999"} + input := crosschainTypes.QueryZetaAccountingRequest{} + method := "/zetachain.zetacore.crosschain.Query/ZetaAccounting" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetAbortedZetaAmount() + require.NoError(t, err) + require.Equal(t, expectedOutput.AbortedZetaAmount, resp) +} + +// Need to test after refactor +func TestZetaCoreBridge_GetGenesisSupply(t *testing.T) { +} + +func TestZetaCoreBridge_GetZetaTokenSupplyOnNode(t *testing.T) { + expectedOutput := banktypes.QuerySupplyOfResponse{ + Amount: types.Coin{ + Denom: config.BaseDenom, + Amount: types.NewInt(329438), + }} + input := banktypes.QuerySupplyOfRequest{Denom: config.BaseDenom} + method := "/cosmos.bank.v1beta1.Query/SupplyOf" + server := setupMockServer(t, banktypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetZetaTokenSupplyOnNode() + require.NoError(t, err) + require.Equal(t, expectedOutput.GetAmount().Amount, resp) +} + +func TestZetaCoreBridge_GetLastBlockHeight(t *testing.T) { + expectedOutput := crosschainTypes.QueryAllLastBlockHeightResponse{ + LastBlockHeight: []*crosschainTypes.LastBlockHeight{ + { + Index: "test12345", + Chain: "7000", + LastSendHeight: 32345, + LastReceiveHeight: 23623, + }, + }, + } + input := crosschainTypes.QueryAllLastBlockHeightRequest{} + method := "/zetachain.zetacore.crosschain.Query/LastBlockHeightAll" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + t.Run("last block height", func(t *testing.T) { + resp, err := zetabridge.GetLastBlockHeight() + require.NoError(t, err) + require.Equal(t, expectedOutput.LastBlockHeight, resp) + }) +} + +func TestZetaCoreBridge_GetLatestZetaBlock(t *testing.T) { + expectedOutput := tmservice.GetLatestBlockResponse{ + SdkBlock: &tmservice.Block{ + Header: tmservice.Header{}, + Data: tmtypes.Data{}, + Evidence: tmtypes.EvidenceList{}, + LastCommit: nil, + }, + } + input := tmservice.GetLatestBlockRequest{} + method := "/cosmos.base.tendermint.v1beta1.Service/GetLatestBlock" + server := setupMockServer(t, tmservice.RegisterServiceServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetLatestZetaBlock() + require.Equal(t, expectedOutput.SdkBlock, resp) +} + +func TestZetaCoreBridge_GetNodeInfo(t *testing.T) { + expectedOutput := tmservice.GetNodeInfoResponse{ + DefaultNodeInfo: nil, + ApplicationVersion: &tmservice.VersionInfo{}, + } + input := tmservice.GetNodeInfoRequest{} + method := "/cosmos.base.tendermint.v1beta1.Service/GetNodeInfo" + server := setupMockServer(t, tmservice.RegisterServiceServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetNodeInfo() + require.NoError(t, err) + require.Equal(t, expectedOutput, *resp) +} + +func TestZetaCoreBridge_GetLastBlockHeightByChain(t *testing.T) { + index := chains.BscMainnetChain() + expectedOutput := crosschainTypes.QueryGetLastBlockHeightResponse{ + LastBlockHeight: &crosschainTypes.LastBlockHeight{ + Index: index.ChainName.String(), + Chain: "7000", + LastSendHeight: 2134123, + LastReceiveHeight: 1234333, + }, + } + input := crosschainTypes.QueryGetLastBlockHeightRequest{Index: index.ChainName.String()} + method := "/zetachain.zetacore.crosschain.Query/LastBlockHeight" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetLastBlockHeightByChain(index) + require.NoError(t, err) + require.Equal(t, expectedOutput.LastBlockHeight, resp) +} + +func TestZetaCoreBridge_GetZetaBlockHeight(t *testing.T) { + expectedOutput := crosschainTypes.QueryLastZetaHeightResponse{Height: 12345} + input := crosschainTypes.QueryLastZetaHeightRequest{} + method := "/zetachain.zetacore.crosschain.Query/LastZetaHeight" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + t.Run("get zeta block height success", func(t *testing.T) { + resp, err := zetabridge.GetZetaBlockHeight() + require.NoError(t, err) + require.Equal(t, expectedOutput.Height, resp) + }) + + t.Run("get block height success", func(t *testing.T) { + resp, err := zetabridge.GetBlockHeight() + require.NoError(t, err) + require.Equal(t, expectedOutput.Height, resp) + }) +} + +func TestZetaCoreBridge_GetBaseGasPrice(t *testing.T) { + expectedOutput := feemarkettypes.QueryParamsResponse{ + Params: feemarkettypes.Params{ + BaseFee: types.NewInt(23455), + }, + } + input := feemarkettypes.QueryParamsRequest{} + method := "/ethermint.feemarket.v1.Query/Params" + server := setupMockServer(t, feemarkettypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetBaseGasPrice() + require.NoError(t, err) + require.Equal(t, expectedOutput.Params.BaseFee.Int64(), resp) +} + +func TestZetaCoreBridge_GetNonceByChain(t *testing.T) { + chain := chains.BscMainnetChain() + expectedOutput := observertypes.QueryGetChainNoncesResponse{ + ChainNonces: observertypes.ChainNonces{ + Creator: "", + Index: "", + ChainId: chain.ChainId, + Nonce: 8446, + Signers: nil, + FinalizedHeight: 0, + }, + } + input := observertypes.QueryGetChainNoncesRequest{Index: chain.ChainName.String()} + method := "/zetachain.zetacore.observer.Query/ChainNonces" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetNonceByChain(chain) + require.NoError(t, err) + require.Equal(t, expectedOutput.ChainNonces, resp) +} + +func TestZetaCoreBridge_GetAllNodeAccounts(t *testing.T) { + expectedOutput := observertypes.QueryAllNodeAccountResponse{ + NodeAccount: []*observertypes.NodeAccount{ + { + Operator: "zeta19jr7nl82lrktge35f52x9g5y5prmvchmk40zhg", + GranteeAddress: "zeta1kxhesgcvl6j5upupd9m3d3g3gfz4l3pcpqfnw6", + GranteePubkey: nil, + NodeStatus: 0, + }, + }, + } + input := observertypes.QueryAllNodeAccountRequest{} + method := "/zetachain.zetacore.observer.Query/NodeAccountAll" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetAllNodeAccounts() + require.NoError(t, err) + require.Equal(t, expectedOutput.NodeAccount, resp) +} + +func TestZetaCoreBridge_GetKeyGen(t *testing.T) { + expectedOutput := observertypes.QueryGetKeygenResponse{ + Keygen: &observertypes.Keygen{ + Status: observertypes.KeygenStatus_KeyGenSuccess, + GranteePubkeys: nil, + BlockNumber: 5646, + }} + input := observertypes.QueryGetKeygenRequest{} + method := "/zetachain.zetacore.observer.Query/Keygen" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetKeyGen() + require.NoError(t, err) + require.Equal(t, expectedOutput.Keygen, resp) +} + +func TestZetaCoreBridge_GetBallotByID(t *testing.T) { + expectedOutput := observertypes.QueryBallotByIdentifierResponse{ + BallotIdentifier: "ballot1235", + } + input := observertypes.QueryBallotByIdentifierRequest{BallotIdentifier: "ballot1235"} + method := "/zetachain.zetacore.observer.Query/BallotByIdentifier" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetBallot("ballot1235") + require.NoError(t, err) + require.Equal(t, expectedOutput, *resp) +} + +func TestZetaCoreBridge_GetInboundTrackersForChain(t *testing.T) { + chainID := chains.BscMainnetChain().ChainId + expectedOutput := crosschainTypes.QueryAllInTxTrackerByChainResponse{ + InTxTracker: []crosschainTypes.InTxTracker{ + { + ChainId: chainID, + TxHash: "DC76A6DCCC3AA62E89E69042ADC44557C50D59E4D3210C37D78DC8AE49B3B27F", + CoinType: coin.CoinType_Gas, + }, + }, + } + input := crosschainTypes.QueryAllInTxTrackerByChainRequest{ChainId: chainID} + method := "/zetachain.zetacore.crosschain.Query/InTxTrackerAllByChain" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetInboundTrackersForChain(chainID) + require.NoError(t, err) + require.Equal(t, expectedOutput.InTxTracker, resp) +} + +func TestZetaCoreBridge_GetCurrentTss(t *testing.T) { + expectedOutput := observertypes.QueryGetTSSResponse{ + TSS: observertypes.TSS{ + TssPubkey: "zetapub1addwnpepqtadxdyt037h86z60nl98t6zk56mw5zpnm79tsmvspln3hgt5phdc79kvfc", + TssParticipantList: nil, + OperatorAddressList: nil, + FinalizedZetaHeight: 1000, + KeyGenZetaHeight: 900, + }, + } + input := observertypes.QueryGetTSSRequest{} + method := "/zetachain.zetacore.observer.Query/TSS" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetCurrentTss() + require.NoError(t, err) + require.Equal(t, expectedOutput.TSS, resp) +} + +func TestZetaCoreBridge_GetEthTssAddress(t *testing.T) { + expectedOutput := observertypes.QueryGetTssAddressResponse{ + Eth: "0x70e967acfcc17c3941e87562161406d41676fd83", + Btc: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", + } + input := observertypes.QueryGetTssAddressRequest{} + method := "/zetachain.zetacore.observer.Query/GetTssAddress" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetEthTssAddress() + require.NoError(t, err) + require.Equal(t, expectedOutput.Eth, resp) +} + +func TestZetaCoreBridge_GetBtcTssAddress(t *testing.T) { + expectedOutput := observertypes.QueryGetTssAddressResponse{ + Eth: "0x70e967acfcc17c3941e87562161406d41676fd83", + Btc: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", + } + input := observertypes.QueryGetTssAddressRequest{BitcoinChainId: 8332} + method := "/zetachain.zetacore.observer.Query/GetTssAddress" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetBtcTssAddress(8332) + require.NoError(t, err) + require.Equal(t, expectedOutput.Btc, resp) +} + +func TestZetaCoreBridge_GetTssHistory(t *testing.T) { + expectedOutput := observertypes.QueryTssHistoryResponse{ + TssList: []observertypes.TSS{ + { + TssPubkey: "zetapub1addwnpepqtadxdyt037h86z60nl98t6zk56mw5zpnm79tsmvspln3hgt5phdc79kvfc", + TssParticipantList: nil, + OperatorAddressList: nil, + FinalizedZetaHeight: 46546, + KeyGenZetaHeight: 6897, + }, + }, + } + input := observertypes.QueryTssHistoryRequest{} + method := "/zetachain.zetacore.observer.Query/TssHistory" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetTssHistory() + require.NoError(t, err) + require.Equal(t, expectedOutput.TssList, resp) +} + +func TestZetaCoreBridge_GetOutTxTracker(t *testing.T) { + chain := chains.BscMainnetChain() + expectedOutput := crosschainTypes.QueryGetOutTxTrackerResponse{ + OutTxTracker: crosschainTypes.OutTxTracker{ + Index: "tracker12345", + ChainId: chain.ChainId, + Nonce: 456, + HashList: nil, + }, + } + input := crosschainTypes.QueryGetOutTxTrackerRequest{ + ChainID: chain.ChainId, + Nonce: 456, + } + method := "/zetachain.zetacore.crosschain.Query/OutTxTracker" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetOutTxTracker(chain, 456) + require.NoError(t, err) + require.Equal(t, expectedOutput.OutTxTracker, *resp) +} + +func TestZetaCoreBridge_GetAllOutTxTrackerByChain(t *testing.T) { + chain := chains.BscMainnetChain() + expectedOutput := crosschainTypes.QueryAllOutTxTrackerByChainResponse{ + OutTxTracker: []crosschainTypes.OutTxTracker{ + { + Index: "tracker23456", + ChainId: chain.ChainId, + Nonce: 123456, + HashList: nil, + }, + }, + } + input := crosschainTypes.QueryAllOutTxTrackerByChainRequest{ + Chain: chain.ChainId, + Pagination: &query.PageRequest{ + Key: nil, + Offset: 0, + Limit: 2000, + CountTotal: false, + Reverse: false, + }, + } + method := "/zetachain.zetacore.crosschain.Query/OutTxTrackerAllByChain" + server := setupMockServer(t, crosschainTypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetAllOutTxTrackerByChain(chain.ChainId, interfaces.Ascending) + require.NoError(t, err) + require.Equal(t, expectedOutput.OutTxTracker, resp) + + resp, err = zetabridge.GetAllOutTxTrackerByChain(chain.ChainId, interfaces.Descending) + require.NoError(t, err) + require.Equal(t, expectedOutput.OutTxTracker, resp) +} + +func TestZetaCoreBridge_GetPendingNoncesByChain(t *testing.T) { + expectedOutput := observertypes.QueryPendingNoncesByChainResponse{ + PendingNonces: observertypes.PendingNonces{ + NonceLow: 0, + NonceHigh: 0, + ChainId: chains.EthChain().ChainId, + Tss: "", + }, + } + input := observertypes.QueryPendingNoncesByChainRequest{ChainId: chains.EthChain().ChainId} + method := "/zetachain.zetacore.observer.Query/PendingNoncesByChain" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetPendingNoncesByChain(chains.EthChain().ChainId) + require.NoError(t, err) + require.Equal(t, expectedOutput.PendingNonces, resp) +} + +func TestZetaCoreBridge_GetBlockHeaderStateByChain(t *testing.T) { + chainID := chains.BscMainnetChain().ChainId + expectedOutput := observertypes.QueryGetBlockHeaderStateResponse{BlockHeaderState: &observertypes.BlockHeaderState{ + ChainId: chainID, + LatestHeight: 5566654, + EarliestHeight: 4454445, + LatestBlockHash: nil, + }} + input := observertypes.QueryGetBlockHeaderStateRequest{ChainId: chainID} + method := "/zetachain.zetacore.observer.Query/GetBlockHeaderStateByChain" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetBlockHeaderStateByChain(chainID) + require.NoError(t, err) + require.Equal(t, expectedOutput, resp) +} + +func TestZetaCoreBridge_GetSupportedChains(t *testing.T) { + expectedOutput := observertypes.QuerySupportedChainsResponse{ + Chains: []*chains.Chain{ + {chains.BscMainnetChain().ChainName, + chains.BscMainnetChain().ChainId, + }, + {chains.EthChain().ChainName, + chains.EthChain().ChainId, + }, + }, + } + input := observertypes.QuerySupportedChains{} + method := "/zetachain.zetacore.observer.Query/SupportedChains" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetSupportedChains() + require.NoError(t, err) + require.Equal(t, expectedOutput.Chains, resp) +} + +func TestZetaCoreBridge_GetPendingNonces(t *testing.T) { + expectedOutput := observertypes.QueryAllPendingNoncesResponse{ + PendingNonces: []observertypes.PendingNonces{ + { + NonceLow: 225, + NonceHigh: 226, + ChainId: 8332, + Tss: "bc1qm24wp577nk8aacckv8np465z3dvmu7ry45el6y", + }, + }, + } + input := observertypes.QueryAllPendingNoncesRequest{} + method := "/zetachain.zetacore.observer.Query/PendingNoncesAll" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.GetPendingNonces() + require.NoError(t, err) + require.Equal(t, expectedOutput, *resp) +} + +func TestZetaCoreBridge_Prove(t *testing.T) { + chainId := chains.BscMainnetChain().ChainId + txHash := "9c8d02b6956b9c78ecb6090a8160faaa48e7aecfd0026fcdf533721d861436a3" + blockHash := "0000000000000000000172c9a64f86f208b867a84dc7a0b7c75be51e750ed8eb" + txIndex := 555 + expectedOutput := observertypes.QueryProveResponse{ + Valid: true, + } + input := observertypes.QueryProveRequest{ + ChainId: chainId, + TxHash: txHash, + Proof: nil, + BlockHash: blockHash, + TxIndex: int64(txIndex), + } + method := "/zetachain.zetacore.observer.Query/Prove" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.Prove(blockHash, txHash, int64(txIndex), nil, chainId) + require.NoError(t, err) + require.Equal(t, expectedOutput.Valid, resp) +} + +func TestZetaCoreBridge_HasVoted(t *testing.T) { + expectedOutput := observertypes.QueryHasVotedResponse{HasVoted: true} + input := observertypes.QueryHasVotedRequest{ + BallotIdentifier: "123456asdf", + VoterAddress: "zeta1l40mm7meacx03r4lp87s9gkxfan32xnznp42u6", + } + method := "/zetachain.zetacore.observer.Query/HasVoted" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + + resp, err := zetabridge.HasVoted("123456asdf", "zeta1l40mm7meacx03r4lp87s9gkxfan32xnznp42u6") + require.NoError(t, err) + require.Equal(t, expectedOutput.HasVoted, resp) +} + +func TestZetaCoreBridge_GetZetaHotKeyBalance(t *testing.T) { + expectedOutput := banktypes.QueryBalanceResponse{ + Balance: &types.Coin{ + Denom: config.BaseDenom, + Amount: types.NewInt(55646484), + }, + } + input := banktypes.QueryBalanceRequest{ + Address: types.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()).String(), + Denom: config.BaseDenom, + } + method := "/cosmos.bank.v1beta1.Query/Balance" + server := setupMockServer(t, banktypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), types.AccAddress{}, "", "") + + resp, err := zetabridge.GetZetaHotKeyBalance() + require.NoError(t, err) + require.Equal(t, expectedOutput.Balance.Amount, resp) +} diff --git a/zetaclient/zetabridge/tx.go b/zetaclient/zetabridge/tx.go index 90e44b16f5..e7cbebd06a 100644 --- a/zetaclient/zetabridge/tx.go +++ b/zetaclient/zetabridge/tx.go @@ -61,7 +61,7 @@ func (b *ZetaCoreBridge) PostGasPrice(chain chains.Chain, gasPrice uint64, suppl } for i := 0; i < DefaultRetryCount; i++ { - zetaTxHash, err := b.Broadcast(PostGasPriceGasLimit, authzMsg, authzSigner) + zetaTxHash, err := zetaBridgeBroadcast(b, PostGasPriceGasLimit, authzMsg, authzSigner) if err == nil { return zetaTxHash, nil } @@ -97,7 +97,7 @@ func (b *ZetaCoreBridge) AddTxHashToOutTxTracker( return "", err } - zetaTxHash, err := b.Broadcast(AddTxHashToOutTxTrackerGasLimit, authzMsg, authzSigner) + zetaTxHash, err := zetaBridgeBroadcast(b, AddTxHashToOutTxTrackerGasLimit, authzMsg, authzSigner) if err != nil { return "", err } @@ -115,7 +115,7 @@ func (b *ZetaCoreBridge) SetTSS(tssPubkey string, keyGenZetaHeight int64, status zetaTxHash := "" for i := 0; i <= DefaultRetryCount; i++ { - zetaTxHash, err = b.Broadcast(DefaultGasLimit, authzMsg, authzSigner) + zetaTxHash, err = zetaBridgeBroadcast(b, DefaultGasLimit, authzMsg, authzSigner) if err == nil { return zetaTxHash, nil } @@ -162,7 +162,7 @@ func (b *ZetaCoreBridge) PostBlameData(blame *blame.Blame, chainID int64, index var gasLimit uint64 = PostBlameDataGasLimit for i := 0; i < DefaultRetryCount; i++ { - zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) + zetaTxHash, err := zetaBridgeBroadcast(b, gasLimit, authzMsg, authzSigner) if err == nil { return zetaTxHash, nil } @@ -184,7 +184,7 @@ func (b *ZetaCoreBridge) PostAddBlockHeader(chainID int64, blockHash []byte, hei var gasLimit uint64 = DefaultGasLimit for i := 0; i < DefaultRetryCount; i++ { - zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) + zetaTxHash, err := zetaBridgeBroadcast(b, gasLimit, authzMsg, authzSigner) if err == nil { return zetaTxHash, nil } @@ -214,7 +214,7 @@ func (b *ZetaCoreBridge) PostVoteInbound(gasLimit, retryGasLimit uint64, msg *ty } for i := 0; i < DefaultRetryCount; i++ { - zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) + zetaTxHash, err := zetaBridgeBroadcast(b, gasLimit, authzMsg, authzSigner) if err == nil { // monitor the result of the transaction and resend if necessary go b.MonitorVoteInboundTxResult(zetaTxHash, retryGasLimit, msg) @@ -338,7 +338,7 @@ func (b *ZetaCoreBridge) PostVoteOutboundFromMsg(gasLimit, retryGasLimit uint64, return "", ballotIndex, nil } for i := 0; i < DefaultRetryCount; i++ { - zetaTxHash, err := b.Broadcast(gasLimit, authzMsg, authzSigner) + zetaTxHash, err := zetaBridgeBroadcast(b, gasLimit, authzMsg, authzSigner) if err == nil { // monitor the result of the transaction and resend if necessary go b.MonitorVoteOutboundTxResult(zetaTxHash, retryGasLimit, msg) diff --git a/zetaclient/zetabridge/tx_test.go b/zetaclient/zetabridge/tx_test.go index 50cd82a929..20da71f1d2 100644 --- a/zetaclient/zetabridge/tx_test.go +++ b/zetaclient/zetabridge/tx_test.go @@ -1,9 +1,37 @@ package zetabridge import ( + "bytes" + "encoding/hex" + "errors" + "math/big" + "net" + "os" "testing" + "cosmossdk.io/math" + sdktypes "github.com/cosmos/cosmos-sdk/types" + upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/require" + "github.com/zeta-chain/go-tss/blame" + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/pkg/coin" + "github.com/zeta-chain/zetacore/pkg/proofs" + crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/authz" + "github.com/zeta-chain/zetacore/zetaclient/config" + corecontext "github.com/zeta-chain/zetacore/zetaclient/core_context" + "github.com/zeta-chain/zetacore/zetaclient/keys" + "github.com/zeta-chain/zetacore/zetaclient/testutils/stub" + "go.nhat.io/grpcmock" + "go.nhat.io/grpcmock/planner" +) + +const ( + sampleHash = "fa51db4412144f1130669f2bae8cb44aadbd8d85958dbffcb0fe236878097e1a" + ethBlockHash = "1a17bcc359e84ba8ae03b17ec425f97022cd11c3e279f6bdf7a96fcffa12b366" ) func Test_GasPriceMultiplier(t *testing.T) { @@ -80,3 +108,364 @@ func Test_GasPriceMultiplier(t *testing.T) { }) } } + +func ZetaBridgeBroadcastTest(_ *ZetaCoreBridge, _ uint64, _ sdktypes.Msg, _ authz.Signer) (string, error) { + return sampleHash, nil +} + +func ZetaBridgeBroadcastTestErr(_ *ZetaCoreBridge, _ uint64, _ sdktypes.Msg, _ authz.Signer) (string, error) { + return sampleHash, errors.New("broadcast error") +} + +func getHeaderData(t *testing.T) proofs.HeaderData { + var header ethtypes.Header + file, err := os.Open("../../pkg/testdata/eth_header_18495266.json") + require.NoError(t, err) + defer file.Close() + headerBytes := make([]byte, 4096) + n, err := file.Read(headerBytes) + require.NoError(t, err) + err = header.UnmarshalJSON(headerBytes[:n]) + require.NoError(t, err) + var buffer bytes.Buffer + err = header.EncodeRLP(&buffer) + require.NoError(t, err) + return proofs.NewEthereumHeader(buffer.Bytes()) +} + +func TestZetaCoreBridge_PostGasPrice(t *testing.T) { + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + + t.Run("post gas price success", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + hash, err := zetabridge.PostGasPrice(chains.BscMainnetChain(), 1000000, "100", 1234) + require.NoError(t, err) + require.Equal(t, sampleHash, hash) + }) + + // Test for failed broadcast, it will take several seconds to complete. Excluding to reduce runtime. + // + //t.Run("post gas price fail", func(t *testing.T) { + // zetaBridgeBroadcast = ZetaBridgeBroadcastTestErr + // hash, err := zetabridge.PostGasPrice(chains.BscMainnetChain(), 1000000, "100", 1234) + // require.ErrorContains(t, err, "post gasprice failed") + // require.Equal(t, "", hash) + //}) +} + +func TestZetaCoreBridge_AddTxHashToOutTxTracker(t *testing.T) { + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + + t.Run("add tx hash success", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + hash, err := zetabridge.AddTxHashToOutTxTracker(chains.BscMainnetChain().ChainId, 123, "", nil, "", 456) + require.NoError(t, err) + require.Equal(t, sampleHash, hash) + }) + + t.Run("add tx hash fail", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTestErr + hash, err := zetabridge.AddTxHashToOutTxTracker(chains.BscMainnetChain().ChainId, 123, "", nil, "", 456) + require.Error(t, err) + require.Equal(t, "", hash) + }) +} + +func TestZetaCoreBridge_SetTSS(t *testing.T) { + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + + t.Run("set tss success", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + hash, err := zetabridge.SetTSS( + "zetapub1addwnpepqtadxdyt037h86z60nl98t6zk56mw5zpnm79tsmvspln3hgt5phdc79kvfc", + 9987, + chains.ReceiveStatus_Success, + ) + require.NoError(t, err) + require.Equal(t, sampleHash, hash) + }) +} + +func TestZetaCoreBridge_UpdateZetaCoreContext(t *testing.T) { + //Setup server for multiple grpc calls + listener, err := net.Listen("tcp", "127.0.0.1:9090") + require.NoError(t, err) + + server := grpcmock.MockUnstartedServer( + grpcmock.RegisterService(crosschaintypes.RegisterQueryServer), + grpcmock.RegisterService(upgradetypes.RegisterQueryServer), + grpcmock.RegisterService(observertypes.RegisterQueryServer), + grpcmock.WithPlanner(planner.FirstMatch()), + grpcmock.WithListener(listener), + func(s *grpcmock.Server) { + method := "/zetachain.zetacore.crosschain.Query/LastZetaHeight" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(crosschaintypes.QueryLastZetaHeightRequest{}). + Return(crosschaintypes.QueryLastZetaHeightResponse{Height: 12345}) + + method = "/cosmos.upgrade.v1beta1.Query/CurrentPlan" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(upgradetypes.QueryCurrentPlanRequest{}). + Return(upgradetypes.QueryCurrentPlanResponse{ + Plan: &upgradetypes.Plan{ + Name: "big upgrade", + Height: 100, + }, + }) + + method = "/zetachain.zetacore.observer.Query/GetChainParams" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(observertypes.QueryGetChainParamsRequest{}). + Return(observertypes.QueryGetChainParamsResponse{ChainParams: &observertypes.ChainParamsList{ + ChainParams: []*observertypes.ChainParams{ + { + ChainId: 7000, + }, + }, + }}) + + method = "/zetachain.zetacore.observer.Query/SupportedChains" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(observertypes.QuerySupportedChains{}). + Return(observertypes.QuerySupportedChainsResponse{ + Chains: []*chains.Chain{ + {chains.BscMainnetChain().ChainName, + chains.BscMainnetChain().ChainId, + }, + {chains.EthChain().ChainName, + chains.EthChain().ChainId, + }, + }, + }) + + method = "/zetachain.zetacore.observer.Query/Keygen" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(observertypes.QueryGetKeygenRequest{}). + Return(observertypes.QueryGetKeygenResponse{ + Keygen: &observertypes.Keygen{ + Status: observertypes.KeygenStatus_KeyGenSuccess, + GranteePubkeys: nil, + BlockNumber: 5646, + }}) + + method = "/zetachain.zetacore.observer.Query/TSS" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(observertypes.QueryGetTSSRequest{}). + Return(observertypes.QueryGetTSSResponse{ + TSS: observertypes.TSS{ + TssPubkey: "zetapub1addwnpepqtadxdyt037h86z60nl98t6zk56mw5zpnm79tsmvspln3hgt5phdc79kvfc", + TssParticipantList: nil, + OperatorAddressList: nil, + FinalizedZetaHeight: 1000, + KeyGenZetaHeight: 900, + }, + }) + + method = "/zetachain.zetacore.observer.Query/CrosschainFlags" + s.ExpectUnary(method). + UnlimitedTimes(). + WithPayload(observertypes.QueryGetCrosschainFlagsRequest{}). + Return(observertypes.QueryGetCrosschainFlagsResponse{CrosschainFlags: observertypes.CrosschainFlags{ + IsInboundEnabled: true, + IsOutboundEnabled: false, + GasPriceIncreaseFlags: nil, + BlockHeaderVerificationFlags: nil, + }}) + }, + )(t) + + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + zetabridge.EnableMockSDKClient(stub.NewSDKClientWithErr(nil, 0)) + + t.Run("core context update success", func(t *testing.T) { + cfg := config.NewConfig() + coreCtx := corecontext.NewZetaCoreContext(cfg) + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + err := zetabridge.UpdateZetaCoreContext(coreCtx, false) + require.NoError(t, err) + }) +} + +func TestZetaCoreBridge_PostBlameData(t *testing.T) { + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + + t.Run("post blame data success", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + hash, err := zetabridge.PostBlameData( + &blame.Blame{ + FailReason: "", + IsUnicast: false, + BlameNodes: nil, + }, + chains.BscMainnetChain().ChainId, + "102394876-bsc", + ) + require.NoError(t, err) + require.Equal(t, sampleHash, hash) + }) +} + +func TestZetaCoreBridge_PostAddBlockHeader(t *testing.T) { + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + blockHash, err := hex.DecodeString(ethBlockHash) + require.NoError(t, err) + + t.Run("post add block header success", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + hash, err := zetabridge.PostAddBlockHeader( + chains.EthChain().ChainId, + blockHash, + 18495266, + getHeaderData(t), + ) + require.NoError(t, err) + require.Equal(t, sampleHash, hash) + }) +} + +func TestZetaCoreBridge_PostVoteInbound(t *testing.T) { + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + + expectedOutput := observertypes.QueryHasVotedResponse{HasVoted: false} + input := observertypes.QueryHasVotedRequest{ + BallotIdentifier: "0x2d10e9b7ce7921fa6b61ada3020d1c797d5ec52424cdcf86ef31cbbbcd45db58", + VoterAddress: address.String(), + } + method := "/zetachain.zetacore.observer.Query/HasVoted" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + zetabridge.EnableMockSDKClient(stub.NewSDKClientWithErr(nil, 0)) + + t.Run("post inbound vote already voted", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + hash, _, err := zetabridge.PostVoteInbound(100, 200, &crosschaintypes.MsgVoteOnObservedInboundTx{ + Creator: address.String(), + }) + require.NoError(t, err) + require.Equal(t, sampleHash, hash) + }) +} + +func TestZetaCoreBridge_GetInBoundVoteMessage(t *testing.T) { + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + t.Run("get inbound vote message", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + msg := GetInBoundVoteMessage( + address.String(), + chains.EthChain().ChainId, + "", + address.String(), + chains.ZetaChainMainnet().ChainId, + math.NewUint(500), + "", + "", 12345, + 1000, + coin.CoinType_Gas, + "azeta", + address.String(), + 0) + require.Equal(t, address.String(), msg.Creator) + }) +} + +func TestZetaCoreBridge_MonitorVoteInboundTxResult(t *testing.T) { + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + zetabridge.EnableMockSDKClient(stub.NewSDKClientWithErr(nil, 0)) + + t.Run("monitor inbound vote", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + zetabridge.MonitorVoteInboundTxResult(sampleHash, 1000, &crosschaintypes.MsgVoteOnObservedInboundTx{ + Creator: address.String(), + }) + // Nothing to verify against this function + // Just running through without panic + }) +} + +func TestZetaCoreBridge_PostVoteOutbound(t *testing.T) { + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + + expectedOutput := observertypes.QueryHasVotedResponse{HasVoted: false} + input := observertypes.QueryHasVotedRequest{ + BallotIdentifier: "0xc507c67847209b403def6d944486ff888c442eccf924cf9ebdc48714b22b5347", + VoterAddress: address.String(), + } + method := "/zetachain.zetacore.observer.Query/HasVoted" + server := setupMockServer(t, observertypes.RegisterQueryServer, method, input, expectedOutput) + server.Serve() + defer closeMockServer(t, server) + + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + zetabridge.EnableMockSDKClient(stub.NewSDKClientWithErr(nil, 0)) + + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + hash, ballot, err := zetabridge.PostVoteOutbound( + sampleHash, + sampleHash, + 1234, + 1000, + big.NewInt(100), + 1200, + big.NewInt(500), + chains.ReceiveStatus_Success, + chains.EthChain(), + 10001, + coin.CoinType_Gas) + require.NoError(t, err) + require.Equal(t, sampleHash, hash) + require.Equal(t, "0xc507c67847209b403def6d944486ff888c442eccf924cf9ebdc48714b22b5347", ballot) +} + +func TestZetaCoreBridge_MonitorVoteOutboundTxResult(t *testing.T) { + address := sdktypes.AccAddress(stub.TestKeyringPair.PubKey().Address().Bytes()) + zetabridge, err := setupCoreBridge() + require.NoError(t, err) + zetabridge.keys = keys.NewKeysWithKeybase(stub.NewKeyring(), address, "", "") + zetabridge.EnableMockSDKClient(stub.NewSDKClientWithErr(nil, 0)) + + t.Run("monitor outbound vote", func(t *testing.T) { + zetaBridgeBroadcast = ZetaBridgeBroadcastTest + zetabridge.MonitorVoteOutboundTxResult(sampleHash, 1000, &crosschaintypes.MsgVoteOnObservedOutboundTx{ + Creator: address.String(), + }) + // Nothing to verify against this function + // Just running through without panic + }) +} diff --git a/zetaclient/zetabridge/zetacore_bridge.go b/zetaclient/zetabridge/zetacore_bridge.go index d8a29fa665..0de3f994b0 100644 --- a/zetaclient/zetabridge/zetacore_bridge.go +++ b/zetaclient/zetabridge/zetacore_bridge.go @@ -10,9 +10,9 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - "github.com/hashicorp/go-retryablehttp" "github.com/rs/zerolog" "github.com/rs/zerolog/log" + rpcclient "github.com/tendermint/tendermint/rpc/client" "github.com/zeta-chain/zetacore/app" "github.com/zeta-chain/zetacore/pkg/authz" "github.com/zeta-chain/zetacore/pkg/chains" @@ -35,7 +35,6 @@ type ZetaCoreBridge struct { accountNumber map[authz.KeyType]uint64 seqNumber map[authz.KeyType]uint64 grpcConn *grpc.ClientConn - httpClient *retryablehttp.Client cfg config.ClientConfiguration encodingCfg params.EncodingConfig keys *keys.Keys @@ -45,6 +44,11 @@ type ZetaCoreBridge struct { stop chan struct{} pause chan struct{} Telemetry *metrics.TelemetryServer + + // enableMockSDKClient is a flag that determines whether the mock cosmos sdk client should be used, primarily for + // unit testing + enableMockSDKClient bool + mockSDKClient rpcclient.Client } // NewZetaCoreBridge create a new instance of ZetaCoreBridge @@ -67,9 +71,6 @@ func NewZetaCoreBridge( HsmMode: hsmMode, } - httpClient := retryablehttp.NewClient() - httpClient.Logger = nil - grpcConn, err := grpc.Dial( fmt.Sprintf("%s:9090", chainIP), grpc.WithInsecure(), @@ -91,20 +92,21 @@ func NewZetaCoreBridge( } return &ZetaCoreBridge{ - logger: logger, - grpcConn: grpcConn, - httpClient: httpClient, - accountNumber: accountsMap, - seqNumber: seqMap, - cfg: cfg, - encodingCfg: app.MakeEncodingConfig(), - keys: k, - broadcastLock: &sync.RWMutex{}, - stop: make(chan struct{}), - zetaChainID: chainID, - zetaChain: zetaChain, - pause: make(chan struct{}), - Telemetry: telemetry, + logger: logger, + grpcConn: grpcConn, + accountNumber: accountsMap, + seqNumber: seqMap, + cfg: cfg, + encodingCfg: app.MakeEncodingConfig(), + keys: k, + broadcastLock: &sync.RWMutex{}, + stop: make(chan struct{}), + zetaChainID: chainID, + zetaChain: zetaChain, + pause: make(chan struct{}), + Telemetry: telemetry, + enableMockSDKClient: false, + mockSDKClient: nil, }, nil } @@ -276,3 +278,8 @@ func (b *ZetaCoreBridge) Pause() { func (b *ZetaCoreBridge) Unpause() { b.pause <- struct{}{} } + +func (b *ZetaCoreBridge) EnableMockSDKClient(client rpcclient.Client) { + b.mockSDKClient = client + b.enableMockSDKClient = true +} From 47661d4df7f9029345df4c3de447889eac3dccdb Mon Sep 17 00:00:00 2001 From: skosito Date: Fri, 5 Apr 2024 21:28:46 +0100 Subject: [PATCH 3/3] test: remove setupKeeper from crosschain module (#1992) * Remove setupKeeper from crosschain module * Changelog --------- Co-authored-by: Lucas Bertrand --- changelog.md | 1 + x/crosschain/keeper/gas_price_test.go | 27 ++++---- .../keeper/grpc_query_gas_price_test.go | 21 +++--- .../grpc_query_last_block_height_test.go | 33 +++++----- x/crosschain/keeper/keeper_test.go | 65 ------------------- x/crosschain/keeper/last_block_height_test.go | 26 ++++---- 6 files changed, 58 insertions(+), 115 deletions(-) delete mode 100644 x/crosschain/keeper/keeper_test.go diff --git a/changelog.md b/changelog.md index 73e8e04e28..da05d7b9b4 100644 --- a/changelog.md +++ b/changelog.md @@ -58,6 +58,7 @@ * [1955](https://github.com/zeta-chain/node/pull/1955) - improve emissions module coverage * [1941](https://github.com/zeta-chain/node/pull/1941) - add unit tests for zetabridge package * [1985](https://github.com/zeta-chain/node/pull/1985) - improve fungible module coverage +* [1992](https://github.com/zeta-chain/node/pull/1992) - remove setupKeeper from crosschain module ### Fixes diff --git a/x/crosschain/keeper/gas_price_test.go b/x/crosschain/keeper/gas_price_test.go index 67aeb95cd6..bdd867081e 100644 --- a/x/crosschain/keeper/gas_price_test.go +++ b/x/crosschain/keeper/gas_price_test.go @@ -1,4 +1,4 @@ -package keeper +package keeper_test import ( "strconv" @@ -6,11 +6,13 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/x/crosschain/keeper" "github.com/zeta-chain/zetacore/x/crosschain/types" ) // Keeper Tests -func createNGasPrice(keeper *Keeper, ctx sdk.Context, n int) []types.GasPrice { +func createNGasPrice(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.GasPrice { items := make([]types.GasPrice, n) for i := range items { items[i].Creator = "any" @@ -22,26 +24,27 @@ func createNGasPrice(keeper *Keeper, ctx sdk.Context, n int) []types.GasPrice { } func TestGasPriceGet(t *testing.T) { - keeper, ctx := setupKeeper(t) - items := createNGasPrice(keeper, ctx, 10) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + items := createNGasPrice(k, ctx, 10) for _, item := range items { - rst, found := keeper.GetGasPrice(ctx, item.ChainId) + rst, found := k.GetGasPrice(ctx, item.ChainId) require.True(t, found) require.Equal(t, item, rst) } } + func TestGasPriceRemove(t *testing.T) { - keeper, ctx := setupKeeper(t) - items := createNGasPrice(keeper, ctx, 10) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + items := createNGasPrice(k, ctx, 10) for _, item := range items { - keeper.RemoveGasPrice(ctx, item.Index) - _, found := keeper.GetGasPrice(ctx, item.ChainId) + k.RemoveGasPrice(ctx, item.Index) + _, found := k.GetGasPrice(ctx, item.ChainId) require.False(t, found) } } func TestGasPriceGetAll(t *testing.T) { - keeper, ctx := setupKeeper(t) - items := createNGasPrice(keeper, ctx, 10) - require.Equal(t, items, keeper.GetAllGasPrice(ctx)) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + items := createNGasPrice(k, ctx, 10) + require.Equal(t, items, k.GetAllGasPrice(ctx)) } diff --git a/x/crosschain/keeper/grpc_query_gas_price_test.go b/x/crosschain/keeper/grpc_query_gas_price_test.go index b8e9f0606e..bba8f9ae74 100644 --- a/x/crosschain/keeper/grpc_query_gas_price_test.go +++ b/x/crosschain/keeper/grpc_query_gas_price_test.go @@ -1,4 +1,4 @@ -package keeper +package keeper_test import ( "fmt" @@ -7,15 +7,16 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/x/crosschain/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) func TestGasPriceQuerySingle(t *testing.T) { - keeper, ctx := setupKeeper(t) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) wctx := sdk.WrapSDKContext(ctx) - msgs := createNGasPrice(keeper, ctx, 2) + msgs := createNGasPrice(k, ctx, 2) for _, tc := range []struct { desc string request *types.QueryGetGasPriceRequest @@ -49,7 +50,7 @@ func TestGasPriceQuerySingle(t *testing.T) { } { tc := tc t.Run(tc.desc, func(t *testing.T) { - response, err := keeper.GasPrice(wctx, tc.request) + response, err := k.GasPrice(wctx, tc.request) if tc.err != nil { require.Error(t, err) } else { @@ -60,9 +61,9 @@ func TestGasPriceQuerySingle(t *testing.T) { } func TestGasPriceQueryPaginated(t *testing.T) { - keeper, ctx := setupKeeper(t) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) wctx := sdk.WrapSDKContext(ctx) - msgs := createNGasPrice(keeper, ctx, 5) + msgs := createNGasPrice(k, ctx, 5) request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllGasPriceRequest { return &types.QueryAllGasPriceRequest{ @@ -77,7 +78,7 @@ func TestGasPriceQueryPaginated(t *testing.T) { t.Run("ByOffset", func(t *testing.T) { step := 2 for i := 0; i < len(msgs); i += step { - resp, err := keeper.GasPriceAll(wctx, request(nil, uint64(i), uint64(step), false)) + resp, err := k.GasPriceAll(wctx, request(nil, uint64(i), uint64(step), false)) require.NoError(t, err) for j := i; j < len(msgs) && j < i+step; j++ { require.Equal(t, &msgs[j], resp.GasPrice[j-i]) @@ -88,7 +89,7 @@ func TestGasPriceQueryPaginated(t *testing.T) { step := 2 var next []byte for i := 0; i < len(msgs); i += step { - resp, err := keeper.GasPriceAll(wctx, request(next, 0, uint64(step), false)) + resp, err := k.GasPriceAll(wctx, request(next, 0, uint64(step), false)) require.NoError(t, err) for j := i; j < len(msgs) && j < i+step; j++ { require.Equal(t, &msgs[j], resp.GasPrice[j-i]) @@ -97,12 +98,12 @@ func TestGasPriceQueryPaginated(t *testing.T) { } }) t.Run("Total", func(t *testing.T) { - resp, err := keeper.GasPriceAll(wctx, request(nil, 0, 0, true)) + resp, err := k.GasPriceAll(wctx, request(nil, 0, 0, true)) require.NoError(t, err) require.Equal(t, len(msgs), int(resp.Pagination.Total)) }) t.Run("InvalidRequest", func(t *testing.T) { - _, err := keeper.GasPriceAll(wctx, nil) + _, err := k.GasPriceAll(wctx, nil) require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) }) } diff --git a/x/crosschain/keeper/grpc_query_last_block_height_test.go b/x/crosschain/keeper/grpc_query_last_block_height_test.go index 057fe120b9..81e3c7d2d9 100644 --- a/x/crosschain/keeper/grpc_query_last_block_height_test.go +++ b/x/crosschain/keeper/grpc_query_last_block_height_test.go @@ -1,4 +1,4 @@ -package keeper +package keeper_test import ( "math" @@ -7,15 +7,16 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/query" "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" "github.com/zeta-chain/zetacore/x/crosschain/types" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) func TestLastBlockHeightQuerySingle(t *testing.T) { - keeper, ctx := setupKeeper(t) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) wctx := sdk.WrapSDKContext(ctx) - msgs := createNLastBlockHeight(keeper, ctx, 2) + msgs := createNLastBlockHeight(k, ctx, 2) for _, tc := range []struct { desc string request *types.QueryGetLastBlockHeightRequest @@ -44,7 +45,7 @@ func TestLastBlockHeightQuerySingle(t *testing.T) { } { tc := tc t.Run(tc.desc, func(t *testing.T) { - response, err := keeper.LastBlockHeight(wctx, tc.request) + response, err := k.LastBlockHeight(wctx, tc.request) if tc.err != nil { require.ErrorIs(t, err, tc.err) } else { @@ -56,14 +57,14 @@ func TestLastBlockHeightQuerySingle(t *testing.T) { func TestLastBlockHeightLimits(t *testing.T) { t.Run("should err if last send height is max int", func(t *testing.T) { - keeper, ctx := setupKeeper(t) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) wctx := sdk.WrapSDKContext(ctx) - keeper.SetLastBlockHeight(ctx, types.LastBlockHeight{ + k.SetLastBlockHeight(ctx, types.LastBlockHeight{ Index: "index", LastSendHeight: math.MaxInt64, }) - res, err := keeper.LastBlockHeight(wctx, &types.QueryGetLastBlockHeightRequest{ + res, err := k.LastBlockHeight(wctx, &types.QueryGetLastBlockHeightRequest{ Index: "index", }) require.Nil(t, res) @@ -71,15 +72,15 @@ func TestLastBlockHeightLimits(t *testing.T) { }) t.Run("should err if last receive height is max int", func(t *testing.T) { - keeper, ctx := setupKeeper(t) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) wctx := sdk.WrapSDKContext(ctx) - keeper.SetLastBlockHeight(ctx, types.LastBlockHeight{ + k.SetLastBlockHeight(ctx, types.LastBlockHeight{ Index: "index", LastSendHeight: 10, LastReceiveHeight: math.MaxInt64, }) - res, err := keeper.LastBlockHeight(wctx, &types.QueryGetLastBlockHeightRequest{ + res, err := k.LastBlockHeight(wctx, &types.QueryGetLastBlockHeightRequest{ Index: "index", }) require.Nil(t, res) @@ -88,9 +89,9 @@ func TestLastBlockHeightLimits(t *testing.T) { } func TestLastBlockHeightQueryPaginated(t *testing.T) { - keeper, ctx := setupKeeper(t) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) wctx := sdk.WrapSDKContext(ctx) - msgs := createNLastBlockHeight(keeper, ctx, 5) + msgs := createNLastBlockHeight(k, ctx, 5) request := func(next []byte, offset, limit uint64, total bool) *types.QueryAllLastBlockHeightRequest { return &types.QueryAllLastBlockHeightRequest{ @@ -105,7 +106,7 @@ func TestLastBlockHeightQueryPaginated(t *testing.T) { t.Run("ByOffset", func(t *testing.T) { step := 2 for i := 0; i < len(msgs); i += step { - resp, err := keeper.LastBlockHeightAll(wctx, request(nil, uint64(i), uint64(step), false)) + resp, err := k.LastBlockHeightAll(wctx, request(nil, uint64(i), uint64(step), false)) require.NoError(t, err) for j := i; j < len(msgs) && j < i+step; j++ { require.Equal(t, &msgs[j], resp.LastBlockHeight[j-i]) @@ -116,7 +117,7 @@ func TestLastBlockHeightQueryPaginated(t *testing.T) { step := 2 var next []byte for i := 0; i < len(msgs); i += step { - resp, err := keeper.LastBlockHeightAll(wctx, request(next, 0, uint64(step), false)) + resp, err := k.LastBlockHeightAll(wctx, request(next, 0, uint64(step), false)) require.NoError(t, err) for j := i; j < len(msgs) && j < i+step; j++ { require.Equal(t, &msgs[j], resp.LastBlockHeight[j-i]) @@ -125,12 +126,12 @@ func TestLastBlockHeightQueryPaginated(t *testing.T) { } }) t.Run("Total", func(t *testing.T) { - resp, err := keeper.LastBlockHeightAll(wctx, request(nil, 0, 0, true)) + resp, err := k.LastBlockHeightAll(wctx, request(nil, 0, 0, true)) require.NoError(t, err) require.Equal(t, len(msgs), int(resp.Pagination.Total)) }) t.Run("InvalidRequest", func(t *testing.T) { - _, err := keeper.LastBlockHeightAll(wctx, nil) + _, err := k.LastBlockHeightAll(wctx, nil) require.ErrorIs(t, err, status.Error(codes.InvalidArgument, "invalid request")) }) } diff --git a/x/crosschain/keeper/keeper_test.go b/x/crosschain/keeper/keeper_test.go deleted file mode 100644 index 58cc10896e..0000000000 --- a/x/crosschain/keeper/keeper_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package keeper - -import ( - "testing" - - "github.com/cosmos/cosmos-sdk/codec" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/store" - storetypes "github.com/cosmos/cosmos-sdk/store/types" - sdk "github.com/cosmos/cosmos-sdk/types" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - bankkeeper "github.com/cosmos/cosmos-sdk/x/bank/keeper" - typesparams "github.com/cosmos/cosmos-sdk/x/params/types" - stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper" - "github.com/stretchr/testify/require" - "github.com/tendermint/tendermint/libs/log" - tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - tmdb "github.com/tendermint/tm-db" - authoritykeeper "github.com/zeta-chain/zetacore/x/authority/keeper" - "github.com/zeta-chain/zetacore/x/crosschain/types" - fungiblekeeper "github.com/zeta-chain/zetacore/x/fungible/keeper" - "github.com/zeta-chain/zetacore/x/observer/keeper" -) - -func setupKeeper(t testing.TB) (*Keeper, sdk.Context) { - storeKey := sdk.NewKVStoreKey(types.StoreKey) - memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey) - - db := tmdb.NewMemDB() - stateStore := store.NewCommitMultiStore(db) - stateStore.MountStoreWithDB(storeKey, storetypes.StoreTypeIAVL, db) - stateStore.MountStoreWithDB(memStoreKey, storetypes.StoreTypeMemory, nil) - require.NoError(t, stateStore.LoadLatestVersion()) - - registry := codectypes.NewInterfaceRegistry() - cdc := codec.NewProtoCodec(registry) - - paramsSubspace := typesparams.NewSubspace(cdc, - types.Amino, - storeKey, - memStoreKey, - "ZetacoreParams", - ) - bankKeeper := bankkeeper.BaseKeeper{} - authKeeper := authkeeper.AccountKeeper{} - observerKeeper := keeper.Keeper{} - fungibleKeeper := fungiblekeeper.Keeper{} - authorityKeeper := authoritykeeper.Keeper{} - - k := NewKeeper( - codec.NewProtoCodec(registry), - storeKey, - memStoreKey, - stakingkeeper.Keeper{}, // custom - paramsSubspace, - authKeeper, - bankKeeper, - observerKeeper, - &fungibleKeeper, - authorityKeeper, - ) - - ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) - return k, ctx -} diff --git a/x/crosschain/keeper/last_block_height_test.go b/x/crosschain/keeper/last_block_height_test.go index 8a284f6f97..707b89ff02 100644 --- a/x/crosschain/keeper/last_block_height_test.go +++ b/x/crosschain/keeper/last_block_height_test.go @@ -1,4 +1,4 @@ -package keeper +package keeper_test import ( "fmt" @@ -6,10 +6,12 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/stretchr/testify/require" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/x/crosschain/keeper" "github.com/zeta-chain/zetacore/x/crosschain/types" ) -func createNLastBlockHeight(keeper *Keeper, ctx sdk.Context, n int) []types.LastBlockHeight { +func createNLastBlockHeight(keeper *keeper.Keeper, ctx sdk.Context, n int) []types.LastBlockHeight { items := make([]types.LastBlockHeight, n) for i := range items { items[i].Creator = "any" @@ -20,26 +22,26 @@ func createNLastBlockHeight(keeper *Keeper, ctx sdk.Context, n int) []types.Last } func TestLastBlockHeightGet(t *testing.T) { - keeper, ctx := setupKeeper(t) - items := createNLastBlockHeight(keeper, ctx, 10) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + items := createNLastBlockHeight(k, ctx, 10) for _, item := range items { - rst, found := keeper.GetLastBlockHeight(ctx, item.Index) + rst, found := k.GetLastBlockHeight(ctx, item.Index) require.True(t, found) require.Equal(t, item, rst) } } func TestLastBlockHeightRemove(t *testing.T) { - keeper, ctx := setupKeeper(t) - items := createNLastBlockHeight(keeper, ctx, 10) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + items := createNLastBlockHeight(k, ctx, 10) for _, item := range items { - keeper.RemoveLastBlockHeight(ctx, item.Index) - _, found := keeper.GetLastBlockHeight(ctx, item.Index) + k.RemoveLastBlockHeight(ctx, item.Index) + _, found := k.GetLastBlockHeight(ctx, item.Index) require.False(t, found) } } func TestLastBlockHeightGetAll(t *testing.T) { - keeper, ctx := setupKeeper(t) - items := createNLastBlockHeight(keeper, ctx, 10) - require.Equal(t, items, keeper.GetAllLastBlockHeight(ctx)) + k, ctx, _, _ := keepertest.CrosschainKeeper(t) + items := createNLastBlockHeight(k, ctx, 10) + require.Equal(t, items, k.GetAllLastBlockHeight(ctx)) }