From 839dc802053ee2dfe1dff9aea511a722d3e12dd7 Mon Sep 17 00:00:00 2001 From: Robert Pirtle Date: Wed, 2 Aug 2023 14:52:48 -0700 Subject: [PATCH] test(e2e): update kvtool & e2e tests (#1659) * add Cdp querier to Chain * verify funded account has sufficient balance * return error for nonzero status codes * update e2e test for eip712 signing complex eip712 workflow now uses x/cdp instead of x/earn vault * update to master kvtool * reset e2e env variables --- tests/e2e/.env | 11 ++++-- tests/e2e/.env.live-network-example | 11 ++++-- tests/e2e/e2e_evm_contracts_test.go | 59 ++++++++++++++++------------- tests/e2e/kvtool | 2 +- tests/e2e/testutil/account.go | 15 ++++++-- tests/e2e/testutil/chain.go | 3 ++ tests/e2e/testutil/init_evm.go | 24 ++++++++---- tests/e2e/testutil/suite.go | 8 ++-- tests/util/sdksigner.go | 4 ++ 9 files changed, 87 insertions(+), 50 deletions(-) diff --git a/tests/e2e/.env b/tests/e2e/.env index 9c8ec26a..fbd211dd 100644 --- a/tests/e2e/.env +++ b/tests/e2e/.env @@ -28,8 +28,11 @@ E2E_KAVA_UPGRADE_HEIGHT= # E2E_KAVA_UPGRADE_BASE_IMAGE_TAG is the tag of the docker image the chain should upgrade from. E2E_KAVA_UPGRADE_BASE_IMAGE_TAG= -# E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token. -# The E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC account must have a balance. -# The ERC20 must be enabled via x/evmutil params for conversion to sdk.Coin. -# The corresponding sdk.Coin must be a supported vault in x/earn. +# E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token with the following properties: +# - the E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC has nonzero balance +# - the ERC20 must be enabled via x/evmutil params for conversion to sdk.Coin +# - the corresponsing sdk.Coin must be supported as a cdp collateral type (w/ valid pricefeed) +# - the evmutil params must support conversion & deposits to mint in eip712 messages +# +# These requirements are verified on test startup in ./testutil/init_evm.go E2E_KAVA_ERC20_ADDRESS=0xeA7100edA2f805356291B0E55DaD448599a72C6d diff --git a/tests/e2e/.env.live-network-example b/tests/e2e/.env.live-network-example index 69a7adbf..7b8fe247 100644 --- a/tests/e2e/.env.live-network-example +++ b/tests/e2e/.env.live-network-example @@ -13,8 +13,11 @@ E2E_KAVA_EVM_RPC_URL='http://localhost:8545' # E2E_INCLUDE_IBC_TESTS is not currently supported for running tests against a live network. E2E_INCLUDE_IBC_TESTS=false -# E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token. -# The E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC account must have a balance. -# The ERC20 must be enabled via x/evmutil params for conversion to sdk.Coin. -# The corresponding sdk.Coin must be a supported vault in x/earn. +# E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token with the following properties: +# - the E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC has nonzero balance +# - the ERC20 must be enabled via x/evmutil params for conversion to sdk.Coin +# - the corresponsing sdk.Coin must be supported as a cdp collateral type (w/ valid pricefeed) +# - the evmutil params must support conversion & deposits to mint in eip712 messages +# +# These requirements are verified on test startup in ./testutil/init_evm.go E2E_KAVA_ERC20_ADDRESS=0xeA7100edA2f805356291B0E55DaD448599a72C6d diff --git a/tests/e2e/e2e_evm_contracts_test.go b/tests/e2e/e2e_evm_contracts_test.go index 1153dac2..42c91409 100644 --- a/tests/e2e/e2e_evm_contracts_test.go +++ b/tests/e2e/e2e_evm_contracts_test.go @@ -11,7 +11,7 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/kava-labs/kava/app" - earntypes "github.com/kava-labs/kava/x/earn/types" + cdptypes "github.com/kava-labs/kava/x/cdp/types" evmutiltypes "github.com/kava-labs/kava/x/evmutil/types" "github.com/kava-labs/kava/tests/e2e/contracts/greeter" @@ -106,13 +106,16 @@ func (suite *IntegrationTestSuite) TestEip712BasicMessageAuthorization() { suite.Equal(sdk.NewInt(1e3), balRes.Balance.Amount) } -// Note that this test works because the deployed erc20 is configured in evmutil & earn params. -func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() { - amount := sdk.NewInt(1e2) // 0.0002 USDC +// Note that this test works because the deployed erc20 is configured in evmutil & cdp params. +// This test matches the webapp's "USDT Earn" workflow +func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToLend() { + // cdp requires minimum of $11 collateral + amount := sdk.NewInt(11e6) // 11 USDT + principal := sdk.NewCoin("usdx", sdk.NewInt(10e6)) sdkDenom := suite.DeployedErc20.CosmosDenom // create new funded account - depositor := suite.Kava.NewFundedAccount("eip712-earn-depositor", sdk.NewCoins(ukava(1e5))) + depositor := suite.Kava.NewFundedAccount("eip712-lend-depositor", sdk.NewCoins(ukava(1e5))) // give them erc20 balance to deposit fundRes := suite.FundKavaErc20Balance(depositor.EvmAddress, amount.BigInt()) suite.NoError(fundRes.Err) @@ -124,16 +127,17 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() { evmutiltypes.NewInternalEVMAddress(suite.DeployedErc20.Address), amount, ) - depositMsg := earntypes.NewMsgDeposit( - depositor.SdkAddress.String(), + depositMsg := cdptypes.NewMsgCreateCDP( + depositor.SdkAddress, sdk.NewCoin(sdkDenom, amount), - earntypes.STRATEGY_TYPE_SAVINGS, + principal, + suite.DeployedErc20.CdpCollateralType, ) msgs := []sdk.Msg{ // convert to coin &convertMsg, - // deposit into earn - depositMsg, + // deposit into cdp (Mint), take out USDX + &depositMsg, } // create tx @@ -143,7 +147,7 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() { 1e6, sdk.NewCoins(ukava(1e4)), msgs, - "depositing my USDC into Earn!", + "doing the USDT Earn workflow! erc20 -> sdk.Coin -> USDX hard deposit", ).GetTx() txBytes, err := suite.Kava.EncodingConfig.TxConfig.TxEncoder()(tx) @@ -158,26 +162,26 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() { suite.Equal(sdkerrors.SuccessABCICode, res.TxResponse.Code) _, err = util.WaitForSdkTxCommit(suite.Kava.Tx, res.TxResponse.TxHash, 6*time.Second) - suite.NoError(err) + suite.Require().NoError(err) // check that depositor no longer has erc20 balance balance := suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, depositor.EvmAddress) suite.BigIntsEqual(big.NewInt(0), balance, "expected no erc20 balance") - // check that account has an earn deposit position - earnRes, err := suite.Kava.Earn.Deposits(context.Background(), &earntypes.QueryDepositsRequest{ - Depositor: depositor.SdkAddress.String(), - Denom: sdkDenom, + // check that account has cdp + cdpRes, err := suite.Kava.Cdp.Cdp(context.Background(), &cdptypes.QueryCdpRequest{ + CollateralType: suite.DeployedErc20.CdpCollateralType, + Owner: depositor.SdkAddress.String(), }) suite.NoError(err) - suite.Len(earnRes.Deposits, 1) - suite.Equal(sdk.NewDecFromInt(amount), earnRes.Deposits[0].Shares.AmountOf(sdkDenom)) + suite.True(cdpRes.Cdp.Collateral.Amount.Equal(amount)) + suite.True(cdpRes.Cdp.Principal.Equal(principal)) // withdraw deposit & convert back to erc20 (this allows refund to recover erc20s used in test) - withdraw := earntypes.NewMsgWithdraw( - depositor.SdkAddress.String(), - sdk.NewCoin(sdkDenom, amount), - earntypes.STRATEGY_TYPE_SAVINGS, + withdraw := cdptypes.NewMsgRepayDebt( + depositor.SdkAddress, + suite.DeployedErc20.CdpCollateralType, + principal, ) convertBack := evmutiltypes.NewMsgConvertCoinToERC20( depositor.SdkAddress.String(), @@ -185,11 +189,14 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() { sdk.NewCoin(sdkDenom, amount), ) withdrawAndConvertBack := util.KavaMsgRequest{ - Msgs: []sdk.Msg{withdraw, &convertBack}, - GasLimit: 3e5, - FeeAmount: sdk.NewCoins(ukava(300)), - Data: "withdrawing from earn & converting back to erc20", + Msgs: []sdk.Msg{&withdraw, &convertBack}, + GasLimit: 1e6, + FeeAmount: sdk.NewCoins(ukava(1000)), + Data: "withdrawing from mint & converting back to erc20", } lastRes := depositor.SignAndBroadcastKavaTx(withdrawAndConvertBack) suite.NoError(lastRes.Err) + + balance = suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, depositor.EvmAddress) + suite.BigIntsEqual(amount.BigInt(), balance, "expected returned erc20 balance") } diff --git a/tests/e2e/kvtool b/tests/e2e/kvtool index 68f3a5ce..b093fc9f 160000 --- a/tests/e2e/kvtool +++ b/tests/e2e/kvtool @@ -1 +1 @@ -Subproject commit 68f3a5ce9e688028ab66cecdb583223f03e153fc +Subproject commit b093fc9f2a28cf57b4a6924f45919edcfe551eaf diff --git a/tests/e2e/testutil/account.go b/tests/e2e/testutil/account.go index 1f2eea99..19b5b7fb 100644 --- a/tests/e2e/testutil/account.go +++ b/tests/e2e/testutil/account.go @@ -9,20 +9,23 @@ import ( "os" "time" + "github.com/stretchr/testify/require" + sdkmath "cosmossdk.io/math" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/go-bip39" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/evmos/ethermint/crypto/ethsecp256k1" emtests "github.com/evmos/ethermint/tests" emtypes "github.com/evmos/ethermint/types" - "github.com/stretchr/testify/require" "github.com/kava-labs/kava/app" "github.com/kava-labs/kava/tests/util" @@ -207,9 +210,15 @@ func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccou return acc } - // TODO: verify whale has funds. - whale := chain.GetAccount(FundedAccountName) + + // check that the whale has the necessary balance to fund account + bal := chain.QuerySdkForBalances(whale.SdkAddress) + require.Truef(chain.t, + bal.IsAllGT(funds), + "funded account lacks funds for account %s\nneeds: %s\nhas: %s", name, funds, bal, + ) + whale.l.Printf("attempting to fund created account (%s=%s)\n", name, acc.SdkAddress.String()) res := whale.BankSend(acc.SdkAddress, funds) diff --git a/tests/e2e/testutil/chain.go b/tests/e2e/testutil/chain.go index 3f757aaf..54244100 100644 --- a/tests/e2e/testutil/chain.go +++ b/tests/e2e/testutil/chain.go @@ -26,6 +26,7 @@ import ( kavaparams "github.com/kava-labs/kava/app/params" "github.com/kava-labs/kava/tests/e2e/runner" "github.com/kava-labs/kava/tests/util" + cdptypes "github.com/kava-labs/kava/x/cdp/types" committeetypes "github.com/kava-labs/kava/x/committee/types" communitytypes "github.com/kava-labs/kava/x/community/types" earntypes "github.com/kava-labs/kava/x/earn/types" @@ -48,6 +49,7 @@ type Chain struct { Auth authtypes.QueryClient Bank banktypes.QueryClient + Cdp cdptypes.QueryClient Committee committeetypes.QueryClient Community communitytypes.QueryClient Earn earntypes.QueryClient @@ -83,6 +85,7 @@ func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic chain.Auth = authtypes.NewQueryClient(grpcConn) chain.Bank = banktypes.NewQueryClient(grpcConn) + chain.Cdp = cdptypes.NewQueryClient(grpcConn) chain.Committee = committeetypes.NewQueryClient(grpcConn) chain.Community = communitytypes.NewQueryClient(grpcConn) chain.Earn = earntypes.NewQueryClient(grpcConn) diff --git a/tests/e2e/testutil/init_evm.go b/tests/e2e/testutil/init_evm.go index 9dabb591..823992ee 100644 --- a/tests/e2e/testutil/init_evm.go +++ b/tests/e2e/testutil/init_evm.go @@ -8,7 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/kava-labs/kava/tests/e2e/contracts/greeter" - "github.com/kava-labs/kava/x/earn/types" + "github.com/kava-labs/kava/x/cdp/types" evmutiltypes "github.com/kava-labs/kava/x/evmutil/types" ) @@ -41,13 +41,21 @@ func (suite *E2eTestSuite) InitKavaEvmData() { } suite.Kava.RegisterErc20(suite.DeployedErc20.Address) - // expect the erc20's cosmos denom to be a supported earn vault - _, err = suite.Kava.Earn.Vault( - context.Background(), - types.NewQueryVaultRequest(suite.DeployedErc20.CosmosDenom), - ) - if err != nil { - panic(fmt.Sprintf("failed to find earn vault with denom %s: %s", suite.DeployedErc20.CosmosDenom, err)) + // expect the erc20's cosmos denom to be a supported cdp collateral type + cdpParams, err := suite.Kava.Cdp.Params(context.Background(), &types.QueryParamsRequest{}) + suite.Require().NoError(err) + found = false + for _, cp := range cdpParams.Params.CollateralParams { + if cp.Denom == suite.DeployedErc20.CosmosDenom { + found = true + suite.DeployedErc20.CdpCollateralType = cp.Type + } + } + if !found { + panic(fmt.Sprintf( + "erc20's cosmos denom %s must be valid cdp collateral type", + suite.DeployedErc20.CosmosDenom), + ) } // deploy an example contract diff --git a/tests/e2e/testutil/suite.go b/tests/e2e/testutil/suite.go index 82ad211f..ff3eae98 100644 --- a/tests/e2e/testutil/suite.go +++ b/tests/e2e/testutil/suite.go @@ -33,11 +33,13 @@ const ( // The tests expect the following: // - the funded account has a nonzero balance of the erc20 // - the erc20 is enabled for conversion to sdk.Coin -// - the corresponding sdk.Coin is enabled as an earn vault denom +// - the corresponding sdk.Coin is enabled as a cdp collateral type // These requirements are checked in InitKavaEvmData(). type DeployedErc20 struct { Address common.Address CosmosDenom string + + CdpCollateralType string } // E2eTestSuite is a testify test suite for running end-to-end integration tests on Kava. @@ -90,7 +92,7 @@ func (suite *E2eTestSuite) SetupSuite() { suite.config = suiteConfig suite.DeployedErc20 = DeployedErc20{ Address: common.HexToAddress(suiteConfig.KavaErc20Address), - // Denom is fetched in InitKavaEvmData() + // Denom & CdpCollateralType are fetched in InitKavaEvmData() } // setup the correct NodeRunner for the given config @@ -154,8 +156,6 @@ func (suite *E2eTestSuite) TearDownSuite() { suite.cost.erc20BalanceAfter = suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, whale.EvmAddress) fmt.Println(suite.cost) - // TODO: track asset denoms & then return all funds to initial funding account. - // close all account request channels suite.Kava.Shutdown() if suite.Ibc != nil { diff --git a/tests/util/sdksigner.go b/tests/util/sdksigner.go index 4c0fe366..a81e0fb3 100644 --- a/tests/util/sdksigner.go +++ b/tests/util/sdksigner.go @@ -24,6 +24,7 @@ import ( var ( ErrSdkBroadcastTimeout = errors.New("timed out waiting for tx to be committed to block") + ErrUnsuccessfulTx = errors.New("tx committed but returned nonzero code") ) type KavaMsgRequest struct { @@ -454,6 +455,9 @@ func WaitForSdkTxCommit(txClient txtypes.ServiceClient, txHash string, timeout t break } txRes = res.TxResponse + if err == nil && txRes.Code != uint32(codes.OK) { + err = errorsmod.Wrapf(ErrUnsuccessfulTx, "code = %d; %s", txRes.Code, txRes.RawLog) + } } break }