From 131a774b06d39e8c1a7884d34f4d962f9edff626 Mon Sep 17 00:00:00 2001 From: skosito Date: Fri, 5 Apr 2024 06:50:26 +0100 Subject: [PATCH] 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 {