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
This commit is contained in:
Robert Pirtle 2023-08-02 14:52:48 -07:00 committed by GitHub
parent 667b6d084e
commit 839dc80205
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 87 additions and 50 deletions

View File

@ -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 is the tag of the docker image the chain should upgrade from.
E2E_KAVA_UPGRADE_BASE_IMAGE_TAG= E2E_KAVA_UPGRADE_BASE_IMAGE_TAG=
# E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token. # E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token with the following properties:
# The E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC account must have a balance. # - the E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC has nonzero balance
# The ERC20 must be enabled via x/evmutil params for conversion to sdk.Coin. # - 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. # - 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 E2E_KAVA_ERC20_ADDRESS=0xeA7100edA2f805356291B0E55DaD448599a72C6d

View File

@ -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 is not currently supported for running tests against a live network.
E2E_INCLUDE_IBC_TESTS=false E2E_INCLUDE_IBC_TESTS=false
# E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token. # E2E_KAVA_ERC20_ADDRESS is the address of a pre-deployed ERC20 token with the following properties:
# The E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC account must have a balance. # - the E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC has nonzero balance
# The ERC20 must be enabled via x/evmutil params for conversion to sdk.Coin. # - 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. # - 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 E2E_KAVA_ERC20_ADDRESS=0xeA7100edA2f805356291B0E55DaD448599a72C6d

View File

@ -11,7 +11,7 @@ import (
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/kava-labs/kava/app" "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" evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
"github.com/kava-labs/kava/tests/e2e/contracts/greeter" "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) suite.Equal(sdk.NewInt(1e3), balRes.Balance.Amount)
} }
// Note that this test works because the deployed erc20 is configured in evmutil & earn params. // Note that this test works because the deployed erc20 is configured in evmutil & cdp params.
func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() { // This test matches the webapp's "USDT Earn" workflow
amount := sdk.NewInt(1e2) // 0.0002 USDC 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 sdkDenom := suite.DeployedErc20.CosmosDenom
// create new funded account // 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 // give them erc20 balance to deposit
fundRes := suite.FundKavaErc20Balance(depositor.EvmAddress, amount.BigInt()) fundRes := suite.FundKavaErc20Balance(depositor.EvmAddress, amount.BigInt())
suite.NoError(fundRes.Err) suite.NoError(fundRes.Err)
@ -124,16 +127,17 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
evmutiltypes.NewInternalEVMAddress(suite.DeployedErc20.Address), evmutiltypes.NewInternalEVMAddress(suite.DeployedErc20.Address),
amount, amount,
) )
depositMsg := earntypes.NewMsgDeposit( depositMsg := cdptypes.NewMsgCreateCDP(
depositor.SdkAddress.String(), depositor.SdkAddress,
sdk.NewCoin(sdkDenom, amount), sdk.NewCoin(sdkDenom, amount),
earntypes.STRATEGY_TYPE_SAVINGS, principal,
suite.DeployedErc20.CdpCollateralType,
) )
msgs := []sdk.Msg{ msgs := []sdk.Msg{
// convert to coin // convert to coin
&convertMsg, &convertMsg,
// deposit into earn // deposit into cdp (Mint), take out USDX
depositMsg, &depositMsg,
} }
// create tx // create tx
@ -143,7 +147,7 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
1e6, 1e6,
sdk.NewCoins(ukava(1e4)), sdk.NewCoins(ukava(1e4)),
msgs, msgs,
"depositing my USDC into Earn!", "doing the USDT Earn workflow! erc20 -> sdk.Coin -> USDX hard deposit",
).GetTx() ).GetTx()
txBytes, err := suite.Kava.EncodingConfig.TxConfig.TxEncoder()(tx) txBytes, err := suite.Kava.EncodingConfig.TxConfig.TxEncoder()(tx)
@ -158,26 +162,26 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
suite.Equal(sdkerrors.SuccessABCICode, res.TxResponse.Code) suite.Equal(sdkerrors.SuccessABCICode, res.TxResponse.Code)
_, err = util.WaitForSdkTxCommit(suite.Kava.Tx, res.TxResponse.TxHash, 6*time.Second) _, 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 // check that depositor no longer has erc20 balance
balance := suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, depositor.EvmAddress) balance := suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, depositor.EvmAddress)
suite.BigIntsEqual(big.NewInt(0), balance, "expected no erc20 balance") suite.BigIntsEqual(big.NewInt(0), balance, "expected no erc20 balance")
// check that account has an earn deposit position // check that account has cdp
earnRes, err := suite.Kava.Earn.Deposits(context.Background(), &earntypes.QueryDepositsRequest{ cdpRes, err := suite.Kava.Cdp.Cdp(context.Background(), &cdptypes.QueryCdpRequest{
Depositor: depositor.SdkAddress.String(), CollateralType: suite.DeployedErc20.CdpCollateralType,
Denom: sdkDenom, Owner: depositor.SdkAddress.String(),
}) })
suite.NoError(err) suite.NoError(err)
suite.Len(earnRes.Deposits, 1) suite.True(cdpRes.Cdp.Collateral.Amount.Equal(amount))
suite.Equal(sdk.NewDecFromInt(amount), earnRes.Deposits[0].Shares.AmountOf(sdkDenom)) suite.True(cdpRes.Cdp.Principal.Equal(principal))
// withdraw deposit & convert back to erc20 (this allows refund to recover erc20s used in test) // withdraw deposit & convert back to erc20 (this allows refund to recover erc20s used in test)
withdraw := earntypes.NewMsgWithdraw( withdraw := cdptypes.NewMsgRepayDebt(
depositor.SdkAddress.String(), depositor.SdkAddress,
sdk.NewCoin(sdkDenom, amount), suite.DeployedErc20.CdpCollateralType,
earntypes.STRATEGY_TYPE_SAVINGS, principal,
) )
convertBack := evmutiltypes.NewMsgConvertCoinToERC20( convertBack := evmutiltypes.NewMsgConvertCoinToERC20(
depositor.SdkAddress.String(), depositor.SdkAddress.String(),
@ -185,11 +189,14 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
sdk.NewCoin(sdkDenom, amount), sdk.NewCoin(sdkDenom, amount),
) )
withdrawAndConvertBack := util.KavaMsgRequest{ withdrawAndConvertBack := util.KavaMsgRequest{
Msgs: []sdk.Msg{withdraw, &convertBack}, Msgs: []sdk.Msg{&withdraw, &convertBack},
GasLimit: 3e5, GasLimit: 1e6,
FeeAmount: sdk.NewCoins(ukava(300)), FeeAmount: sdk.NewCoins(ukava(1000)),
Data: "withdrawing from earn & converting back to erc20", Data: "withdrawing from mint & converting back to erc20",
} }
lastRes := depositor.SignAndBroadcastKavaTx(withdrawAndConvertBack) lastRes := depositor.SignAndBroadcastKavaTx(withdrawAndConvertBack)
suite.NoError(lastRes.Err) suite.NoError(lastRes.Err)
balance = suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, depositor.EvmAddress)
suite.BigIntsEqual(amount.BigInt(), balance, "expected returned erc20 balance")
} }

