mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-26 00:05:18 +00:00
test(e2e): support running against live networks (#1630)
* add NodeRunner impl for connecting to live network * refactor out node runner setups * remove hardcoded denom for DeployedErc20 * further specify restrictions on DeployedErc20 * don't override .env funded account mnemonic * lower amounts for convert to coin e2e tests * lower fund values used by e2e tests * add doc comments for all e2e functions & types
This commit is contained in:
parent
336bac7466
commit
7cff7bec23
1
Makefile
1
Makefile
@ -294,7 +294,6 @@ test-basic: test
|
|||||||
|
|
||||||
# run end-to-end tests (local docker container must be built, see docker-build)
|
# run end-to-end tests (local docker container must be built, see docker-build)
|
||||||
test-e2e: docker-build
|
test-e2e: docker-build
|
||||||
export E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC='tent fitness boat among census primary pipe nose dream glance cave turtle electric fabric jacket shaft easy myself genuine this sibling pulse word unfold'; \
|
|
||||||
go test -failfast -count=1 -v ./tests/e2e/...
|
go test -failfast -count=1 -v ./tests/e2e/...
|
||||||
|
|
||||||
test:
|
test:
|
||||||
|
@ -29,5 +29,7 @@ E2E_KAVA_UPGRADE_HEIGHT=
|
|||||||
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.
|
||||||
# The E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC account should have a balance.
|
# 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=0xeA7100edA2f805356291B0E55DaD448599a72C6d
|
E2E_KAVA_ERC20_ADDRESS=0xeA7100edA2f805356291B0E55DaD448599a72C6d
|
||||||
|
20
tests/e2e/.env.live-network-example
Normal file
20
tests/e2e/.env.live-network-example
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC is for a funded account used to intialize all new testing accounts.
|
||||||
|
# Should be funded with KAVA and have an ERC20 balance
|
||||||
|
E2E_KAVA_FUNDED_ACCOUNT_MNEMONIC='tent fitness boat among census primary pipe nose dream glance cave turtle electric fabric jacket shaft easy myself genuine this sibling pulse word unfold'
|
||||||
|
|
||||||
|
# E2E_RUN_KVTOOL_NETWORKS must be false to trigger run on live network
|
||||||
|
E2E_RUN_KVTOOL_NETWORKS=false
|
||||||
|
|
||||||
|
# Configure the endpoints for connecting to the running network here.
|
||||||
|
E2E_KAVA_RPC_URL='http://localhost:26657'
|
||||||
|
E2E_KAVA_GRPC_URL='http://localhost:9090'
|
||||||
|
E2E_KAVA_EMV_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=0xeA7100edA2f805356291B0E55DaD448599a72C6d
|
@ -32,7 +32,7 @@ func setupConvertToCoinTest(
|
|||||||
denom = tokenInfo.CosmosDenom
|
denom = tokenInfo.CosmosDenom
|
||||||
initialFunds = sdk.NewCoins(
|
initialFunds = sdk.NewCoins(
|
||||||
sdk.NewInt64Coin(suite.Kava.StakingDenom, 1e6), // gas money
|
sdk.NewInt64Coin(suite.Kava.StakingDenom, 1e6), // gas money
|
||||||
sdk.NewInt64Coin(denom, 1e10), // conversion-enabled cosmos coin
|
sdk.NewInt64Coin(denom, 1e6), // conversion-enabled cosmos coin
|
||||||
)
|
)
|
||||||
|
|
||||||
user = suite.Kava.NewFundedAccount(accountName, initialFunds)
|
user = suite.Kava.NewFundedAccount(accountName, initialFunds)
|
||||||
@ -40,12 +40,12 @@ func setupConvertToCoinTest(
|
|||||||
return denom, initialFunds, user
|
return denom, initialFunds, user
|
||||||
}
|
}
|
||||||
|
|
||||||
// amount must be less than 1e10
|
// amount must be less than initial funds (1e6)
|
||||||
func (suite *IntegrationTestSuite) setupAccountWithCosmosCoinERC20Balance(
|
func (suite *IntegrationTestSuite) setupAccountWithCosmosCoinERC20Balance(
|
||||||
accountName string, amount int64,
|
accountName string, amount int64,
|
||||||
) (user *testutil.SigningAccount, contractAddress *evmutiltypes.InternalEVMAddress, denom string, sdkBalance sdk.Coins) {
|
) (user *testutil.SigningAccount, contractAddress *evmutiltypes.InternalEVMAddress, denom string, sdkBalance sdk.Coins) {
|
||||||
if amount > 1e10 {
|
if amount > 1e6 {
|
||||||
panic("test erc20 amount must be less than 1e10")
|
panic("test erc20 amount must be less than 1e6")
|
||||||
}
|
}
|
||||||
|
|
||||||
denom, sdkBalance, user = setupConvertToCoinTest(suite, accountName)
|
denom, sdkBalance, user = setupConvertToCoinTest(suite, accountName)
|
||||||
@ -88,7 +88,7 @@ func (suite *IntegrationTestSuite) TestConvertCosmosCoinsToFromERC20() {
|
|||||||
denom, initialFunds, user := setupConvertToCoinTest(suite, "cosmo-coin-converter")
|
denom, initialFunds, user := setupConvertToCoinTest(suite, "cosmo-coin-converter")
|
||||||
|
|
||||||
fee := sdk.NewCoins(ukava(7500))
|
fee := sdk.NewCoins(ukava(7500))
|
||||||
convertAmount := int64(5e9)
|
convertAmount := int64(5e5)
|
||||||
initialModuleBalance := suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
|
initialModuleBalance := suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
@ -168,7 +168,7 @@ func (suite *IntegrationTestSuite) TestConvertCosmosCoinsToFromERC20() {
|
|||||||
func (suite *IntegrationTestSuite) TestEIP712ConvertCosmosCoinsToFromERC20() {
|
func (suite *IntegrationTestSuite) TestEIP712ConvertCosmosCoinsToFromERC20() {
|
||||||
denom, initialFunds, user := setupConvertToCoinTest(suite, "cosmo-coin-converter-eip712")
|
denom, initialFunds, user := setupConvertToCoinTest(suite, "cosmo-coin-converter-eip712")
|
||||||
|
|
||||||
convertAmount := int64(5e9)
|
convertAmount := int64(5e5)
|
||||||
initialModuleBalance := suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
|
initialModuleBalance := suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
@ -325,14 +325,14 @@ func (suite *IntegrationTestSuite) TestConvertCosmosCoins_ForbiddenERC20Calls()
|
|||||||
// - check complex conversion flow. bob converts funds they receive on evm back to sdk.Coin
|
// - check complex conversion flow. bob converts funds they receive on evm back to sdk.Coin
|
||||||
func (suite *IntegrationTestSuite) TestConvertCosmosCoins_ERC20Magic() {
|
func (suite *IntegrationTestSuite) TestConvertCosmosCoins_ERC20Magic() {
|
||||||
fee := sdk.NewCoins(ukava(7500))
|
fee := sdk.NewCoins(ukava(7500))
|
||||||
initialAliceAmount := int64(2e6)
|
initialAliceAmount := int64(2e5)
|
||||||
alice, contractAddress, denom, _ := suite.setupAccountWithCosmosCoinERC20Balance(
|
alice, contractAddress, denom, _ := suite.setupAccountWithCosmosCoinERC20Balance(
|
||||||
"cosmo-coin-converter-complex-alice", initialAliceAmount,
|
"cosmo-coin-converter-complex-alice", initialAliceAmount,
|
||||||
)
|
)
|
||||||
|
|
||||||
gasMoney := sdk.NewCoins(ukava(1e6))
|
gasMoney := sdk.NewCoins(ukava(1e6))
|
||||||
bob := suite.Kava.NewFundedAccount("cosmo-coin-converter-complex-bob", gasMoney)
|
bob := suite.Kava.NewFundedAccount("cosmo-coin-converter-complex-bob", gasMoney)
|
||||||
amount := big.NewInt(1e6)
|
amount := big.NewInt(1e5)
|
||||||
|
|
||||||
// bob can't move alice's funds
|
// bob can't move alice's funds
|
||||||
nonce, err := bob.NextNonce()
|
nonce, err := bob.NextNonce()
|
||||||
|
@ -22,7 +22,7 @@ func (suite *IntegrationTestSuite) TestEthCallToGreeterContract() {
|
|||||||
// this test manipulates state of the Greeter contract which means other tests shouldn't use it.
|
// this test manipulates state of the Greeter contract which means other tests shouldn't use it.
|
||||||
|
|
||||||
// setup funded account to interact with contract
|
// setup funded account to interact with contract
|
||||||
user := suite.Kava.NewFundedAccount("greeter-contract-user", sdk.NewCoins(ukava(10e6)))
|
user := suite.Kava.NewFundedAccount("greeter-contract-user", sdk.NewCoins(ukava(1e6)))
|
||||||
|
|
||||||
greeterAddr := suite.Kava.ContractAddrs["greeter"]
|
greeterAddr := suite.Kava.ContractAddrs["greeter"]
|
||||||
contract, err := greeter.NewGreeter(greeterAddr, suite.Kava.EvmClient)
|
contract, err := greeter.NewGreeter(greeterAddr, suite.Kava.EvmClient)
|
||||||
@ -47,17 +47,17 @@ func (suite *IntegrationTestSuite) TestEthCallToGreeterContract() {
|
|||||||
|
|
||||||
func (suite *IntegrationTestSuite) TestEthCallToErc20() {
|
func (suite *IntegrationTestSuite) TestEthCallToErc20() {
|
||||||
randoReceiver := util.SdkToEvmAddress(app.RandomAddress())
|
randoReceiver := util.SdkToEvmAddress(app.RandomAddress())
|
||||||
amount := big.NewInt(1e6)
|
amount := big.NewInt(1e3)
|
||||||
|
|
||||||
// make unauthenticated eth_call query to check balance
|
// make unauthenticated eth_call query to check balance
|
||||||
beforeBalance := suite.Kava.GetErc20Balance(suite.DeployedErc20Address, randoReceiver)
|
beforeBalance := suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, randoReceiver)
|
||||||
|
|
||||||
// make authenticate eth_call to transfer tokens
|
// make authenticate eth_call to transfer tokens
|
||||||
res := suite.FundKavaErc20Balance(randoReceiver, amount)
|
res := suite.FundKavaErc20Balance(randoReceiver, amount)
|
||||||
suite.NoError(res.Err)
|
suite.NoError(res.Err)
|
||||||
|
|
||||||
// make another unauthenticated eth_call query to check new balance
|
// make another unauthenticated eth_call query to check new balance
|
||||||
afterBalance := suite.Kava.GetErc20Balance(suite.DeployedErc20Address, randoReceiver)
|
afterBalance := suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, randoReceiver)
|
||||||
|
|
||||||
suite.BigIntsEqual(big.NewInt(0), beforeBalance, "expected before balance to be zero")
|
suite.BigIntsEqual(big.NewInt(0), beforeBalance, "expected before balance to be zero")
|
||||||
suite.BigIntsEqual(amount, afterBalance, "unexpected post-transfer balance")
|
suite.BigIntsEqual(amount, afterBalance, "unexpected post-transfer balance")
|
||||||
@ -65,12 +65,12 @@ func (suite *IntegrationTestSuite) TestEthCallToErc20() {
|
|||||||
|
|
||||||
func (suite *IntegrationTestSuite) TestEip712BasicMessageAuthorization() {
|
func (suite *IntegrationTestSuite) TestEip712BasicMessageAuthorization() {
|
||||||
// create new funded account
|
// create new funded account
|
||||||
sender := suite.Kava.NewFundedAccount("eip712-msgSend", sdk.NewCoins(ukava(10e6)))
|
sender := suite.Kava.NewFundedAccount("eip712-msgSend", sdk.NewCoins(ukava(2e4)))
|
||||||
receiver := app.RandomAddress()
|
receiver := app.RandomAddress()
|
||||||
|
|
||||||
// setup message for sending 1KAVA to random receiver
|
// setup message for sending some kava to random receiver
|
||||||
msgs := []sdk.Msg{
|
msgs := []sdk.Msg{
|
||||||
banktypes.NewMsgSend(sender.SdkAddress, receiver, sdk.NewCoins(ukava(1e6))),
|
banktypes.NewMsgSend(sender.SdkAddress, receiver, sdk.NewCoins(ukava(1e3))),
|
||||||
}
|
}
|
||||||
|
|
||||||
// create tx
|
// create tx
|
||||||
@ -103,16 +103,16 @@ func (suite *IntegrationTestSuite) TestEip712BasicMessageAuthorization() {
|
|||||||
Denom: "ukava",
|
Denom: "ukava",
|
||||||
})
|
})
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.Equal(sdk.NewInt(1e6), 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 & earn params.
|
||||||
func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
|
func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
|
||||||
amount := sdk.NewInt(10e6) // 10 USDC
|
amount := sdk.NewInt(1e4) // .04 USDC
|
||||||
sdkDenom := "erc20/multichain/usdc"
|
sdkDenom := suite.DeployedErc20.CosmosDenom
|
||||||
|
|
||||||
// create new funded account
|
// create new funded account
|
||||||
depositor := suite.Kava.NewFundedAccount("eip712-earn-depositor", sdk.NewCoins(ukava(1e6)))
|
depositor := suite.Kava.NewFundedAccount("eip712-earn-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)
|
||||||
@ -121,7 +121,7 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
|
|||||||
convertMsg := evmutiltypes.NewMsgConvertERC20ToCoin(
|
convertMsg := evmutiltypes.NewMsgConvertERC20ToCoin(
|
||||||
evmutiltypes.NewInternalEVMAddress(depositor.EvmAddress),
|
evmutiltypes.NewInternalEVMAddress(depositor.EvmAddress),
|
||||||
depositor.SdkAddress,
|
depositor.SdkAddress,
|
||||||
evmutiltypes.NewInternalEVMAddress(suite.DeployedErc20Address),
|
evmutiltypes.NewInternalEVMAddress(suite.DeployedErc20.Address),
|
||||||
amount,
|
amount,
|
||||||
)
|
)
|
||||||
depositMsg := earntypes.NewMsgDeposit(
|
depositMsg := earntypes.NewMsgDeposit(
|
||||||
@ -161,7 +161,7 @@ func (suite *IntegrationTestSuite) TestEip712ConvertToCoinAndDepositToEarn() {
|
|||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
// check that depositor no longer has erc20 balance
|
// check that depositor no longer has erc20 balance
|
||||||
balance := suite.Kava.GetErc20Balance(suite.DeployedErc20Address, 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 an earn deposit position
|
||||||
|
@ -33,7 +33,7 @@ func (suite *IntegrationTestSuite) TestEthGasPriceReturnsMinFee() {
|
|||||||
|
|
||||||
func (suite *IntegrationTestSuite) TestEvmRespectsMinFee() {
|
func (suite *IntegrationTestSuite) TestEvmRespectsMinFee() {
|
||||||
// setup sender & receiver
|
// setup sender & receiver
|
||||||
sender := suite.Kava.NewFundedAccount("evm-min-fee-test-sender", sdk.NewCoins(ukava(2e6)))
|
sender := suite.Kava.NewFundedAccount("evm-min-fee-test-sender", sdk.NewCoins(ukava(1e3)))
|
||||||
randoReceiver := util.SdkToEvmAddress(app.RandomAddress())
|
randoReceiver := util.SdkToEvmAddress(app.RandomAddress())
|
||||||
|
|
||||||
// get min gas price for evm (from app.toml)
|
// get min gas price for evm (from app.toml)
|
||||||
@ -44,7 +44,7 @@ func (suite *IntegrationTestSuite) TestEvmRespectsMinFee() {
|
|||||||
// attempt tx with less than min gas price (min fee - 1)
|
// attempt tx with less than min gas price (min fee - 1)
|
||||||
tooLowGasPrice := minGasPrice.Sub(sdk.OneInt()).BigInt()
|
tooLowGasPrice := minGasPrice.Sub(sdk.OneInt()).BigInt()
|
||||||
req := util.EvmTxRequest{
|
req := util.EvmTxRequest{
|
||||||
Tx: ethtypes.NewTransaction(0, randoReceiver, big.NewInt(1e6), 1e5, tooLowGasPrice, nil),
|
Tx: ethtypes.NewTransaction(0, randoReceiver, big.NewInt(5e2), 1e5, tooLowGasPrice, nil),
|
||||||
Data: "this tx should fail because it's gas price is too low",
|
Data: "this tx should fail because it's gas price is too low",
|
||||||
}
|
}
|
||||||
res := sender.SignAndBroadcastEvmTx(req)
|
res := sender.SignAndBroadcastEvmTx(req)
|
||||||
|
@ -80,7 +80,7 @@ func (suite *IntegrationTestSuite) TestFundedAccount() {
|
|||||||
// example test that signs & broadcasts an EVM tx
|
// example test that signs & broadcasts an EVM tx
|
||||||
func (suite *IntegrationTestSuite) TestTransferOverEVM() {
|
func (suite *IntegrationTestSuite) TestTransferOverEVM() {
|
||||||
// fund an account that can perform the transfer
|
// fund an account that can perform the transfer
|
||||||
initialFunds := ukava(1e7) // 10 KAVA
|
initialFunds := ukava(1e6) // 1 KAVA
|
||||||
acc := suite.Kava.NewFundedAccount("evm-test-transfer", sdk.NewCoins(initialFunds))
|
acc := suite.Kava.NewFundedAccount("evm-test-transfer", sdk.NewCoins(initialFunds))
|
||||||
|
|
||||||
// get a rando account to send kava to
|
// get a rando account to send kava to
|
||||||
@ -93,7 +93,7 @@ func (suite *IntegrationTestSuite) TestTransferOverEVM() {
|
|||||||
suite.Equal(uint64(0), nonce) // sanity check. the account should have no prior txs
|
suite.Equal(uint64(0), nonce) // sanity check. the account should have no prior txs
|
||||||
|
|
||||||
// transfer kava over EVM
|
// transfer kava over EVM
|
||||||
kavaToTransfer := big.NewInt(1e18) // 1 KAVA; akava has 18 decimals.
|
kavaToTransfer := big.NewInt(1e17) // .1 KAVA; akava has 18 decimals.
|
||||||
req := util.EvmTxRequest{
|
req := util.EvmTxRequest{
|
||||||
Tx: ethtypes.NewTransaction(nonce, to, kavaToTransfer, 1e5, minEvmGasPrice, nil),
|
Tx: ethtypes.NewTransaction(nonce, to, kavaToTransfer, 1e5, minEvmGasPrice, nil),
|
||||||
Data: "any ol' data to track this through the system",
|
Data: "any ol' data to track this through the system",
|
||||||
@ -109,7 +109,7 @@ func (suite *IntegrationTestSuite) TestTransferOverEVM() {
|
|||||||
|
|
||||||
// expect (9 - gas used) KAVA remaining in account.
|
// expect (9 - gas used) KAVA remaining in account.
|
||||||
balance := suite.Kava.QuerySdkForBalances(acc.SdkAddress)
|
balance := suite.Kava.QuerySdkForBalances(acc.SdkAddress)
|
||||||
suite.Equal(sdkmath.NewInt(9e6).Sub(ukavaUsedForGas), balance.AmountOf("ukava"))
|
suite.Equal(sdkmath.NewInt(9e5).Sub(ukavaUsedForGas), balance.AmountOf("ukava"))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestIbcTransfer transfers KAVA from the primary kava chain (suite.Kava) to the ibc chain (suite.Ibc).
|
// TestIbcTransfer transfers KAVA from the primary kava chain (suite.Kava) to the ibc chain (suite.Ibc).
|
||||||
@ -119,7 +119,7 @@ func (suite *IntegrationTestSuite) TestIbcTransfer() {
|
|||||||
|
|
||||||
// ARRANGE
|
// ARRANGE
|
||||||
// setup kava account
|
// setup kava account
|
||||||
funds := ukava(1e7) // 10 KAVA
|
funds := ukava(1e5) // .1 KAVA
|
||||||
kavaAcc := suite.Kava.NewFundedAccount("ibc-transfer-kava-side", sdk.NewCoins(funds))
|
kavaAcc := suite.Kava.NewFundedAccount("ibc-transfer-kava-side", sdk.NewCoins(funds))
|
||||||
// setup ibc account
|
// setup ibc account
|
||||||
ibcAcc := suite.Ibc.NewFundedAccount("ibc-transfer-ibc-side", sdk.NewCoins())
|
ibcAcc := suite.Ibc.NewFundedAccount("ibc-transfer-ibc-side", sdk.NewCoins())
|
||||||
@ -127,7 +127,7 @@ func (suite *IntegrationTestSuite) TestIbcTransfer() {
|
|||||||
gasLimit := int64(2e5)
|
gasLimit := int64(2e5)
|
||||||
fee := ukava(7500)
|
fee := ukava(7500)
|
||||||
|
|
||||||
fundsToSend := ukava(5e6) // 5 KAVA
|
fundsToSend := ukava(5e4) // .005 KAVA
|
||||||
transferMsg := ibctypes.NewMsgTransfer(
|
transferMsg := ibctypes.NewMsgTransfer(
|
||||||
testutil.IbcPort,
|
testutil.IbcPort,
|
||||||
testutil.IbcChannel,
|
testutil.IbcChannel,
|
||||||
|
@ -24,22 +24,30 @@ type ChainDetails struct {
|
|||||||
StakingDenom string
|
StakingDenom string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EvmClient dials the underlying EVM RPC url and returns an ethclient.
|
||||||
func (c ChainDetails) EvmClient() (*ethclient.Client, error) {
|
func (c ChainDetails) EvmClient() (*ethclient.Client, error) {
|
||||||
return ethclient.Dial(c.EvmRpcUrl)
|
return ethclient.Dial(c.EvmRpcUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GrpcConn creates a new connection to the underlying Grpc url.
|
||||||
func (c ChainDetails) GrpcConn() (*grpc.ClientConn, error) {
|
func (c ChainDetails) GrpcConn() (*grpc.ClientConn, error) {
|
||||||
return util.NewGrpcConnection(c.GrpcUrl)
|
return util.NewGrpcConnection(c.GrpcUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Chains wraps a map of name -> details about how to connect to a chain.
|
||||||
|
// It prevents registering multiple chains with the same name & encapsulates
|
||||||
|
// panicking if attempting to access a chain that does not exist.
|
||||||
type Chains struct {
|
type Chains struct {
|
||||||
byName map[string]*ChainDetails
|
byName map[string]*ChainDetails
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewChains creates an empty Chains map.
|
||||||
func NewChains() Chains {
|
func NewChains() Chains {
|
||||||
return Chains{byName: make(map[string]*ChainDetails, 0)}
|
return Chains{byName: make(map[string]*ChainDetails, 0)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MustGetChain returns the chain of a given name,
|
||||||
|
// or panics if a chain with that name has not been registered.
|
||||||
func (c Chains) MustGetChain(name string) *ChainDetails {
|
func (c Chains) MustGetChain(name string) *ChainDetails {
|
||||||
chain, found := c.byName[name]
|
chain, found := c.byName[name]
|
||||||
if !found {
|
if !found {
|
||||||
@ -48,6 +56,8 @@ func (c Chains) MustGetChain(name string) *ChainDetails {
|
|||||||
return chain
|
return chain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register adds a chain to the map.
|
||||||
|
// It returns an error if a ChainDetails with that name has already been registered.
|
||||||
func (c *Chains) Register(name string, chain *ChainDetails) error {
|
func (c *Chains) Register(name string, chain *ChainDetails) error {
|
||||||
if _, found := c.byName[name]; found {
|
if _, found := c.byName[name]; found {
|
||||||
return ErrChainAlreadyExists
|
return ErrChainAlreadyExists
|
||||||
|
@ -32,12 +32,15 @@ type KvtoolRunner struct {
|
|||||||
|
|
||||||
var _ NodeRunner = &KvtoolRunner{}
|
var _ NodeRunner = &KvtoolRunner{}
|
||||||
|
|
||||||
|
// NewKvtoolRunner creates a new KvtoolRunner.
|
||||||
func NewKvtoolRunner(config KvtoolRunnerConfig) *KvtoolRunner {
|
func NewKvtoolRunner(config KvtoolRunnerConfig) *KvtoolRunner {
|
||||||
return &KvtoolRunner{
|
return &KvtoolRunner{
|
||||||
config: config,
|
config: config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StartChains implements NodeRunner.
|
||||||
|
// For KvtoolRunner, it sets up, runs, and connects to a local chain via kvtool.
|
||||||
func (k *KvtoolRunner) StartChains() Chains {
|
func (k *KvtoolRunner) StartChains() Chains {
|
||||||
// install kvtool if not already installed
|
// install kvtool if not already installed
|
||||||
installKvtoolCmd := exec.Command("./scripts/install-kvtool.sh")
|
installKvtoolCmd := exec.Command("./scripts/install-kvtool.sh")
|
||||||
@ -89,6 +92,10 @@ func (k *KvtoolRunner) StartChains() Chains {
|
|||||||
return chains
|
return chains
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shutdown implements NodeRunner.
|
||||||
|
// For KvtoolRunner, it shuts down the local kvtool network.
|
||||||
|
// To prevent shutting down the chain (eg. to preserve logs or examine post-test state)
|
||||||
|
// use the `SkipShutdown` option on the config.
|
||||||
func (k *KvtoolRunner) Shutdown() {
|
func (k *KvtoolRunner) Shutdown() {
|
||||||
if k.config.SkipShutdown {
|
if k.config.SkipShutdown {
|
||||||
log.Printf("would shut down but SkipShutdown is true")
|
log.Printf("would shut down but SkipShutdown is true")
|
||||||
|
80
tests/e2e/runner/live.go
Normal file
80
tests/e2e/runner/live.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package runner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/cosmos/cosmos-sdk/client/grpc/tmservice"
|
||||||
|
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LiveNodeRunnerConfig implements NodeRunner.
|
||||||
|
// It connects to a running network via the RPC, GRPC, and EVM urls.
|
||||||
|
type LiveNodeRunnerConfig struct {
|
||||||
|
KavaRpcUrl string
|
||||||
|
KavaGrpcUrl string
|
||||||
|
KavaEvmRpcUrl string
|
||||||
|
}
|
||||||
|
|
||||||
|
// LiveNodeRunner implements NodeRunner for an already-running chain.
|
||||||
|
// If a LiveNodeRunner is used, end-to-end tests are run against a live chain.
|
||||||
|
type LiveNodeRunner struct {
|
||||||
|
config LiveNodeRunnerConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ NodeRunner = LiveNodeRunner{}
|
||||||
|
|
||||||
|
// NewLiveNodeRunner creates a new LiveNodeRunner.
|
||||||
|
func NewLiveNodeRunner(config LiveNodeRunnerConfig) *LiveNodeRunner {
|
||||||
|
return &LiveNodeRunner{config}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StartChains implements NodeRunner.
|
||||||
|
// It initializes connections to the chain based on parameters.
|
||||||
|
// It attempts to ping the necessary endpoints and panics if they cannot be reached.
|
||||||
|
func (r LiveNodeRunner) StartChains() Chains {
|
||||||
|
fmt.Println("establishing connection to live kava network")
|
||||||
|
chains := NewChains()
|
||||||
|
|
||||||
|
kavaChain := ChainDetails{
|
||||||
|
RpcUrl: r.config.KavaRpcUrl,
|
||||||
|
GrpcUrl: r.config.KavaGrpcUrl,
|
||||||
|
EvmRpcUrl: r.config.KavaEvmRpcUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := waitForChainStart(kavaChain); err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to ping chain: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// determine chain id
|
||||||
|
grpc, err := kavaChain.GrpcConn()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to establish grpc conn to %s: %s", r.config.KavaGrpcUrl, err))
|
||||||
|
}
|
||||||
|
tm := tmservice.NewServiceClient(grpc)
|
||||||
|
nodeInfo, err := tm.GetNodeInfo(context.Background(), &tmservice.GetNodeInfoRequest{})
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to fetch kava node info: %s", err))
|
||||||
|
}
|
||||||
|
kavaChain.ChainId = nodeInfo.DefaultNodeInfo.Network
|
||||||
|
|
||||||
|
// determine staking denom
|
||||||
|
staking := stakingtypes.NewQueryClient(grpc)
|
||||||
|
stakingParams, err := staking.Params(context.Background(), &stakingtypes.QueryParamsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to fetch kava staking params: %s", err))
|
||||||
|
}
|
||||||
|
kavaChain.StakingDenom = stakingParams.Params.BondDenom
|
||||||
|
|
||||||
|
chains.Register("kava", &kavaChain)
|
||||||
|
|
||||||
|
fmt.Printf("successfully connected to live network %+v\n", kavaChain)
|
||||||
|
|
||||||
|
return chains
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown implements NodeRunner.
|
||||||
|
// As the chains are externally operated, this is a no-op.
|
||||||
|
func (LiveNodeRunner) Shutdown() {
|
||||||
|
fmt.Println("shutting down e2e test connections.")
|
||||||
|
}
|
@ -15,26 +15,28 @@ type NodeRunner interface {
|
|||||||
Shutdown()
|
Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waitForChainStart sets a timeout and repeatedly pings the chains.
|
||||||
|
// If the chain is successfully reached before the timeout, this returns no error.
|
||||||
func waitForChainStart(chainDetails ChainDetails) error {
|
func waitForChainStart(chainDetails ChainDetails) error {
|
||||||
// exponential backoff on trying to ping the node, timeout after 30 seconds
|
// exponential backoff on trying to ping the node, timeout after 30 seconds
|
||||||
b := backoff.NewExponentialBackOff()
|
b := backoff.NewExponentialBackOff()
|
||||||
b.MaxInterval = 5 * time.Second
|
b.MaxInterval = 5 * time.Second
|
||||||
b.MaxElapsedTime = 30 * time.Second
|
b.MaxElapsedTime = 30 * time.Second
|
||||||
if err := backoff.Retry(func() error { return pingKava(chainDetails.RpcUrl) }, b); err != nil {
|
if err := backoff.Retry(func() error { return pingKava(chainDetails.RpcUrl) }, b); err != nil {
|
||||||
return fmt.Errorf("failed to start & connect to chain: %s", err)
|
return fmt.Errorf("failed connect to chain: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
b.Reset()
|
b.Reset()
|
||||||
// the evm takes a bit longer to start up. wait for it to start as well.
|
// the evm takes a bit longer to start up. wait for it to start as well.
|
||||||
if err := backoff.Retry(func() error { return pingEvm(chainDetails.EvmRpcUrl) }, b); err != nil {
|
if err := backoff.Retry(func() error { return pingEvm(chainDetails.EvmRpcUrl) }, b); err != nil {
|
||||||
return fmt.Errorf("failed to start & connect to chain: %s", err)
|
return fmt.Errorf("failed connect to chain: %s", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func pingKava(rpcUrl string) error {
|
func pingKava(rpcUrl string) error {
|
||||||
log.Println("pinging kava chain...")
|
|
||||||
statusUrl := fmt.Sprintf("%s/status", rpcUrl)
|
statusUrl := fmt.Sprintf("%s/status", rpcUrl)
|
||||||
|
log.Printf("pinging kava chain: %s\n", statusUrl)
|
||||||
res, err := http.Get(statusUrl)
|
res, err := http.Get(statusUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -27,6 +27,8 @@ import (
|
|||||||
"github.com/kava-labs/kava/tests/util"
|
"github.com/kava-labs/kava/tests/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SigningAccount wraps details about an account and its private keys.
|
||||||
|
// It exposes functionality for signing and broadcasting transactions.
|
||||||
type SigningAccount struct {
|
type SigningAccount struct {
|
||||||
name string
|
name string
|
||||||
mnemonic string
|
mnemonic string
|
||||||
@ -173,6 +175,8 @@ func (a *SigningAccount) SignAndBroadcastEvmTx(req util.EvmTxRequest) EvmTxRespo
|
|||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignRawEvmData signs raw evm data with the SigningAccount's private key.
|
||||||
|
// It does not broadcast the signed data.
|
||||||
func (a *SigningAccount) SignRawEvmData(msg []byte) ([]byte, types.PubKey, error) {
|
func (a *SigningAccount) SignRawEvmData(msg []byte) ([]byte, types.PubKey, error) {
|
||||||
keyringSigner := emtests.NewSigner(a.evmPrivKey)
|
keyringSigner := emtests.NewSigner(a.evmPrivKey)
|
||||||
return keyringSigner.SignByAddress(a.SdkAddress, msg)
|
return keyringSigner.SignByAddress(a.SdkAddress, msg)
|
||||||
|
@ -133,6 +133,7 @@ func (chain *Chain) GetModuleBalances(moduleName string) sdk.Coins {
|
|||||||
return chain.QuerySdkForBalances(addr)
|
return chain.QuerySdkForBalances(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetErc20Balance fetches the ERC20 balance of `contract` for `address`.
|
||||||
func (chain *Chain) GetErc20Balance(contract, address common.Address) *big.Int {
|
func (chain *Chain) GetErc20Balance(contract, address common.Address) *big.Int {
|
||||||
resData, err := chain.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
|
resData, err := chain.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
|
||||||
To: &contract,
|
To: &contract,
|
||||||
|
@ -13,12 +13,15 @@ func init() {
|
|||||||
gotenv.Load()
|
gotenv.Load()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SuiteConfig wraps configuration details for running the end-to-end test suite.
|
||||||
type SuiteConfig struct {
|
type SuiteConfig struct {
|
||||||
// A funded account used to fnd all other accounts.
|
// A funded account used to fnd all other accounts.
|
||||||
FundedAccountMnemonic string
|
FundedAccountMnemonic string
|
||||||
|
|
||||||
// A config for using kvtool local networks for the test run
|
// A config for using kvtool local networks for the test run
|
||||||
Kvtool *KvtoolConfig
|
Kvtool *KvtoolConfig
|
||||||
|
// A config for connecting to a running network
|
||||||
|
LiveNetwork *LiveNetworkConfig
|
||||||
|
|
||||||
// Whether or not to start an IBC chain. Use `suite.SkipIfIbcDisabled()` in IBC tests in IBC tests.
|
// Whether or not to start an IBC chain. Use `suite.SkipIfIbcDisabled()` in IBC tests in IBC tests.
|
||||||
IncludeIbcTests bool
|
IncludeIbcTests bool
|
||||||
@ -30,6 +33,8 @@ type SuiteConfig struct {
|
|||||||
SkipShutdown bool
|
SkipShutdown bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KvtoolConfig wraps configuration options for running the end-to-end test suite against
|
||||||
|
// a locally running chain. This config must be defined if E2E_RUN_KVTOOL_NETWORKS is true.
|
||||||
type KvtoolConfig struct {
|
type KvtoolConfig struct {
|
||||||
// The kava.configTemplate flag to be passed to kvtool, usually "master".
|
// The kava.configTemplate flag to be passed to kvtool, usually "master".
|
||||||
// This allows one to change the base genesis used to start the chain.
|
// This allows one to change the base genesis used to start the chain.
|
||||||
@ -45,6 +50,15 @@ type KvtoolConfig struct {
|
|||||||
KavaUpgradeBaseImageTag string
|
KavaUpgradeBaseImageTag string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LiveNetworkConfig wraps configuration options for running the end-to-end test suite
|
||||||
|
// against a live network. It must be defined if E2E_RUN_KVTOOL_NETWORKS is false.
|
||||||
|
type LiveNetworkConfig struct {
|
||||||
|
KavaRpcUrl string
|
||||||
|
KavaGrpcUrl string
|
||||||
|
KavaEvmRpcUrl string
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseSuiteConfig builds a SuiteConfig from environment variables.
|
||||||
func ParseSuiteConfig() SuiteConfig {
|
func ParseSuiteConfig() SuiteConfig {
|
||||||
config := SuiteConfig{
|
config := SuiteConfig{
|
||||||
// this mnemonic is expected to be a funded account that can seed the funds for all
|
// this mnemonic is expected to be a funded account that can seed the funds for all
|
||||||
@ -63,11 +77,15 @@ func ParseSuiteConfig() SuiteConfig {
|
|||||||
if useKvtoolNetworks {
|
if useKvtoolNetworks {
|
||||||
kvtoolConfig := ParseKvtoolConfig()
|
kvtoolConfig := ParseKvtoolConfig()
|
||||||
config.Kvtool = &kvtoolConfig
|
config.Kvtool = &kvtoolConfig
|
||||||
|
} else {
|
||||||
|
liveNetworkConfig := ParseLiveNetworkConfig()
|
||||||
|
config.LiveNetwork = &liveNetworkConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseKvtoolConfig builds a KvtoolConfig from environment variables.
|
||||||
func ParseKvtoolConfig() KvtoolConfig {
|
func ParseKvtoolConfig() KvtoolConfig {
|
||||||
config := KvtoolConfig{
|
config := KvtoolConfig{
|
||||||
KavaConfigTemplate: nonemptyStringEnv("E2E_KVTOOL_KAVA_CONFIG_TEMPLATE"),
|
KavaConfigTemplate: nonemptyStringEnv("E2E_KVTOOL_KAVA_CONFIG_TEMPLATE"),
|
||||||
@ -87,6 +105,17 @@ func ParseKvtoolConfig() KvtoolConfig {
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseLiveNetworkConfig builds a LiveNetworkConfig from environment variables.
|
||||||
|
func ParseLiveNetworkConfig() LiveNetworkConfig {
|
||||||
|
return LiveNetworkConfig{
|
||||||
|
KavaRpcUrl: nonemptyStringEnv("E2E_KAVA_RPC_URL"),
|
||||||
|
KavaGrpcUrl: nonemptyStringEnv("E2E_KAVA_GRPC_URL"),
|
||||||
|
KavaEvmRpcUrl: nonemptyStringEnv("E2E_KAVA_EMV_RPC_URL"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mustParseBool is a helper method that panics if the env variable `name`
|
||||||
|
// cannot be parsed to a boolean
|
||||||
func mustParseBool(name string) bool {
|
func mustParseBool(name string) bool {
|
||||||
envValue := os.Getenv(name)
|
envValue := os.Getenv(name)
|
||||||
if envValue == "" {
|
if envValue == "" {
|
||||||
@ -99,6 +128,8 @@ func mustParseBool(name string) bool {
|
|||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nonemptyStringEnv is a helper method that panics if the env variable `name`
|
||||||
|
// is empty or undefined.
|
||||||
func nonemptyStringEnv(name string) string {
|
func nonemptyStringEnv(name string) string {
|
||||||
value := os.Getenv(name)
|
value := os.Getenv(name)
|
||||||
if value == "" {
|
if value == "" {
|
||||||
|
@ -16,6 +16,8 @@ import (
|
|||||||
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
evmtypes "github.com/evmos/ethermint/x/evm/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NewEip712TxBuilder is a helper method for creating an EIP712 signed tx
|
||||||
|
// A tx like this is what a user signing cosmos messages with Metamask would broadcast.
|
||||||
func (suite *E2eTestSuite) NewEip712TxBuilder(
|
func (suite *E2eTestSuite) NewEip712TxBuilder(
|
||||||
acc *SigningAccount, chain *Chain, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg, memo string,
|
acc *SigningAccount, chain *Chain, gas uint64, gasAmount sdk.Coins, msgs []sdk.Msg, memo string,
|
||||||
) client.TxBuilder {
|
) client.TxBuilder {
|
||||||
|
@ -10,6 +10,8 @@ import (
|
|||||||
|
|
||||||
"github.com/kava-labs/kava/tests/e2e/contracts/greeter"
|
"github.com/kava-labs/kava/tests/e2e/contracts/greeter"
|
||||||
"github.com/kava-labs/kava/tests/util"
|
"github.com/kava-labs/kava/tests/util"
|
||||||
|
"github.com/kava-labs/kava/x/earn/types"
|
||||||
|
evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// InitKavaEvmData is run after the chain is running, but before the tests are run.
|
// InitKavaEvmData is run after the chain is running, but before the tests are run.
|
||||||
@ -18,11 +20,37 @@ func (suite *E2eTestSuite) InitKavaEvmData() {
|
|||||||
whale := suite.Kava.GetAccount(FundedAccountName)
|
whale := suite.Kava.GetAccount(FundedAccountName)
|
||||||
|
|
||||||
// ensure funded account has nonzero erc20 balance
|
// ensure funded account has nonzero erc20 balance
|
||||||
balance := suite.Kava.GetErc20Balance(suite.DeployedErc20Address, whale.EvmAddress)
|
balance := suite.Kava.GetErc20Balance(suite.DeployedErc20.Address, whale.EvmAddress)
|
||||||
if balance.Cmp(big.NewInt(0)) != 1 {
|
if balance.Cmp(big.NewInt(0)) != 1 {
|
||||||
panic(fmt.Sprintf("expected funded account (%s) to have erc20 balance", whale.EvmAddress.Hex()))
|
panic(fmt.Sprintf("expected funded account (%s) to have erc20 balance", whale.EvmAddress.Hex()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// expect the erc20 to be enabled for conversion to sdk.Coin
|
||||||
|
params, err := suite.Kava.Evmutil.Params(context.Background(), &evmutiltypes.QueryParamsRequest{})
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("failed to fetch evmutil params during init: %s", err))
|
||||||
|
}
|
||||||
|
found := false
|
||||||
|
erc20Addr := suite.DeployedErc20.Address.Hex()
|
||||||
|
for _, p := range params.Params.EnabledConversionPairs {
|
||||||
|
if common.BytesToAddress(p.KavaERC20Address).Hex() == erc20Addr {
|
||||||
|
found = true
|
||||||
|
suite.DeployedErc20.CosmosDenom = p.Denom
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
panic(fmt.Sprintf("erc20 %s must be enabled for conversion to cosmos coin", erc20Addr))
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
|
||||||
// deploy an example contract
|
// deploy an example contract
|
||||||
greeterAddr, _, _, err := greeter.DeployGreeter(
|
greeterAddr, _, _, err := greeter.DeployGreeter(
|
||||||
whale.evmSigner.Auth,
|
whale.evmSigner.Auth,
|
||||||
@ -33,6 +61,7 @@ func (suite *E2eTestSuite) InitKavaEvmData() {
|
|||||||
suite.Kava.ContractAddrs["greeter"] = greeterAddr
|
suite.Kava.ContractAddrs["greeter"] = greeterAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FundKavaErc20Balance sends the pre-deployed ERC20 token to the `toAddress`.
|
||||||
func (suite *E2eTestSuite) FundKavaErc20Balance(toAddress common.Address, amount *big.Int) EvmTxResponse {
|
func (suite *E2eTestSuite) FundKavaErc20Balance(toAddress common.Address, amount *big.Int) EvmTxResponse {
|
||||||
// funded account should have erc20 balance
|
// funded account should have erc20 balance
|
||||||
whale := suite.Kava.GetAccount(FundedAccountName)
|
whale := suite.Kava.GetAccount(FundedAccountName)
|
||||||
@ -42,7 +71,7 @@ func (suite *E2eTestSuite) FundKavaErc20Balance(toAddress common.Address, amount
|
|||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
req := util.EvmTxRequest{
|
req := util.EvmTxRequest{
|
||||||
Tx: ethtypes.NewTransaction(nonce, suite.DeployedErc20Address, big.NewInt(0), 1e5, big.NewInt(1e10), data),
|
Tx: ethtypes.NewTransaction(nonce, suite.DeployedErc20.Address, big.NewInt(0), 1e5, big.NewInt(1e10), data),
|
||||||
Data: fmt.Sprintf("fund %s with ERC20 balance (%s)", toAddress.Hex(), amount.String()),
|
Data: fmt.Sprintf("fund %s with ERC20 balance (%s)", toAddress.Hex(), amount.String()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,20 @@ const (
|
|||||||
IbcChannel = "channel-0"
|
IbcChannel = "channel-0"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DeployedErc20 is a type that wraps the details of the pre-deployed erc20 used by the e2e test suite.
|
||||||
|
// The Address comes from SuiteConfig.KavaErc20Address
|
||||||
|
// The CosmosDenom is fetched from the EnabledConversionPairs param of x/evmutil.
|
||||||
|
// 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
|
||||||
|
// These requirements are checked in InitKavaEvmData().
|
||||||
|
type DeployedErc20 struct {
|
||||||
|
Address common.Address
|
||||||
|
CosmosDenom string
|
||||||
|
}
|
||||||
|
|
||||||
|
// E2eTestSuite is a testify test suite for running end-to-end integration tests on Kava.
|
||||||
type E2eTestSuite struct {
|
type E2eTestSuite struct {
|
||||||
suite.Suite
|
suite.Suite
|
||||||
|
|
||||||
@ -32,10 +46,12 @@ type E2eTestSuite struct {
|
|||||||
Kava *Chain
|
Kava *Chain
|
||||||
Ibc *Chain
|
Ibc *Chain
|
||||||
|
|
||||||
UpgradeHeight int64
|
UpgradeHeight int64
|
||||||
DeployedErc20Address common.Address
|
DeployedErc20 DeployedErc20
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetupSuite is run before all tests. It initializes chain connections and sets up the
|
||||||
|
// account used for funding accounts in the tests.
|
||||||
func (suite *E2eTestSuite) SetupSuite() {
|
func (suite *E2eTestSuite) SetupSuite() {
|
||||||
var err error
|
var err error
|
||||||
fmt.Println("setting up test suite.")
|
fmt.Println("setting up test suite.")
|
||||||
@ -43,25 +59,18 @@ func (suite *E2eTestSuite) SetupSuite() {
|
|||||||
|
|
||||||
suiteConfig := ParseSuiteConfig()
|
suiteConfig := ParseSuiteConfig()
|
||||||
suite.config = suiteConfig
|
suite.config = suiteConfig
|
||||||
suite.DeployedErc20Address = common.HexToAddress(suiteConfig.KavaErc20Address)
|
suite.DeployedErc20 = DeployedErc20{
|
||||||
|
Address: common.HexToAddress(suiteConfig.KavaErc20Address),
|
||||||
|
// Denom is fetched in InitKavaEvmData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup the correct NodeRunner for the given config
|
||||||
if suiteConfig.Kvtool != nil {
|
if suiteConfig.Kvtool != nil {
|
||||||
suite.UpgradeHeight = suiteConfig.Kvtool.KavaUpgradeHeight
|
suite.runner = suite.SetupKvtoolNodeRunner()
|
||||||
|
} else if suiteConfig.LiveNetwork != nil {
|
||||||
runnerConfig := runner.KvtoolRunnerConfig{
|
suite.runner = suite.SetupLiveNetworkNodeRunner()
|
||||||
KavaConfigTemplate: suiteConfig.Kvtool.KavaConfigTemplate,
|
} else {
|
||||||
|
panic("expected either kvtool or live network configs to be defined")
|
||||||
IncludeIBC: suiteConfig.IncludeIbcTests,
|
|
||||||
ImageTag: "local",
|
|
||||||
|
|
||||||
EnableAutomatedUpgrade: suiteConfig.Kvtool.IncludeAutomatedUpgrade,
|
|
||||||
KavaUpgradeName: suiteConfig.Kvtool.KavaUpgradeName,
|
|
||||||
KavaUpgradeHeight: suiteConfig.Kvtool.KavaUpgradeHeight,
|
|
||||||
KavaUpgradeBaseImageTag: suiteConfig.Kvtool.KavaUpgradeBaseImageTag,
|
|
||||||
|
|
||||||
SkipShutdown: suiteConfig.SkipShutdown,
|
|
||||||
}
|
|
||||||
suite.runner = runner.NewKvtoolRunner(runnerConfig)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chains := suite.runner.StartChains()
|
chains := suite.runner.StartChains()
|
||||||
@ -84,8 +93,13 @@ func (suite *E2eTestSuite) SetupSuite() {
|
|||||||
suite.InitKavaEvmData()
|
suite.InitKavaEvmData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TearDownSuite is run after all tests have run.
|
||||||
|
// In the event of a panic during the tests, it is run after testify recovers.
|
||||||
func (suite *E2eTestSuite) TearDownSuite() {
|
func (suite *E2eTestSuite) TearDownSuite() {
|
||||||
fmt.Println("tearing down test suite.")
|
fmt.Println("tearing down test suite.")
|
||||||
|
|
||||||
|
// 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 {
|
||||||
@ -95,12 +109,55 @@ func (suite *E2eTestSuite) TearDownSuite() {
|
|||||||
suite.runner.Shutdown()
|
suite.runner.Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetupKvtoolNodeRunner is a helper method for building a KvtoolRunnerConfig from the suite config.
|
||||||
|
func (suite *E2eTestSuite) SetupKvtoolNodeRunner() *runner.KvtoolRunner {
|
||||||
|
// upgrade tests are only supported on kvtool networks
|
||||||
|
suite.UpgradeHeight = suite.config.Kvtool.KavaUpgradeHeight
|
||||||
|
|
||||||
|
runnerConfig := runner.KvtoolRunnerConfig{
|
||||||
|
KavaConfigTemplate: suite.config.Kvtool.KavaConfigTemplate,
|
||||||
|
|
||||||
|
IncludeIBC: suite.config.IncludeIbcTests,
|
||||||
|
ImageTag: "local",
|
||||||
|
|
||||||
|
EnableAutomatedUpgrade: suite.config.Kvtool.IncludeAutomatedUpgrade,
|
||||||
|
KavaUpgradeName: suite.config.Kvtool.KavaUpgradeName,
|
||||||
|
KavaUpgradeHeight: suite.config.Kvtool.KavaUpgradeHeight,
|
||||||
|
KavaUpgradeBaseImageTag: suite.config.Kvtool.KavaUpgradeBaseImageTag,
|
||||||
|
|
||||||
|
SkipShutdown: suite.config.SkipShutdown,
|
||||||
|
}
|
||||||
|
|
||||||
|
return runner.NewKvtoolRunner(runnerConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetupLiveNetworkNodeRunner is a helper method for building a LiveNodeRunner from the suite config.
|
||||||
|
func (suite *E2eTestSuite) SetupLiveNetworkNodeRunner() *runner.LiveNodeRunner {
|
||||||
|
// live network setup doesn't presently support ibc
|
||||||
|
if suite.config.IncludeIbcTests {
|
||||||
|
panic("ibc tests not supported for live network configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
runnerConfig := runner.LiveNodeRunnerConfig{
|
||||||
|
KavaRpcUrl: suite.config.LiveNetwork.KavaRpcUrl,
|
||||||
|
KavaGrpcUrl: suite.config.LiveNetwork.KavaGrpcUrl,
|
||||||
|
KavaEvmRpcUrl: suite.config.LiveNetwork.KavaEvmRpcUrl,
|
||||||
|
}
|
||||||
|
|
||||||
|
return runner.NewLiveNodeRunner(runnerConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SkipIfIbcDisabled should be called at the start of tests that require IBC.
|
||||||
|
// It gracefully skips the current test if IBC tests are disabled.
|
||||||
func (suite *E2eTestSuite) SkipIfIbcDisabled() {
|
func (suite *E2eTestSuite) SkipIfIbcDisabled() {
|
||||||
if !suite.config.IncludeIbcTests {
|
if !suite.config.IncludeIbcTests {
|
||||||
suite.T().SkipNow()
|
suite.T().SkipNow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SkipIfUpgradeDisabled should be called at the start of tests that require automated upgrades.
|
||||||
|
// It gracefully skips the current test if upgrades are dissabled.
|
||||||
|
// Note: automated upgrade tests are currently only enabled for Kvtool suite runs.
|
||||||
func (suite *E2eTestSuite) SkipIfUpgradeDisabled() {
|
func (suite *E2eTestSuite) SkipIfUpgradeDisabled() {
|
||||||
if suite.config.Kvtool != nil && suite.config.Kvtool.IncludeAutomatedUpgrade {
|
if suite.config.Kvtool != nil && suite.config.Kvtool.IncludeAutomatedUpgrade {
|
||||||
suite.T().SkipNow()
|
suite.T().SkipNow()
|
||||||
|
Loading…
Reference in New Issue
Block a user