test(e2e): add tests for cosmos coin conversion (#1612)

* add e2e test for cosmos coin conversion

* add e2e test for eip712 signing of converts

* update kvtool
This commit is contained in:
Robert Pirtle 2023-06-05 13:22:23 -07:00 committed by GitHub
parent 528be6350e
commit a1f1f0d957
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 259 additions and 2 deletions

4
.gitignore vendored
View File

@ -37,3 +37,7 @@ build/bin
# Ignore build dirs # Ignore build dirs
build/darwin build/darwin
build/linux build/linux
# Go workspace files
go.work
go.work.sum

View File

@ -0,0 +1,244 @@
package e2e_test
import (
"context"
"math/big"
"time"
sdkerrors "cosmossdk.io/errors"
sdk "github.com/cosmos/cosmos-sdk/types"
txtypes "github.com/cosmos/cosmos-sdk/types/tx"
"github.com/ethereum/go-ethereum"
"github.com/kava-labs/kava/tests/e2e/testutil"
"github.com/kava-labs/kava/tests/util"
evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
)
func setupConvertToCoinTest(
suite *IntegrationTestSuite, accountName string,
) (denom string, initialFunds sdk.Coins, user *testutil.SigningAccount) {
// we expect a denom to be registered to the allowed denoms param
// and for the funded account to have a balance for that denom
params, err := suite.Kava.Evmutil.Params(context.Background(), &evmutiltypes.QueryParamsRequest{})
suite.NoError(err)
suite.GreaterOrEqual(
len(params.Params.AllowedCosmosDenoms), 1,
"kava chain expected to have at least one AllowedCosmosDenom for ERC20 conversion",
)
tokenInfo := params.Params.AllowedCosmosDenoms[0]
denom = tokenInfo.CosmosDenom
initialFunds = sdk.NewCoins(
sdk.NewInt64Coin(suite.Kava.StakingDenom, 1e6), // gas money
sdk.NewInt64Coin(denom, 1e10), // conversion-enabled cosmos coin
)
user = suite.Kava.NewFundedAccount(accountName, initialFunds)
return denom, initialFunds, user
}
func (suite *IntegrationTestSuite) TestConvertCosmosCoinsToFromERC20() {
denom, initialFunds, user := setupConvertToCoinTest(suite, "cosmo-coin-converter")
fee := sdk.NewCoins(ukava(7500))
convertAmount := int64(5e9)
initialModuleBalance := suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
///////////////////////////////
// CONVERT COSMOS COIN -> ERC20
///////////////////////////////
convertToErc20Msg := evmutiltypes.NewMsgConvertCosmosCoinToERC20(
user.SdkAddress.String(),
user.EvmAddress.Hex(),
sdk.NewInt64Coin(denom, convertAmount),
)
tx := util.KavaMsgRequest{
Msgs: []sdk.Msg{&convertToErc20Msg},
GasLimit: 2e6,
FeeAmount: fee,
Data: "converting sdk coin to erc20",
}
res := user.SignAndBroadcastKavaTx(tx)
suite.NoError(res.Err)
// query for the deployed contract
deployedContracts, err := suite.Kava.Evmutil.DeployedCosmosCoinContracts(
context.Background(),
&evmutiltypes.QueryDeployedCosmosCoinContractsRequest{CosmosDenoms: []string{denom}},
)
suite.NoError(err)
suite.Len(deployedContracts.DeployedCosmosCoinContracts, 1)
contractAddress := deployedContracts.DeployedCosmosCoinContracts[0].Address
// check erc20 balance
bz, err := suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
To: &contractAddress.Address,
Data: util.BuildErc20BalanceOfCallData(user.EvmAddress),
}, nil)
suite.NoError(err)
erc20Balance := new(big.Int).SetBytes(bz)
suite.BigIntsEqual(big.NewInt(convertAmount), erc20Balance, "unexpected erc20 balance post-convert")
// check cosmos coin is deducted from account
expectedFunds := initialFunds.AmountOf(denom).SubRaw(convertAmount)
balance := suite.Kava.QuerySdkForBalances(user.SdkAddress).AmountOf(denom)
suite.Equal(expectedFunds, balance)
// check that module account has sdk coins
expectedModuleBalance := initialModuleBalance.AddRaw(convertAmount)
actualModuleBalance := suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
suite.Equal(expectedModuleBalance, actualModuleBalance)
///////////////////////////////
// CONVERT ERC20 -> COSMOS COIN
///////////////////////////////
convertFromErc20Msg := evmutiltypes.NewMsgConvertCosmosCoinFromERC20(
user.EvmAddress.Hex(),
user.SdkAddress.String(),
sdk.NewInt64Coin(denom, convertAmount),
)
tx = util.KavaMsgRequest{
Msgs: []sdk.Msg{&convertFromErc20Msg},
GasLimit: 2e5,
FeeAmount: fee,
Data: "converting erc20 to cosmos coin",
}
res = user.SignAndBroadcastKavaTx(tx)
suite.NoError(res.Err)
// check erc20 balance
bz, err = suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
To: &contractAddress.Address,
Data: util.BuildErc20BalanceOfCallData(user.EvmAddress),
}, nil)
suite.NoError(err)
erc20Balance = new(big.Int).SetBytes(bz)
suite.BigIntsEqual(big.NewInt(0), erc20Balance, "expected all erc20 to be converted back")
// check cosmos coin is added back to account
expectedFunds = initialFunds.AmountOf(denom)
balance = suite.Kava.QuerySdkForBalances(user.SdkAddress).AmountOf(denom)
suite.Equal(expectedFunds, balance)
// check that module account has sdk coins deducted
actualModuleBalance = suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
suite.Equal(initialModuleBalance, actualModuleBalance)
}
// like the above, but confirming we can sign the messages with eip712
func (suite *IntegrationTestSuite) TestEIP712ConvertCosmosCoinsToFromERC20() {
denom, initialFunds, user := setupConvertToCoinTest(suite, "cosmo-coin-converter-eip712")
convertAmount := int64(5e9)
initialModuleBalance := suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
///////////////////////////////
// CONVERT COSMOS COIN -> ERC20
///////////////////////////////
convertToErc20Msg := evmutiltypes.NewMsgConvertCosmosCoinToERC20(
user.SdkAddress.String(),
user.EvmAddress.Hex(),
sdk.NewInt64Coin(denom, convertAmount),
)
tx := suite.NewEip712TxBuilder(
user,
suite.Kava,
2e6,
sdk.NewCoins(ukava(1e4)),
[]sdk.Msg{&convertToErc20Msg},
"this is a memo",
).GetTx()
txBytes, err := suite.Kava.EncodingConfig.TxConfig.TxEncoder()(tx)
suite.NoError(err)
// submit the eip712 message to the chain.
res, err := suite.Kava.Tx.BroadcastTx(context.Background(), &txtypes.BroadcastTxRequest{
TxBytes: txBytes,
Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC,
})
suite.NoError(err)
suite.Equal(sdkerrors.SuccessABCICode, res.TxResponse.Code)
_, err = util.WaitForSdkTxCommit(suite.Kava.Tx, res.TxResponse.TxHash, 6*time.Second)
suite.NoError(err)
// query for the deployed contract
deployedContracts, err := suite.Kava.Evmutil.DeployedCosmosCoinContracts(
context.Background(),
&evmutiltypes.QueryDeployedCosmosCoinContractsRequest{CosmosDenoms: []string{denom}},
)
suite.NoError(err)
suite.Len(deployedContracts.DeployedCosmosCoinContracts, 1)
contractAddress := deployedContracts.DeployedCosmosCoinContracts[0].Address
// check erc20 balance
bz, err := suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
To: &contractAddress.Address,
Data: util.BuildErc20BalanceOfCallData(user.EvmAddress),
}, nil)
suite.NoError(err)
erc20Balance := new(big.Int).SetBytes(bz)
suite.BigIntsEqual(big.NewInt(convertAmount), erc20Balance, "unexpected erc20 balance post-convert")
// check cosmos coin is deducted from account
expectedFunds := initialFunds.AmountOf(denom).SubRaw(convertAmount)
balance := suite.Kava.QuerySdkForBalances(user.SdkAddress).AmountOf(denom)
suite.Equal(expectedFunds, balance)
// check that module account has sdk coins
expectedModuleBalance := initialModuleBalance.AddRaw(convertAmount)
actualModuleBalance := suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
suite.Equal(expectedModuleBalance, actualModuleBalance)
///////////////////////////////
// CONVERT ERC20 -> COSMOS COIN
///////////////////////////////
convertFromErc20Msg := evmutiltypes.NewMsgConvertCosmosCoinFromERC20(
user.EvmAddress.Hex(),
user.SdkAddress.String(),
sdk.NewInt64Coin(denom, convertAmount),
)
tx = suite.NewEip712TxBuilder(
user,
suite.Kava,
2e5,
sdk.NewCoins(ukava(1e4)),
[]sdk.Msg{&convertFromErc20Msg},
"",
).GetTx()
txBytes, err = suite.Kava.EncodingConfig.TxConfig.TxEncoder()(tx)
suite.NoError(err)
// submit the eip712 message to the chain
res, err = suite.Kava.Tx.BroadcastTx(context.Background(), &txtypes.BroadcastTxRequest{
TxBytes: txBytes,
Mode: txtypes.BroadcastMode_BROADCAST_MODE_SYNC,
})
suite.NoError(err)
suite.Equal(sdkerrors.SuccessABCICode, res.TxResponse.Code)
_, err = util.WaitForSdkTxCommit(suite.Kava.Tx, res.TxResponse.TxHash, 6*time.Second)
suite.NoError(err)
// check erc20 balance
bz, err = suite.Kava.EvmClient.CallContract(context.Background(), ethereum.CallMsg{
To: &contractAddress.Address,
Data: util.BuildErc20BalanceOfCallData(user.EvmAddress),
}, nil)
suite.NoError(err)
erc20Balance = new(big.Int).SetBytes(bz)
suite.BigIntsEqual(big.NewInt(0), erc20Balance, "expected all erc20 to be converted back")
// check cosmos coin is added back to account
expectedFunds = initialFunds.AmountOf(denom)
balance = suite.Kava.QuerySdkForBalances(user.SdkAddress).AmountOf(denom)
suite.Equal(expectedFunds, balance)
// check that module account has sdk coins deducted
actualModuleBalance = suite.Kava.GetModuleBalances(evmutiltypes.ModuleName).AmountOf(denom)
suite.Equal(initialModuleBalance, actualModuleBalance)
}