@ -1 +1 @@
Subproject commit 68f3a5ce9e688028ab66cecdb583223f03e153fc Subproject commit b093fc9f2a28cf57b4a6924f45919edcfe551eaf

View File

@ -9,20 +9,23 @@ import (
"os" "os"
"time" "time"
"github.com/stretchr/testify/require"
sdkmath "cosmossdk.io/math" sdkmath "cosmossdk.io/math"
"github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/crypto/types"
sdk "github.com/cosmos/cosmos-sdk/types" sdk "github.com/cosmos/cosmos-sdk/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/cosmos/go-bip39" "github.com/cosmos/go-bip39"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types" ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/evmos/ethermint/crypto/ethsecp256k1" "github.com/evmos/ethermint/crypto/ethsecp256k1"
emtests "github.com/evmos/ethermint/tests" emtests "github.com/evmos/ethermint/tests"
emtypes "github.com/evmos/ethermint/types" emtypes "github.com/evmos/ethermint/types"
"github.com/stretchr/testify/require"
"github.com/kava-labs/kava/app" "github.com/kava-labs/kava/app"
"github.com/kava-labs/kava/tests/util" "github.com/kava-labs/kava/tests/util"
@ -207,9 +210,15 @@ func (chain *Chain) NewFundedAccount(name string, funds sdk.Coins) *SigningAccou
return acc return acc
} }
// TODO: verify whale has funds.
whale := chain.GetAccount(FundedAccountName) 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()) whale.l.Printf("attempting to fund created account (%s=%s)\n", name, acc.SdkAddress.String())
res := whale.BankSend(acc.SdkAddress, funds) res := whale.BankSend(acc.SdkAddress, funds)

View File

@ -26,6 +26,7 @@ import (
kavaparams "github.com/kava-labs/kava/app/params" kavaparams "github.com/kava-labs/kava/app/params"
"github.com/kava-labs/kava/tests/e2e/runner" "github.com/kava-labs/kava/tests/e2e/runner"
"github.com/kava-labs/kava/tests/util" "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" committeetypes "github.com/kava-labs/kava/x/committee/types"
communitytypes "github.com/kava-labs/kava/x/community/types" communitytypes "github.com/kava-labs/kava/x/community/types"
earntypes "github.com/kava-labs/kava/x/earn/types" earntypes "github.com/kava-labs/kava/x/earn/types"
@ -48,6 +49,7 @@ type Chain struct {
Auth authtypes.QueryClient Auth authtypes.QueryClient
Bank banktypes.QueryClient Bank banktypes.QueryClient
Cdp cdptypes.QueryClient
Committee committeetypes.QueryClient Committee committeetypes.QueryClient
Community communitytypes.QueryClient Community communitytypes.QueryClient
Earn earntypes.QueryClient Earn earntypes.QueryClient
@ -83,6 +85,7 @@ func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic
chain.Auth = authtypes.NewQueryClient(grpcConn) chain.Auth = authtypes.NewQueryClient(grpcConn)
chain.Bank = banktypes.NewQueryClient(grpcConn) chain.Bank = banktypes.NewQueryClient(grpcConn)
chain.Cdp = cdptypes.NewQueryClient(grpcConn)
chain.Committee = committeetypes.NewQueryClient(grpcConn) chain.Committee = committeetypes.NewQueryClient(grpcConn)
chain.Community = communitytypes.NewQueryClient(grpcConn) chain.Community = communitytypes.NewQueryClient(grpcConn)
chain.Earn = earntypes.NewQueryClient(grpcConn) chain.Earn = earntypes.NewQueryClient(grpcConn)

View File

@ -8,7 +8,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/kava-labs/kava/tests/e2e/contracts/greeter" "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" evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
) )
@ -41,13 +41,21 @@ func (suite *E2eTestSuite) InitKavaEvmData() {
} }
suite.Kava.RegisterErc20(suite.DeployedErc20.Address) suite.Kava.RegisterErc20(suite.DeployedErc20.Address)
// expect the erc20's cosmos denom to be a supported earn vault // expect the erc20's cosmos denom to be a supported cdp collateral type
_, err = suite.Kava.Earn.Vault( cdpParams, err := suite.Kava.Cdp.Params(context.Background(), &types.QueryParamsRequest{})
context.Background(), suite.Require().NoError(err)
types.NewQueryVaultRequest(suite.DeployedErc20.CosmosDenom), 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),
) )
if err != nil {
panic(fmt.Sprintf("failed to find earn vault with denom %s: %s", suite.DeployedErc20.CosmosDenom, err))
} }
// deploy an example contract // deploy an example contract

View File

@ -33,11 +33,13 @@ const (
// The tests expect the following: // The tests expect the following:
// - the funded account has a nonzero balance of the erc20 // - the funded account has a nonzero balance of the erc20
// - the erc20 is enabled for conversion to sdk.Coin // - 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(). // These requirements are checked in InitKavaEvmData().
type DeployedErc20 struct { type DeployedErc20 struct {
Address common.Address Address common.Address
CosmosDenom string CosmosDenom string
CdpCollateralType string
} }
// E2eTestSuite is a testify test suite for running end-to-end integration tests on Kava. // 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.config = suiteConfig
suite.DeployedErc20 = DeployedErc20{ suite.DeployedErc20 = DeployedErc20{
Address: common.HexToAddress(suiteConfig.KavaErc20Address), Address: common.HexToAddress(suiteConfig.KavaErc20Address),
// Denom is fetched in InitKavaEvmData() // Denom & CdpCollateralType are fetched in InitKavaEvmData()
} }
// setup the correct NodeRunner for the given config // 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) suite.cost.erc20BalanceAfter = suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, whale.EvmAddress)
fmt.Println(suite.cost) fmt.Println(suite.cost)
// TODO: track asset denoms & then return all funds to initial funding account.
// close all account request channels // close all account request channels
suite.Kava.Shutdown() suite.Kava.Shutdown()
if suite.Ibc != nil { if suite.Ibc != nil {

View File

@ -24,6 +24,7 @@ import (
var ( var (
ErrSdkBroadcastTimeout = errors.New("timed out waiting for tx to be committed to block") 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 { type KavaMsgRequest struct {
@ -454,6 +455,9 @@ func WaitForSdkTxCommit(txClient txtypes.ServiceClient, txHash string, timeout t
break break
} }
txRes = res.TxResponse txRes = res.TxResponse
if err == nil && txRes.Code != uint32(codes.OK) {
err = errorsmod.Wrapf(ErrUnsuccessfulTx, "code = %d; %s", txRes.Code, txRes.RawLog)
}
} }
break break
} }