View File

@ -5,7 +5,7 @@ import "fmt"
// TestUpgradeHandler can be used to run tests post-upgrade. If an upgrade is enabled, all tests // TestUpgradeHandler can be used to run tests post-upgrade. If an upgrade is enabled, all tests
// are run against the upgraded chain. However, this file is a good place to consolidate all // are run against the upgraded chain. However, this file is a good place to consolidate all
// acceptance tests for a given set of upgrade handlers. // acceptance tests for a given set of upgrade handlers.
func (suite IntegrationTestSuite) TestUpgradeHandler() { func (suite *IntegrationTestSuite) TestUpgradeHandler() {
suite.SkipIfUpgradeDisabled() suite.SkipIfUpgradeDisabled()
fmt.Println("An upgrade has run!") fmt.Println("An upgrade has run!")
suite.True(true) suite.True(true)

@ -1 +1 @@
Subproject commit ea6bd5386c80d372c52f0801ff91923eb0dab56f Subproject commit 98d25c9b659eaee465c72198f387268ce763400c

View File

@ -22,6 +22,7 @@ import (
"github.com/kava-labs/kava/tests/util" "github.com/kava-labs/kava/tests/util"
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"
evmutiltypes "github.com/kava-labs/kava/x/evmutil/types"
) )
// Chain wraps query clients & accounts for a network // Chain wraps query clients & accounts for a network
@ -42,6 +43,7 @@ type Chain struct {
Community communitytypes.QueryClient Community communitytypes.QueryClient
Earn earntypes.QueryClient Earn earntypes.QueryClient
Evm evmtypes.QueryClient Evm evmtypes.QueryClient
Evmutil evmutiltypes.QueryClient
Tm tmservice.ServiceClient Tm tmservice.ServiceClient
Tx txtypes.ServiceClient Tx txtypes.ServiceClient
} }
@ -75,6 +77,7 @@ func NewChain(t *testing.T, details *runner.ChainDetails, fundedAccountMnemonic
chain.Community = communitytypes.NewQueryClient(grpcConn) chain.Community = communitytypes.NewQueryClient(grpcConn)
chain.Earn = earntypes.NewQueryClient(grpcConn) chain.Earn = earntypes.NewQueryClient(grpcConn)
chain.Evm = evmtypes.NewQueryClient(grpcConn) chain.Evm = evmtypes.NewQueryClient(grpcConn)
chain.Evmutil = evmutiltypes.NewQueryClient(grpcConn)
chain.Tm = tmservice.NewServiceClient(grpcConn) chain.Tm = tmservice.NewServiceClient(grpcConn)
chain.Tx = txtypes.NewServiceClient(grpcConn) chain.Tx = txtypes.NewServiceClient(grpcConn)
@ -114,3 +117,9 @@ func (chain *Chain) QuerySdkForBalances(addr sdk.AccAddress) sdk.Coins {
require.NoError(chain.t, err) require.NoError(chain.t, err)
return res.Balances return res.Balances
} }
// GetModuleBalances returns the balance of a requested module account
func (chain *Chain) GetModuleBalances(moduleName string) sdk.Coins {
addr := authtypes.NewModuleAddress(moduleName)
return chain.QuerySdkForBalances(addr)
}